什麼是HSV顏色
HSV,HSL等(或在OpenCV中,HLS),是圓柱形色彩空間中的一個。
名稱是某種描述的他們的價值觀是如何引用。 (在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×3的圖像(僅適用於簡單演示的目的)與3通道,它可能是這個樣子:
# 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
值將被包括在內,並不會影響我們的面具。但是隻有S
值包括在0到50之間(朝向圓柱體的中心),並且只包括從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
值每幀。從左到右,我們有最小值到最大值,而從上到下,我們有最小值到最大值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
被使用,以證明:
你的意思是你想看到的所有顏色的曲線列入範圍?要查看上限和下限,您可以簡單地創建兩個填充了這兩種顏色的圖像,以便至少了解這些圖像的樣子。但是否則要熟悉[HSV空間中的顏色圓柱模型](https://en.wikipedia.org/wiki/HSL_and_HSV#/media/File:Hsl-hsv_models.svg)。這些邊界說「包括在220和260度之間的色調,在50和255之間的飽和度,以及在50和255之間的值(暗到振動)」。你可以想象得到這個圓柱體的大塊。 –
我想繪製範圍內的所有可能值。可能嗎? – pwan
@AlexanderReynolds你能教我如何繪製這個圓柱體並想象切割該塊體?只是更新了我的問題。 – pwan