【问题标题】:OpenCV - detecting color ranges and display on consoleOpenCV - 检测颜色范围并在控制台上显示
【发布时间】:2019-02-04 14:49:33
【问题描述】:

所以我有以下代码,并且在图像上显示颜色时可以正常工作。我知道它在原始图像上使用蒙版,并且只显示在声明的边界中定义的颜色。所以基本上它不会“检测”颜色,而是覆盖范围之外的所有其他内容。

用法:python code.py

您可以找到here 的示例图片

代码:

import numpy as np
import cv2
import sys

image = cv2.imread(sys.argv[1])


colors = {
    "red_lower" : "[  0   0 255]",
    "red_upper" : "[  0   0 127]",
    "blue_lower" : "[255  38   0]",
    "blue_upper" : "[255  38   0]",
    "yellow_lower" : "[  0 216 255]",
    "yellow_upper" : "[  0 216 255]",
    "gray_lower" : "[160 160 160]",
    "gray_upper" : "[160 160 160]"
}

boundaries = [
    ([0, 0, 255], [127, 0, 255]), #red
    ([255, 38, 0], [255, 38, 0]), #blue
    ([0, 216, 255], [0, 216, 255]), #yellow
    ([160, 160, 160], [160, 160, 160]) #gray
]

# loop over the boundaries
for (lower, upper) in boundaries:

    # create NumPy arrays from the boundaries
    lower = np.array(lower, dtype = np.uint8)
    upper = np.array(upper, dtype = np.uint8)

    # find the colors within the specified boundaries and apply the mask
    mask = cv2.inRange(image, lower, upper)
    output = cv2.bitwise_and(image, image, mask = mask)

    # show the images
    cv2.imshow("Climbing Holds", np.hstack([image, output]))

    cv2.waitKey(0)

在匹配其中一个边界时,我试图通过 If 语句捕捉控制台上的颜色。如果我直接与我的颜色字典进行比较,则不会按预期工作,因为所有边界都经过循环。

If 语句示例:

if str(lower) == colors["red_lower"]:
    print "red"
elif str(upper) == colors["red_upper"]:
    print "dark red"
elif str(lower) == colors["blue_lower"]:
    print "blue"
elif str(lower) == colors["yellow_lower"]:
    print "yellow"
elif str(lower) == colors["gray_lower"]:
    print "gray

我尝试通过打印掩码和输出进行调试,但这些只返回零元组:

 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]]

有谁知道如何返回掩码匹配?是否可以使用 cv2.imshow 或 cv2.read?

【问题讨论】:

    标签: python opencv colors detection cv2


    【解决方案1】:

    您可以将colorsboundaries 组合成一个对象进行迭代。无论如何,合并数据是一个好主意,因为当前的下限/上限是重复的,一次在boundaries 中,一次作为字符串在colors 值中。这种重复并不是很好,因为它可能导致细微的错误。某些值似乎已经不同步,因此将它们放在一个位置不太容易出错。

    color_boundaries = {
        "red":    ([0,   0,   255], [127, 0,   255]),
        "blue":   ([255, 38,  0],   [255, 38,  0]),
        "yellow": ([0,   216, 255], [0,   216, 255]),
        "gray":   ([160, 160, 160], [160, 160, 160])
    }
    
    for color_name, (lower, upper) in color_boundaries.items():
        # create NumPy arrays from the boundaries
        lower = np.array(lower, dtype = np.uint8)
        upper = np.array(upper, dtype = np.uint8)
    
        # find the colors within the specified boundaries and apply the mask
        mask = cv2.inRange(image, lower, upper)
        output = cv2.bitwise_and(image, image, mask = mask)
    
        if mask.any():
            print(f"{color_name}: {mask.sum()}")
    

    【讨论】:

    • 您好,感谢您的贡献。是的,这类似于我提到的使用 If 语句的尝试。问题是它总是会输出其他对象。以这个文件imgur.com/a/L1tivfV 为例,我面临的问题是确定存在哪些颜色,但由于掩码只是覆盖了所有内容,并且只显示由边界定义的颜色,所以它变得很棘手。也许 OpenCV 中还有其他一些方法可以做到这一点。
    • 您到底想打印什么?
    • 好吧,我只想打印图片上实际存在的颜色。例如上面的第二张图片,它应该只打印两个并忽略其他声明的。如果未找到边界,则不会打印。那是我的问题,是否甚至可以使用面具。
    • 是的,当然。您可以对掩码数组使用任何操作,例如 .any() 进行测试或 .sum() 进行计数。我已经用一个例子编辑了答案。
    • 效果很好,谢谢!我不知道 .any() 方法。只是为了好奇,在检测后立即打印掩码时,为什么它返回零矩阵?它不应该根据边界返回一个矩阵吗?它是 bitwise_and() 方法的属性吗?输出示例:{'yellow': 16953165} [[0 0 0 ... 0 0 0] [0 0 0 ... 0 0 0] [0 0 0 ... 0 0 0]
    猜你喜欢
    • 2014-02-27
    • 2018-01-09
    • 2017-10-14
    • 2014-06-19
    • 1970-01-01
    • 2019-05-12
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    相关资源
    最近更新 更多