4

我正在尝试制作一个检测红色的程序。但是有时它比平时更暗,所以我不能只使用一个值。检测不同深浅的红色的最佳范围是多少?我目前使用的范围是 128、0、0 - 255、60、60,但有时它甚至没有检测到我放在它前面的红色物体。

4

4 回答 4

14

RGB不是用于特定颜色检测的良好颜色空间。HSV将是一个不错的选择。

对于 RED,您可以选择 HSV 范围(0,50,20) ~ (5,255,255)(175,50,20)~(180,255,255)使用以下颜色图。当然,RED range不是那么精确,但还可以。

在此处输入图像描述

取自我的另一个答案的代码:检测像素是否为红色

#!/usr/bin/python3
# 2018.07.08 10:39:15 CST
# 2018.07.08 11:09:44 CST
import cv2
import numpy as np
## Read and merge
img = cv2.imread("ColorChecker.png")
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

## Gen lower mask (0-5) and upper mask (175-180) of RED
mask1 = cv2.inRange(img_hsv, (0,50,20), (5,255,255))
mask2 = cv2.inRange(img_hsv, (175,50,20), (180,255,255))

## Merge the mask and crop the red regions
mask = cv2.bitwise_or(mask1, mask2 )
croped = cv2.bitwise_and(img, img, mask=mask)

## Display
cv2.imshow("mask", mask)
cv2.imshow("croped", croped)
cv2.waitKey()

在此处输入图像描述

相关答案:

  1. 使用 cv::inRange (OpenCV) 为颜色检测选择正确的 HSV 上下边界
  2. 如何定义阈值以仅检测图像中的绿色对象:Opencv
  3. 如何在 Python-OpenCV 中使用 `cv2.inRange` 检测两种不同的颜色?
  4. 检测像素是否为红色

当然,对于具体的问题,也许其他色彩空间也可以。

如何用opencv读取公用事业表针?

于 2018-07-08T08:48:39.423 回答
2

您可以检查红色分量是否最大,而其他分量都明显较低:

def red(r, g, b):
    threshold = max(r, g, b)
    return (
        threshold > 8          # stay away from black
        and r == threshold     # red is biggest component
        and g < threshold*0.5  # green is much smaller
        and b < threshold*0.5  # so is b
    )

这可以使用 numpy 非常有效地实现。

“正确的方法”是完全转换为 HSV 并在那里检查,但它会更慢而且有点棘手(色调是一个角度,所以你不能只取差异的绝对值,而且颜色像 (255, 254 , 254) 将被限定为“红色”,即使它们被认为是人类的白色)。

另请注意,人类视觉系统倾向于补偿平均值,因此即使最大的组件确实是红色,也可以将某些东西视为“蓝色”,但图像中的所有内容都是红色的,因此对我们的大脑“不算数”。

在下图中,如果你问一个人,圆圈区域中的部分是什么颜色,大多数人会说“蓝色”,而实际上最大的部分是红色:

带红色的莲

于 2018-07-08T05:38:19.123 回答
1

hue请使用 HSV 或 HSL(色调、饱和度、亮度)而不是 RGB,在 HSV 中,可以使用某个阈值内的值轻松检测到红色。

于 2018-07-08T05:40:27.773 回答
1

红色表示红色值高于蓝色和绿色。

因此,您可以检查红色和蓝色、红色和绿色之间的差异。

您可以简单地将 RGB 拆分为单独的通道并像这样应用阈值。

b,g,r = cv2.split(img_rgb)
rg = r - g
rb = r - b
rg = np.clip(rg, 0, 255)
rb = np.clip(rb, 0, 255)

mask1 = cv2.inRange(rg, 50, 255)
mask2 = cv2.inRange(rb, 50, 255)
mask = cv2.bitwise_and(mask1, mask2)

希望它可以解决您的问题。

谢谢你。

于 2018-07-08T11:00:08.170 回答