代码之家  ›  专栏  ›  技术社区  ›  wasd

如何定义BGR颜色范围?将颜色代码映射到颜色名称

  •  1
  • wasd  · 技术社区  · 7 年前

    我想创建颜色映射,定义一些颜色名称和边界,这些颜色应该落在它们的范围内。例如(bgr格式)

    colors = {
        'red': ((0, 0, 255), (125, 125, 255)),
        'blue': ((255, 0, 0), (255, 125, 125)),
        'yellow' ....
    }
    

    所以如果我收到颜色,比如说(255,50,119),我可以称之为蓝色。我想至少为彩虹加上灰色,黑色,白色的颜色做这样的映射。使用python和opencv。

    问题是,我不太明白在哪里可以得到这些边界值,蓝色、红色等等是否有最低/最高的值?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Mark Setchell    7 年前

    我建议使用 单纯疱疹病毒 比较颜色的色彩空间,因为它对可变光的敏感度比 RGB ,其中日光中的绿色可能是rgb(20255,10),但阴影中的绿色可能是rgb(3,45,2),而两者的颜色非常相似。 色调 在HSV色彩空间。


    所以,开始……

    创建一个小的10x1 numpy数组,使第一个像素为红色,第二个像素为橙色,然后是黄色、绿色、蓝色、靛蓝、紫色、黑色、中灰色和白色。有张桌子 here .

    然后转换为 单纯疱疹病毒 色彩空间和注意 色调 价值观。

    我已经启动了一些代码…

    #!/usr/local/bin/python3
    import numpy as np
    import imageio
    import cv2
    
    # Create black image 10x1
    im = np.zeros([1,10,3], dtype=np.uint8)
    
    # Fill with colours of rainbow and greys
    im[0,0,:]=[255,0,0]       # red
    im[0,1,:]=[255,165,0]     # orange
    im[0,2,:]=[255,255,0]     # yellow
    im[0,3,:]=[0,255,0]       # green
    im[0,4,:]=[0,0,255]       # blue
    im[0,5,:]=[75,0,130]      # indigo
    im[0,6,:]=[238,130,238]   # violet
    im[0,7,:]=[0,0,0]         # black
    im[0,8,:]=[127,127,127]   # grey
    im[0,9,:]=[255,255,255]   # white
    imageio.imwrite("result.png",im)
    
    hsv=cv2.cvtColor(im,cv2.COLOR_RGB2HSV)
    print(hsv)
    

    检查图像:

    enter image description here

    也可以使用ImageMagick检查颜色:

    convert result.png txt:
    
    # ImageMagick pixel enumeration: 10,1,65535,srgb
    0,0: (65535,0,0)  #FF0000  red
    1,0: (65535,42405,0)  #FFA500  orange
    2,0: (65535,65535,0)  #FFFF00  yellow
    3,0: (0,65535,0)  #00FF00  lime
    4,0: (0,0,65535)  #0000FF  blue
    5,0: (19275,0,33410)  #4B0082  indigo
    6,0: (61166,33410,61166)  #EE82EE  violet
    7,0: (0,0,0)  #000000  black
    8,0: (32639,32639,32639)  #7F7F7F  grey50
    9,0: (65535,65535,65535)  #FFFFFF  white
    

    现在看看下面的hsv数组-特别是第一列( 色调 )你可以看到红色的色调是0,橙色是19,黄色是30等等。同样要注意的是,黑色、灰色和白色都没有饱和度,黑色的饱和度很低。 价值 ,灰色有中等 价值 白色有一个高 价值 .

    [[[  0 255 255]
      [ 19 255 255]
      [ 30 255 255]
      [ 60 255 255]
      [120 255 255]
      [137 255 130]
      [150 116 238]
      [  0   0   0]
      [  0   0 127]
      [  0   0 255]]]
    

    现在,您可以在python中为每种颜色创建一个数据结构来存储:

    • 最低包含色调
    • 最高包含色调
    • 名字

    因此,您可以使用:

    ... see note at bottom for Red
    14,23,"Orange"
    25,35,"Yellow"
    55,65,"Green"
    115,125,"Blue"
    ...
    

    等等——把黑、灰、白从桌子上去掉。


    那么,你怎么样 使用 这个?

    好吧,当你要检查颜色时,首先把R、G和B值转换为 单纯疱疹病毒 看看结果 饱和 -这是对色彩生动性的衡量。艳丽的色彩会有很高的饱和度,而暗淡的灰色会有很低的饱和度。

    所以,看看 饱和 大于最大可能值的10%,例如在0-255的范围内大于25。

    如果 饱和 低于限制,请检查 价值 并指定黑色if 价值 中低灰色中低白色中频 价值 很高。

    如果 饱和 高于限制,请检查是否在您记录的某一项的下限和上限内 色调 并据此命名。

    所以代码是这样的:

    def ColorNameFromRGB(R,G,B)
        # Calculate HSV from R,G,B - something like this
        # Make a single pixel from the parameters 
        onepx=np.reshape(np.array([R,G,B],dtype=np.uint8),(1,1,3))
        # Convert it to HSV
        onepxHSV=cv2.cvtColor(onepx,cv2.COLOR_RGB2HSV)
        ...
        ...
        if S<25:
            if V<85:
               return "black"
            elsif V<170:
               return "grey"
            return "white"
        # This is a saturated colour
        Iterate through colour names table and return name of entry with matching Hue
    

    有两件事需要注意:

    • 红色的色调值存在不连续性,因为hsv颜色轮是圆形的,红色的色调值为0,所以大于350和小于10的值都是红色。opencv通过除以2来缩放0-360的范围,这意味着它的结果是0-180…它整齐地放在一个无符号字节中。所以,对于红色,你需要检查色调是否大于175小于5。

    • 在查找颜色时,请务必生成8位图像,因为色调值在16位和浮动图像上的比例不同。

        2
  •  0
  •   Stefan Dragnev    7 年前

    定义两种颜色之间的距离。然后找到给定颜色的“最近”颜色名称。你将选择哪种距离的定义必须根据你的要求来确定,因为据我所知,没有“最佳”的定义。

    一种可能是RGB空间中的距离。两种颜色之间的距离可以定义为,例如,用三维空间中的向量表示的颜色之间的欧几里得(l2)距离。- distance(a,b) = (a-b).length() 或者,如果结果合理,请尝试曼哈顿(L1)度量,因为RGB空间中的欧几里得距离更像是一种启发式的度量,而不是有效的度量。

    另一种可能是先转换为HSV空间。那么最接近的颜色将是与给定颜色具有最接近色调的颜色。除非给定的颜色没有足够的饱和度,否则根据颜色的亮度,颜色可以是白色、灰色或黑色。