【问题标题】:python+opencv - How to plot hsv range?python+opencv - 如何绘制 hsv 范围?
【发布时间】:2017-07-13 02:54:16
【问题描述】:

为了提取颜色,我们有这个函数

# 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]])

【问题讨论】:

  • 您的意思是要查看包含在该范围内的所有颜色的图吗?要查看上限和下限,您可以简单地创建两个填充这两种颜色的图像,以至少查看它们的外观。但否则请熟悉cylindrical model for color in the HSV space。这些界限是说“包括 220 到 260 度之间的色调,50 到 255 之间的饱和度,以及 50 到 255 之间的值(从暗到鲜艳)”。你可以想象拿走圆柱体的那块。
  • 我想绘制范围内所有可能的值。有可能吗?
  • @AlexanderReynolds 你能教我如何绘制那个圆柱体并可视化切割那个块吗?刚刚更新了我的问题。
  • 我认为现在可能更容易做的事情是:创建一个渐变图像,从左到右s_min 到s_max,从上到下v_min 到@987654327 @,然后循环遍历每种色调以获得动画效果。我会为此做点什么,给我一点。
  • 我真的不明白这里的“范围”是什么意思?在我的情况下,110 ~ 130 度都在范围内。但是“H”和“V”呢?

标签: python opencv


【解决方案1】:

什么是 HSV 颜色

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

这个名称在某种程度上描述了它们的值是如何被引用的。

色调表示为从 0 到 360 的度数(在 OpenCV 中,为了适应 8 位无符号整数格式,它们的度数除以 2 得到一个从 0 到 179 的数字;所以 OpenCV 中的 110 是 220度)。如果您要获取色调值的“范围”,这就像从蛋糕上切下一片。你只是在吃蛋糕。

饱和度通道是你离中心的距离——你所在的半径。中心绝对没有饱和度——只有从黑色到白色的灰色。如果您采用这些值的范围,则类似于剃掉圆柱体的外部,或从中心切出一个圆。例如,如果范围是 0 到 255,那么范围 0 到 127 将是一个仅延伸到一半半径的圆柱体; 127 到 255 的范围将切割一个半径为一半的内圆柱。

价值通道是一个有点混乱的名字;它不完全是从暗到亮,因为最高值代表直接颜色,而最低值是黑色。这是圆柱体的高度。不难想象垂直切割圆柱体的一部分。

HSV 值的范围

函数cv2.inRange(image, lower_bound, upper_bound) 查找图像在lower_bound 和upper_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 每帧显示一个新的 H 值。从左到右我们有最小到最大S 值,从上到下我们有最小到最大V 值。此动画中显示的每一种颜色都将从您的图像中选择,作为您的mask 的一部分。

制作你自己的 inRange() 函数

要完全理解OpenCV函数,最简单的方法就是自己制作函数来完成任务。一点都不难,代码也不多。

该函数背后的想法很简单:找到每个通道的值在min 和max 之间的位置,然后将所有通道& 放在一起。

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,用于演示:

【讨论】:

  • 谢谢!这是一个非常深刻的解释。非常有帮助。还有 1 个愚蠢的问题,是否可以在 ipython 中内联显示它?所以我可以可视化许多范围来一次比较它们。
  • @RobAu 两种表述都是正确的;它们通常被称为cylindrical coordinates。使用圆锥或双圆锥实体,您可以获得每种颜色的单一表示的好处,而对于 HSV,例如无限数量的黑点(值 = 0,任何程度的 H 和任何饱和度 S 仍会产生黑色)。但我发现圆柱模型更容易解释;立体圆锥的 3d 截面是一种奇怪的想象。
  • @AlexanderReynolds 圆柱模型也更容易存储在数据中。但是很高兴认识到圆柱体中的所有黑点实际上都是相同的颜色,尽管它们的 H 和 S 值不同。这可能会使圆柱体中的颜色距离函数无法按预期工作。
  • @RobAu 说得好,已采纳,感谢您的意见。我知道对于v=0,h 和s 频道无关紧要;既然我们正在讨论这个问题,我意识到这意味着对于 8 位表示,您在 RGB 中有更多颜色(甚至不包括在 OpenCV 的 HSV 模型中度数增量为 2 度的事实)。
  • 上帝,你的工具太棒了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
相关资源
最近更新 更多