彩色模型
數字圖像處理中常用的採用模型是RGB(紅,綠,藍)模型和HSV(色調,飽和度,亮度),RGB廣泛應用於彩色監視器和彩色視頻攝像機,我們平時的圖片一般都是RGB模型。而HSV模型更符合人描述和解釋顏色的方式,HSV的彩色描述對人來說是自然且非常直觀的。
RGB就是指Red,Green和Blue,一副圖像由這三個channel(通道)構成;
Gray就是隻有灰度值一個channel;
HSV即Hue(色調),Saturation(飽和度)和Value(亮度)三個channel。
HSV模型
HSV模型中顏色的參數分別是:色調(H:hue),飽和度(S:saturation),亮度(V:value)。由A. R. Smith在1978年創建的一種顏色空間, 也稱六角錐體模型(Hexcone Model)。
色調(H:hue):用角度度量,取值範圍爲0°~360°,從紅色開始按逆時針方向計算,紅色爲0°,綠色爲120°,藍色爲240°。它們的補色是:黃色爲60°,青色爲180°,品紅爲300°;(OpenCV中H的取值範圍爲0~180,8bit存儲時)
飽和度(S:saturation):取值範圍爲0.0~1.0,值越大,顏色越飽和;
亮度(V:value):取值範圍爲0(黑色)~255(白色)。
BGR轉HSV
設 (r, g, b) 分別是一個顏色的紅、綠和藍座標,它們的值是在 0 到 1 之間的實數。設 max 等價於 r, g 和 b 中的最大者。設 min 等於這些值中的最小者。要找到在 HSV 空間中的 (h, s, v) 值,這裏的 h ∈ [0, 360)是角度的色相角,而 s, v ∈ [0,1] 是飽和度和亮度,計算爲:
max=max(R,G,B)
min=min(R,G,B)
if R = max:H = (G-B)/(max-min)
if G = max:H = 2 + (B-R)/(max-min)
if B = max:H = 4 + (R-G)/(max-min)
H = H * 60
if H < 0:H = H + 360
V=max(R,G,B)
S=(max-min)/max
OpenCV下有個函數可以直接將RGB模型轉換爲HSV模型,注意的是OpenCV中H∈ [0, 180), S ∈ [0, 255], V ∈ [0, 255]。我們知道H分量基本能表示一個物體的顏色,但是S和V的取值也要在一定範圍內,因爲S代表的是H所表示的那個顏色和白色的混合程度,也就說S越小,顏色越發白,也就是越淺;V代表的是H所表示的那個顏色和黑色的混合程度,也就說V越小,顏色越發黑。經過實驗,識別藍色的取值是 H在100到140,S和V都在90到255之間。一些基本的顏色H的取值可以如下設置:
Orange 0-22
Yellow 22- 38
Green 38-75
Blue 75-130
Violet 130-160
Red 160-179
Python實現
RGB在OpenCV中存儲爲BGR的順序,數據結構爲一個3D的numpy.array,索引的順序是行,列,通道:
BGRImg = cv2.imread(ImgPath)
B = BGRImg[:, :, 0]
G = BGRImg[:, :, 1]
R = BGRImg[:, :, 2]
也可以使用:
BGRImg = cv2.imread(ImgPath)
B, G, R = cv2.split(BGRImg)
注意:cv2.split的速度比直接索引要慢,但cv2.split返回的是拷貝,直接索引返回的是引用(改變B就會改變BGRImg)
轉換顏色空間:(從BGR轉換到HSV)
cv2.cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV)
HSV空間亦是如此:
HSV = cv2.cvtColor(Img, cv2.COLOR_BGR2HSV)
H, S, V = cv2.split(HSV)
顏色物體檢測
以檢測藍色物體爲例
Python代碼:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
# Take each frame
_, frame = cap.read()
# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 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)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
實驗結果如下: