简体   繁体   English

如何使用OpenCV查找红色的颜色区域?

[英]How to find the RED color regions using OpenCV?

I am trying to make a program where I detect red. 我正在尝试制作一个检测红色的程序。 However sometimes it is darker than usual so I can't just use one value. 但是有时它比平时更暗,所以我不能只使用一个值。 What is a good range for detecting different shades of red? 检测不同深红色的最佳范围是多少? I am currently using the range 128, 0, 0 - 255, 60, 60 but sometimes it doesn't even detect a red object I put in front of it. 我目前使用的范围是128、0、0-255、60、60,但有时甚至无法检测到放在其前面的红色物体。

RGB is not a good color space for specific color detection. 对于特定的颜色检测, RGB不是一个好的颜色空间。 HSV will be a good choice. HSV将是一个不错的选择。

For RED, you can choose the HSV range (0,50,20) ~ (5,255,255) and (175,50,20)~(180,255,255) using the following colormap. 对于RED,可以使用以下颜色图选择HSV范围(0,50,20) ~ (5,255,255)(175,50,20)~(180,255,255) Of course, the RED range is not that precise, but it is just ok. 当然, RED range不是那么精确,但是还可以。

在此处输入图片说明

The code taken from my another answer: Detect whether a pixel is red or not 来自我另一个答案的代码: 检测像素是否为红色

#!/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()

在此处输入图片说明

Related answers: 相关答案:

  1. Choosing the correct upper and lower HSV boundaries for color detection with`cv::inRange` (OpenCV) 选择正确的HSV上下边界以使用`cv :: inRange`(OpenCV)进行颜色检测
  2. How to define a threshold value to detect only green colour objects in an image :Opencv 如何定义阈值以仅检测图像中的绿色对象:Opencv
  3. How to detect two different colors using `cv2.inRange` in Python-OpenCV? 如何在Python-OpenCV中使用`cv2.inRange`检测两种不同的颜色?
  4. Detect whether a pixel is red or not 检测像素是否为红色

Of course, for the specific question, maybe other color space is also OK. 当然,对于特定的问题,也许其他颜色空间也可以。

How to read utility meter needle with opencv? 如何用opencv读取电表针?

You could check that the red component is the maximum and others are both clearly lower: 您可以检查红色部分是否最大,其他两个部分都明显更低:

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
    )

This can be implemented very efficiently using numpy. 使用numpy可以非常有效地实现这一点。

The "right way" would be doing a full conversion to HSV and check there, but it's going to be slower and somewhat trickier (hue is an angle so you cannot just take the absolute value of the difference, moreover colors like (255, 254, 254) are going to be qualified as "red" even if they're considered white for a human). “正确的方法”是将其完全转换为HSV并在那里进行检查,但是这样做会更慢且更棘手(色相是一个角度,因此您不能只取差值的绝对值,而且还喜欢(255,254) ,254)将被认定为“红色”,即使人类认为它们是白色)。

Note also that human visual system tends to compensate for average, so something could be seen as "blue" even if indeed the biggest component is red, but everything in the image is red, so that "doesn't count" for our brain. 还要注意,人的视觉系统往往会补偿平均值,因此即使最大的成分确实是红色,也可以将其视为“蓝色”,但是图像中的所有内容都是红色,因此对我们的大脑“不计数”。

In the image below if you ask a human what color is the part in the circle area most would say "blue" while indeed the biggest component is red: 在下图中,如果您问一个人,圆圈区域的部分是什么颜色,大多数人会说“蓝色”,而实际上最大的部分是红色:

略带红色的娜娜

请使用HSV或HSL(色相,饱和度,亮度)代替RGB,在HSV中,可以使用某个阈值内的hue值轻松检测红色。

Red Color means Red value is higher than Blue and Green. 红色表示红色值高于蓝色和绿色。

So you can check the differences between Red and Blue, Red and Green. 因此,您可以检查红色和蓝色,红色和绿色之间的差异。

You can simply split RGB into individual channels and apply threshold like this. 您可以简单地将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)

Hope it can be a solution for your problem. 希望它可以解决您的问题。

Thank you. 谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM