如何从一张图片中检测黑色和灰色

7
我正在尝试让程序检测任何黑色(和一些轻微的灰色),但目前在寻找一个好的上限色调向量(即upper_hue变量)方面遇到了困难,这将允许我提取大部分黑色色调而不提取其他颜色。它似乎可以很好地处理像黑鞋或雨伞之类的图片,但是在道路照片等亮度变化较大的情况下会出现问题。
我正在尝试找到一个良好的上限色调范围,使程序能够对此具有鲁棒性,但这可能会导致非黑色颜色的提取。

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

如果黑色和灰色的上限色调向量是一个问题,那么解决这个问题的好方法是什么?

代码:

import cv2
import numpy as np
import imutils

def color_seg(choice):
    if choice == 'blue':
        lower_hue = np.array([100,30,30])
        upper_hue = np.array([150,148,255])
    elif choice == 'white':
        lower_hue = np.array([0,0,0])
        upper_hue = np.array([0,0,255])
    elif choice == 'black':
        lower_hue = np.array([0,0,0])
        upper_hue = np.array([50,50,100])
    return lower_hue, upper_hue


# Take each frame
frame = cv2.imread('images/black0.jpg')
#frame = cv2.imread('images/road_1.jpg')

frame = imutils.resize(frame, height = 300)
chosen_color = 'black'


# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

# define range of a color in HSV
lower_hue, upper_hue = color_seg(chosen_color)


# Threshold the HSV image to get only blue colors
mask = cv2.inRange(hsv, lower_hue, upper_hue)


cv2.imshow('frame',frame)
cv2.imshow('mask',mask)

cv2.waitKey(0)

2
提示:黑色不是一种色调。只需保持低亮度、任何色调,而不要过低的饱和度。 - Miki
直方图怎么样?如果你有很多黑色和灰色,那么它们在直方图中应该是不同的。因此,尝试找到峰值或仅仅是水平,并将其用作阈值。 - Spektre
直方图听起来不错,但我正在尝试找到一个通用的上限色调范围,这样我就不必不断分析直方图并调整色调值以适应特定的图片。 - user3377126
我认为直方图只对物体图像有效,对于道路来说不太稳定,因为道路可能有许多不同的颜色,并且仅代表图像的一小部分(请参见您的最后一个示例)。 - FiReTiTi
1
你找到答案了吗?能否分享一下呢? - mrmashal
1个回答

5
在HSV颜色空间中,它非常简单。
img = cv2.imread(img_path)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_gray = np.array([0, 5, 50], np.uint8)
upper_gray = np.array([179, 50, 255], np.uint8)
mask_gray = cv2.inRange(hsv, lower_gray, upper_gray)
img_res = cv2.bitwise_and(img, img, mask = mask_gray)

H表示色相,因此灰度检测器需要所有的H值(0 -> 360°,OpenCV中用整数范围0到179来表示以适配8位)。S表示饱和度(0 -> 255)。灰阶介于0到50之间。如果我们不想保留白色值,可以将最小值设置为5。V表示亮度值(0=暗 -> 255=明)。


我的理解是,OpenCV仅使用0到179的整数表示色调,因此upper_gray的第一个值应该是179而不是360,对吗?无论如何,在这个例子中这不应该是一个问题,因为所有的色调都将被接受。 - user118967
1
更正:OpenCV仅使用0到179的整数表示色调,因此upper_gray的第一个值应为179而不是360。起初我认为这并不重要,因为使用360将选择所有色调,但由于360大于255,它需要uint8支持的8位以上。这会导致upper_gray的实际色调为360的低8位,即360-2 ^ 8 = 104。因此它并未选择所有色调。 - user118967

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接