gpt4 book ai didi

python - python + opencv-如何绘制hsv范围?

转载 作者:太空宇宙 更新时间:2023-11-03 21:14:38 25 4
gpt4 key购买 nike

要提取颜色,我们有此功能

# define range of blue color in HSV
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])

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

我们如何实际可视化我在hsv空间上定义的范围(lower_blue,upper_blue)?
另外,我如何实际绘制hsv颜色,但不起作用...?
我有以下代码:
upper = np.array([60, 255, 255])
upper = cv2.cvtColor(upper, cv2.COLOR_HSV2BGR)


upper = totuple(upper/-255)
print(upper)
plt.imshow([[upper]])

最佳答案

什么是HSV颜色

像HSL(或OpenCV中的HLS)一样,HSV是圆柱颜色空间之一。

cylindrical colorspaces

该名称在某种程度上描述了如何引用其值。

色相表示为0到360度(在OpenCV中,为适应8位无符号整数格式,它们的度数除以2得到0到179之间的数字;因此OpenCV中的110为220度)。如果要采用“范围”的色相值,就好比从蛋糕上切下一块。您只是拿了一些蛋糕块。

饱和通道是距中心的距离-半径。中心绝对没有饱和度-只有从黑色到白色的灰色。如果您使用这些值的范围,则类似于刮除圆柱体的外部,或从中心切出一个圆圈。例如,如果范围是0到255,则范围0到127将是仅延伸到半径一半的圆柱;否则,范围将变为0。 127到255之间的范围将是切割一个半径为一半的内圆柱。

值通道是一个有点令人困惑的名称。这并不是完全由暗到亮,因为最大值代表直接颜色,而最小值代表黑色。这是圆柱体的高度。很难想象垂直切割圆柱体的一部分。

HSV值范围

函数cv2.inRange(image, lower_bound, upper_bound)lower_boundupper_bound之间找到图像的所有值。例如,如果您的图像是具有3通道的3x3图像(仅出于简单演示目的),则可能看起来像这样:

# h channel    # s channel    # v channel
100 150 250 150 150 100 50 75 225
50 100 125 75 25 50 255 100 50
0 255 125 100 200 250 50 75 100

如果我们想选择100到200之间的色相,那么我们的 lower_b应该是 [100, 0, 0],而 upper_b应该是 [200, 255, 255]。这样,我们的遮罩将仅考虑色相通道中的值,而不受饱和度和值的影响。这就是HSV如此受欢迎的原因-您可以通过色相选择颜色,而不论它们的亮度或暗度,因此只需指定色相通道的最小值和最大值即可选择深红色和亮红色。

但是说我们只想选择明亮的白色。回头看一下圆柱模型-我们看到圆柱的顶部中心处有白色,因此 s值较低,而 v值较高,并且色角无关紧要。因此, lower_b看起来像 [0, 0, 200]upper_b看起来像 [255, 50, 255]。这意味着将包括所有 H值,并且不会影响我们的遮罩。但是,将仅包含0到50之间的 S值(朝向圆柱体的中心),并且仅包括200到255之间的 V值(朝向圆柱体的顶部)。

可视化HSV中的各种颜色

可视化范围内所有颜色的一种方法是为两个通道的每个通道创建沿两个方向的长度的渐变,然后在变化的第三通道上设置动画。

例如,您可以为 S值范围创建从左到右的值渐变,为 V值范围创建从上到下的值渐变,然后循环遍历每个 H值。整个程序可能如下所示:
import numpy as np 
import cv2

lower_b = np.array([110,50,50])
upper_b = np.array([130,255,255])

s_gradient = np.ones((500,1), dtype=np.uint8)*np.linspace(lower_b[1], upper_b[1], 500, dtype=np.uint8)
v_gradient = np.rot90(np.ones((500,1), dtype=np.uint8)*np.linspace(lower_b[1], upper_b[1], 500, dtype=np.uint8))
h_array = np.arange(lower_b[0], upper_b[0]+1)

for hue in h_array:
h = hue*np.ones((500,500), dtype=np.uint8)
hsv_color = cv2.merge((h, s_gradient, v_gradient))
rgb_color = cv2.cvtColor(hsv_color, cv2.COLOR_HSV2BGR)
cv2.imshow('', rgb_color)
cv2.waitKey(250)

cv2.destroyAllWindows()

Gif of range values

现在,此gif每帧显示一个新的 H值。从左到右,我们有最小到最大 S值,从上到下,我们有最小到最大 V值。此动画中显示的每种颜色中的每一种都会从图像中选择,作为 mask的一部分。

制作自己的inRange()函数

要完全理解OpenCV功能,最简单的方法就是使自己的功能完成任务。这一点都不困难,代码也不是很多。

该函数背后的想法很简单:找到每个通道的值在 minmax之间,然后将所有通道一起 &
def inRange(img, lower_b, upper_b):
ch1, ch2, ch3 = cv2.split(img)
ch1m = (lower_b[0] <= ch1) & (ch1 <= upper_b[0])
ch2m = (lower_b[1] <= ch2) & (ch2 <= upper_b[1])
ch3m = (lower_b[2] <= ch3) & (ch3 <= upper_b[2])
mask = ch1m & ch2m & ch3m
return mask.astype(np.uint8)*255

您可以阅读 OpenCV docs来查看这确实是所使用的公式。我们也可以进行验证。
lower_b = np.array([200,200,200])
upper_b = np.array([255,255,255])

mask = cv2.inRange(img, lower_b, upper_b) # OpenCV function
mask2 = inRange(img, lower_b, upper_b) # above defined function
print((mask==mask2).all()) # checks that the masks agree on all values
# True

如何找到合适的颜色

找到用于特定图像的正确值可能有些棘手。不过,有一种简单的实验方法。您可以在OpenCV中创建跟踪栏,并使用它们来控制每个通道的最小值和最大值,并在每次更改值时让Python程序更新您的遮罩。我为此编写了一个程序,您可以在GitHub here上获取它。这是正在使用的动画 .gif,以演示:

Gif of cspaceThresh program

关于python - python + opencv-如何绘制hsv范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45070661/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com