简体   繁体   English

使用 cv::inRange (OpenCV) 为颜色检测选择正确的 HSV 上下边界

[英]Choosing the correct upper and lower HSV boundaries for color detection with`cv::inRange` (OpenCV)

I have an image of a coffee can with an orange lid position of which I want to find.我有一张带有橙色盖子的咖啡罐 position 的图像,我想找到它。 Here is it就这个图片. .

gcolor2 utility shows HSV at the center of the lid to be (22, 59, 100). gcolor2 实用程序显示盖子中心的 HSV 为 (22, 59, 100)。 The question is how to choose the limits of the color then?问题是如何选择颜色的界限呢? I tried min = (18, 40, 90) and max = (27, 255, 255), but have got unexpected我尝试了 min = (18, 40, 90) 和 max = (27, 255, 255),但结果出乎意料结果

Here is the Python code:这是 Python 代码:

import cv

in_image = 'kaffee.png'
out_image = 'kaffee_out.png'
out_image_thr = 'kaffee_thr.png'

ORANGE_MIN = cv.Scalar(18, 40, 90)
ORANGE_MAX = cv.Scalar(27, 255, 255)
COLOR_MIN = ORANGE_MIN
COLOR_MAX = ORANGE_MAX

def test1():
    frame = cv.LoadImage(in_image)
    frameHSV = cv.CreateImage(cv.GetSize(frame), 8, 3)
    cv.CvtColor(frame, frameHSV, cv.CV_RGB2HSV)
    frame_threshed = cv.CreateImage(cv.GetSize(frameHSV), 8, 1)
    cv.InRangeS(frameHSV, COLOR_MIN, COLOR_MAX, frame_threshed)
    cv.SaveImage(out_image_thr, frame_threshed)

if __name__ == '__main__':
    test1()

Problem 1 : Different applications use different scales for HSV.问题 1:不同的应用程序对 HSV 使用不同的尺度。 For example gimp uses H = 0-360, S = 0-100 and V = 0-100 .例如 gimp 使用H = 0-360, S = 0-100 and V = 0-100 But OpenCV uses H: 0-179, S: 0-255, V: 0-255 .但是 OpenCV 使用H: 0-179, S: 0-255, V: 0-255 Here i got a hue value of 22 in gimp.在这里,我在 gimp 中得到了 22 的色调值。 So I took half of it, 11, and defined range for that.所以我拿了一半,11,并为此定义了范围。 ie (5,50,50) - (15,255,255) .(5,50,50) - (15,255,255)

Problem 2: And also, OpenCV uses BGR format, not RGB.问题 2:此外,OpenCV 使用 BGR 格式,而不是 RGB。 So change your code which converts RGB to HSV as follows:因此,更改将 RGB 转换为 HSV 的代码,如下所示:

cv.CvtColor(frame, frameHSV, cv.CV_BGR2HSV)

Now run it.现在运行它。 I got an output as follows:我得到如下输出:

在此处输入图像描述

Hope that is what you wanted.希望那是你想要的。 There are some false detections, but they are small, so you can choose biggest contour which is your lid.有一些错误检测,但它们很小,因此您可以选择最大的轮廓,即您的盖子。

EDIT:编辑:

As Karl Philip told in his comment, it would be good to add new code.正如Karl Philip在他的评论中所说,添加新代码会很好。 But there is change of only a single line.但是只有一行的变化。 So, I would like to add the same code implemented in new cv2 module, so users can compare the easiness and flexibility of new cv2 module.所以,我想添加在新cv2模块中实现的相同代码,以便用户可以比较新cv2模块的易用性和灵活性。

import cv2
import numpy as np

img = cv2.imread('sof.jpg')

ORANGE_MIN = np.array([5, 50, 50],np.uint8)
ORANGE_MAX = np.array([15, 255, 255],np.uint8)

hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

frame_threshed = cv2.inRange(hsv_img, ORANGE_MIN, ORANGE_MAX)
cv2.imwrite('output2.jpg', frame_threshed)

It gives the same result as above.它给出了与上面相同的结果。 But code is much more simpler.但是代码要简单得多。

Ok, find color in HSV space is an old but common question.好的,在HSV空间中查找颜色是一个古老但常见的问题。 I made a hsv-colormap to fast look up special color.我制作了一个hsv-colormap来快速查找特殊颜色。 Here it is:这里是:

在此处输入图像描述

The x-axis represents Hue in [0,180), the y-axis1 represents Saturation in [0,255], the y-axis2 represents S = 255 , while keep V = 255 . x 轴表示 [0,180) 中的Hue ,y 轴 1 表示 [0,255] 中的Saturation ,y 轴 2 表示S = 255 ,同时保持V = 255

