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

2024-12-11 08:47:00
admin
原创
157
摘要:问题描述:我有一张咖啡罐的图片,上面有一个橙色的盖子,我想找到它的位置。就是这里。gcolor2 实用程序显示盖子中心的 HSV 为 (22, 59, 100)。那么问题是如何选择颜色的界限呢?我尝试了 min = (18, 40, 90) 和 max = (27, 255, 255),但得到了意想不到的结果...

问题描述:

我有一张咖啡罐的图片,上面有一个橙色的盖子,我想找到它的位置。就是这里图像

gcolor2 实用程序显示盖子中心的 HSV 为 (22, 59, 100)。那么问题是如何选择颜色的界限呢?我尝试了 min = (18, 40, 90) 和 max = (27, 255, 255),但得到了意想不到的结果结果

以下是 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()

解决方案 1:

问题 1:不同的应用程序对 HSV 使用不同的比例。例如,gimp 使用H = 0-360, S = 0-100 and V = 0-100。但 OpenCV 使用 H: 0-179, S: 0-255, V: 0-255。这里我在 gimp 中得到的色调值为 22。所以我取了它的一半,即 11,并为此定义了范围。即(5,50,50) - (15,255,255)

问题 2:此外,OpenCV 使用 BGR 格式,而不是 RGB。因此,请按如下方式更改将 RGB 转换为 HSV 的代码:

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

现在运行它。我得到的输出如下:

在此处输入图片描述

希望这就是你想要的。有一些误检,但它们很小,所以你可以选择最大的轮廓,也就是你的眼睑。

编辑:

正如Karl Philip在他的评论中所说,添加新代码会很好。但只有一行更改。因此,我想在新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)

它给出的结果与上面相同。但代码要简单得多。

解决方案 2:

HSV好吧,在空间中寻找颜色是一个古老但常见的问题。我做了一个hsv-colormap快速查找特殊颜色的方法。它如下:

在此处输入图片描述

x轴代表Hue在[0,180),y轴1代表Saturation在[0,255],y轴2代表S = 255,同时保持V = 255

要找到一种颜色,通常只需查找H和的范围S,并将 v 设置在范围内(20,255)。

为了找到橙色,我们查找地图,并找到最佳范围:H :[10, 25], S: [100, 255], and V: [20, 255]。因此,蒙版是cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )

然后我们使用找到的范围来寻找橙色,这是结果:

在此处输入图片描述


方法很简单,但很常用:

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

类似答案:

  1. 如何定义阈值以仅检测图像中的绿色物体:Opencv

  2. 使用 InRangeS 为 OpenCV 阈值选择正确的 HSV 值

解决方案 3:

这是一个简单的 HSV 颜色阈值脚本,用于使用轨迹栏确定磁盘上任何图像的下限/上限颜色范围。只需更改 中的图像路径即可cv2.imread()。隔离橙色的示例:

在此处输入图片描述

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 下限/上限颜色阈值范围

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

一旦确定了lowerHSVupper颜色范围,就可以像这样分割所需的颜色:

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()

解决方案 4:

我创建了这个简单的程序来实时获取 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()

解决方案 5:

为此,我使用 opencv-python 创建了一个简单(更合适)的工具。我认为它对像我今年早些时候偶然发现这里的人很有用

在此处输入图片描述

由于该工具本身是使用 python cv2 编写的,因此可以保证使用相同的范围。此外,还有一个滑块erodedilate因为通常计算机视觉项目需要这两个功能

您可以从这里克隆该工具https://github.com/hariangr/HsvRangeTool

解决方案 6:

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

在 Gimp(或其他照片处理软件)上,色调范围从 0 到 360,由于 opencv 将颜色信息放在一个字节中,单个字节中的最大数值是 255,因此 openCV 色调值相当于 gimp 的色调值除以 2。

我发现,在尝试基于 HSV 颜色空间进行对象检测时,5(opencv 范围)的范围足以过滤掉特定颜色。我建议您使用 HSV 调色板找出最适合您的应用程序的范围。

HSV 调色板,可在 HSV 空间中进行颜色检测

解决方案 7:

要查找绿色的 HSV 值,请尝试在 Python 终端中执行以下命令

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

解决方案 8:

您可以使用 GIMP 或 PaintDotNet 来获取 HSV 的精确范围。但问题是图形软件中的 HSV 范围与 OpenCV 中的相同范围不同,因此您需要一个函数来为您纠正这一点。为此,您可以使用以下函数。

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)

在此处输入图片描述

例如你可以像这样使用它:

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)

在此处输入图片描述

解决方案 9:

上面提到的大多数方法通常需要了解特定颜色的颜色范围,然后反复试验才能获得正确的范围。但 OpenCV 的官方文档提出了一种更好的方法来找到 HSV 的下限和上限,即使对于不太常见的颜色也是如此。

如何找到要跟踪的 HSV 值?

这是 stackoverflow.com 上的一个常见问题。它非常简单,您可以使用相同的函数 cv.cvtColor()。您无需传递图像,只需传递所需的 BGR 值即可。例如,要查找 Green 的 HSV 值,请在 Python 终端中尝试以下命令:

您可以找到所需对象的精确像素值(BGR)并使用它们,例如绿色(0,255,0)

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

现在,您分别将[H-10, 100,100][H+10, 255, 255]用作下限和上限。除了此方法之外,您还可以使用任何图像编辑工具(如 GIMP)或任何在线转换器来查找这些值,但不要忘记调整 HSV 范围。

来源:

OpenCV 色彩空间和对象跟踪

GIMP - 图像处理工具

解决方案 10:

我也一直在努力寻找要选择哪些 HSV 值(最终选择区域)。经过一番谷歌搜索,我编写了这个小脚本来检查图像中的 HSV 值。

它会打开您的图像(调整路径cv2.imread)。当您单击图像中感兴趣的点时,它会打印鼠标单击的位置和图像中该位置的 HSV 值。

import cv2

def on_mouse(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        print("HSV values at ({}, {}): {}".format(x, y, hsv[y, x]))

img = cv2.imread(‘path    oyourimagepiccie.png’)
cv2.namedWindow("image")
cv2.setMouseCallback("image", on_mouse)

while True:
    cv2.imshow("image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用