To find a color, usually just look up for the range of H and S , and set v in range(20, 255).要查找颜色,通常只需查找HS的范围,并将 v 设置在 range(20, 255) 中。

To find the orange color, we look up for the map, and find the best range: H :[10, 25], S: [100, 255], and V: [20, 255] .为了找到橙色,我们查找地图,并找到最佳范围: H :[10, 25], S: [100, 255], and V: [20, 255] So the mask is cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )所以掩码是cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )

Then we use the found range to look for the orange color, this is the result:然后我们使用找到的范围寻找橙色,结果如下:

在此处输入图像描述


The method is simple but common to use:该方法简单但常用:

#!/usr/bin/python3
# 2018.01.21 20:46:41 CST
import cv2

img = cv2.imread("test.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )
cv2.imshow("orange", mask);cv2.waitKey();cv2.destroyAllWindows()

Similar answers:类似的答案:

  1. How to define a threshold value to detect only green colour objects in an image :Opencv 如何定义阈值以仅检测图像中的绿色对象:Opencv

  2. Choosing correct HSV values for OpenCV thresholding with InRangeS 使用 InRangeS 为 OpenCV 阈值选择正确的 HSV 值

Here's a simple HSV color thresholder script to determine the lower/upper color ranges using trackbars for any image on the disk.这是一个简单的 HSV 颜色阈值脚本,用于使用磁盘上任何图像的轨迹栏来确定下/上色范围。 Simply change the image path in cv2.imread() .只需更改cv2.imread()中的图像路径。 Example to isolate orange:隔离橙色的示例:

在此处输入图像描述

import cv2
import numpy as np

def nothing(x):
    pass

# Load image
image = cv2.imread('1.jpg')

# Create a window
cv2.namedWindow('image')

# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)

# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

while(1):
    # Get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin', 'image')
    sMin = cv2.getTrackbarPos('SMin', 'image')
    vMin = cv2.getTrackbarPos('VMin', 'image')
    hMax = cv2.getTrackbarPos('HMax', 'image')
    sMax = cv2.getTrackbarPos('SMax', 'image')
    vMax = cv2.getTrackbarPos('VMax', 'image')

    # Set minimum and maximum HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Convert to HSV format and color threshold
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    result = cv2.bitwise_and(image, image, mask=mask)

    # Print if there is a change in HSV value
    if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
        print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax

    # Display result image
    cv2.imshow('image', result)
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

HSV lower/upper color threshold ranges HSV 下限/上限颜色阈值范围

(hMin = 0 , sMin = 164, vMin = 0), (hMax = 179 , sMax = 255, vMax = 255)

Once you have determined your lower and upper HSV color ranges, you can segment your desired colors like this:一旦确定了 HSV lowerupper颜色范围,您可以像这样分割所需的颜色:

import numpy as np
import cv2

image = cv2.imread('1.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 164, 0])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)

cv2.imshow('result', result)
cv2.waitKey()

I Created this simple program to get HSV Codes in realtime我创建了这个简单的程序来实时获取 HSV 代码

import cv2
import numpy as np


cap = cv2.VideoCapture(0)

def nothing(x):
    pass
# Creating a window for later use
cv2.namedWindow('result')

# Starting with 100's to prevent error while masking
h,s,v = 100,100,100

# Creating track bar
cv2.createTrackbar('h', 'result',0,179,nothing)
cv2.createTrackbar('s', 'result',0,255,nothing)
cv2.createTrackbar('v', 'result',0,255,nothing)

while(1):

    _, frame = cap.read()

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

    # get info from track bar and appy to result
    h = cv2.getTrackbarPos('h','result')
    s = cv2.getTrackbarPos('s','result')
    v = cv2.getTrackbarPos('v','result')

    # Normal masking algorithm
    lower_blue = np.array([h,s,v])
    upper_blue = np.array([180,255,255])

    mask = cv2.inRange(hsv,lower_blue, upper_blue)

    result = cv2.bitwise_and(frame,frame,mask = mask)

    cv2.imshow('result',result)

    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cap.release()

cv2.destroyAllWindows()

I created a simple (more proper) tool using opencv-python for this purpose.为此,我使用 opencv-python 创建了一个简单(更合适)的工具。 Thought it would be useful for someone stumbled here like I did earlier this year认为这对像我今年早些时候一样在这里偶然发现的人很有用

在此处输入图像描述

Since the tool itself is written using python cv2, it would be guaranteed to use the same range.由于该工具本身是使用 python cv2 编写的,因此可以保证使用相同的范围。 Also there's a slider for erode and dilate since usually computer vision project need these two feature还有一个用于erodedilate的滑块,因为通常计算机视觉项目需要这两个功能

You can clone the tool from here https://github.com/hariangr/HsvRangeTool您可以从这里克隆工具https://github.com/hariangr/HsvRangeTool

OpenCV HSV range is: H: 0 to 179 S: 0 to 255 V: 0 to 255 OpenCV HSV 范围是: H:0 到 179 S:0 到 255 V:0 到 255

On Gimp (or other photo manipulation sw) Hue range from 0 to 360, since opencv put color info in a single byte, the maximum number value in a single byte is 255 therefore openCV Hue values are equivalent to Hue values from gimp divided by 2.在 Gimp(或其他照片处理软件)上,色调范围从 0 到 360,由于 opencv 将颜色信息放在单个字节中,因此单个字节中的最大数值为 255,因此 openCV 色调值等于来自 gimp 的色调值除以 2 .

I found when trying to do object detection based on HSV color space that a range of 5 (opencv range) was sufficient to filter out a specific color.我在尝试基于 HSV 颜色空间进行对象检测时发现,5 的范围(opencv 范围)足以过滤掉特定的颜色。 I would advise you to use an HSV color palate to figure out the range that works best for your application.我建议您使用 HSV 色板来确定最适合您的应用的范围。

在 HSV 空间中进行颜色检测的 HSV 色板

To find the HSV value of Green, try following commands in Python terminal要查找 Green 的 HSV 值,请尝试在 Python 终端中执行以下命令

green = np.uint8([[[0,255,0 ]]])
hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
print hsv_green
[[[ 60 255 255]]]

You can use GIMP or PaintDotNet to get the exact range of HSV.您可以使用 GIMP 或 PaintDotNet 来获得 HSV 的确切范围。 But the problem is that the HSV range in graphics software is different from the same range in OpenCV, so you need a function to correct this for you.但问题是图形软件中的 HSV 范围与 OpenCV 中的相同范围不同,因此您需要一个函数来为您纠正这个问题。 For this purpose, you can use the following function.为此,您可以使用以下功能。

def fixHSVRange(h, s, v):
    # Normal H,S,V: (0-360,0-100%,0-100%)
    # OpenCV H,S,V: (0-180,0-255 ,0-255)
    return (180 * h / 360, 255 * s / 100, 255 * v / 100)

在此处输入图像描述

For example you can use it something like this:例如,您可以像这样使用它:

im=cv2.imread("image.jpg",1)
im_hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
color1 = fixHSVRange(h=10, s=20, v=0)
color2 = fixHSVRange(h=30, s=70, v=100)
mask = cv2.inRange(im_hsv, color1, color2)
cv2.imwrite("mask.jpg",mask)

在此处输入图像描述

Most of the methods mentioned above usually require some knowledge of the colour range for a particular colour followed by trial and error to get the right range.上面提到的大多数方法通常需要对特定颜色的颜色范围有一些了解,然后通过反复试验来获得正确的范围。 But the official documentation of OpenCV suggests a better way to find HSV lower and upper bounds even for the colours that are not very common.但是 OpenCV 的官方文档提出了一种更好的方法来找到 HSV 下限和上限,即使对于不常见的颜色也是如此。

How to find HSV values to track?如何找到要跟踪的 HSV 值?

This is a common question found in stackoverflow.com.这是在 stackoverflow.com 中发现的一个常见问题。 It is very simple and you can use the same function, cv.cvtColor().它非常简单,您可以使用相同的函数 cv.cvtColor()。 Instead of passing an image, you just pass the BGR values you want.您只需传递所需的 BGR 值,而不是传递图像。 For example, to find the HSV value of Green, try the following commands in a Python terminal:例如,要查找 Green 的 HSV 值,请在 Python 终端中尝试以下命令:

You can find the exact pixel values (BGR) of the required object and use them for example green (0, 255, 0)您可以找到所需对象的确切像素值 (BGR) 并使用它们,例如绿色 (0, 255, 0)

green = np.uint8([[[0,255,0 ]]])
hsv_green = cv.cvtColor(green,cv.COLOR_BGR2HSV)
print(hsv_green)
[[[60 255 255]]]

Now you take [H-10, 100,100] and [H+10, 255, 255] as the lower bound and upper bound respectively.现在您将[H-10, 100,100][H+10, 255, 255]分别作为下限和上限。 Apart from this method, you can use any image editing tools like GIMP or any online converters to find these values, but don't forget to adjust the HSV ranges.除了这种方法,您可以使用任何图像编辑工具,如 GIMP 或任何在线转换器来查找这些值,但不要忘记调整 HSV 范围。

Source:资源:
OpenCV Colorspaces and Object Tracking OpenCV 颜色空间和对象跟踪
GIMP - Image Manipulating Tool GIMP - 图像处理工具

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

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