OpenCV-色彩空間
- 2019 年 11 月 13 日
- 筆記
本小節主要介紹色彩空間的一些概念,並使用OpenCV進行色彩空間的轉換,並通過通過色彩空間的轉換提取影片中的指定顏色。
01
什麼是色彩空間
顏色通常是由三個獨立的屬性來描述的,比如我們熟悉的RGB,任意色光都可以通過R(紅色)、G(綠色)以及B(藍色)相加混合而成,這也是我們常說的三個通道。每一個通道像素值都是0-255,我們可以把三個通道看成是坐標系中的三個軸,由於R、G以及B中取值都是0-255的範圍,因此RGB組合表示的顏色可以構成一個包含256*256*256個元素的立方體,其中每一個元素都對用著RGB三個通道的不同取值(你可以簡單將元素看成是一個(R值, G值, B值)空間中的一點),如下圖所示:

可以看出當三個通道即R = 0,G = 0,B = 0混合後的顏色為黑色,同理如果R = 255,G = 255,B = 255混合的話顏色為白色。 此時坐標軸為0-1,這是因為在電腦中1個位元組表示8位,2的8次方為256,因此使用1個位元組就可以表示0-255之間的任意數,所以在上面圖中使用0-1的坐標軸來進行標示。
將下面RGB圖分裂成三個通道,R通道,G通道,B通道,原始圖片如下:

分割成三個通道即B,G,R:

我們期望大的結果是紅紅的綠綠的藍藍的三張圖片,但是顯示的結果並不是我們所期望的那樣:

其實原因就在於,分割通道後的圖片,僅包含長度和寬度,此時使用imshow函數,可以為其自動加上第三個維度也就是通道數,但是此時的通道數為1,(可以通過將分割後的圖片reshape()來對比,得到的結果一致)。單通道俗稱灰度圖,每個像素點只能有一個值表示顏色,它的像素值在0到255之間,0是黑色,255是白色,中間值是一些不同等級的灰色,可以說灰度是黑與白之間的過渡色。這就是問題的根源所在。如果解決呢?其實也很簡單,我們只需要加上兩個通道,但是直接reshape肯定不行,因此我們需要創建兩個0矩陣然後拼接在分割的單通道圖片上,手動組成三通道,也就是組成(B,0,0),(G,0,0),(R,0,0)。具體程式碼如下:


執行效果:


色彩空間有很多,比如gray、hsv、yuv、ycrcb等,使用OpenCV進行色彩空間的轉換很簡單。

執行效果:

其中HSV是比較常用的,下面主要介紹一下HSV色彩空間。
02
HSV色彩空間
HSV是一種將RGB色彩空間中的點在倒圓錐體中的表示方法。HSV即色相(Hue)、飽和度(Saturation)、明度(Value),又稱HSB(B即Brightness)。色相是色彩的基本屬性,就是平常說的顏色的名稱,如紅色、黃色等。飽和度(S)是指色彩的純度,越高色彩越純,低則逐漸變灰,取0-100%的數值。明度(V),取0-max(電腦中HSV取值範圍和存儲的長度有關)。HSV顏色空間可以用一個圓錐空間模型來描述。圓錐的頂點處,V=0,H和S無定義,代表黑色。圓錐的頂面中心處V=max,S=0,H無定義,代表白色。

RGB顏色空間中,三種顏色分量的取值與所生成的顏色之間的聯繫並不直觀。而HSV顏色空間,更類似於人類感覺顏色的方式,封裝了關於顏色的資訊:「這是什麼顏色?深淺如何?明暗如何?」。我們可以將圖片或者影片轉換為HSV色彩空間,然後通過其中過濾像素的區間範圍來過濾出特定的顏色,下標就是HSV色彩空間中對應顏色的取值範圍:

實際上H真實取值是0-360的,但是在OpenCV中取值為0-180。其實有一個歸一化問題,因為其他兩個通道都是255,如果用uint8,一個位元組就可以表示,當0-360的時候超出了1個位元組,此時uint8表示不了,會溢出,此時OpenCV為了解決這個問題,將H通道歸一化到0-180之間,雖然把尺度空間變小了,但是unit8可以存了。
03
使用HSV檢測影片指定顏色
如何應用HSV來過濾出特定的顏呢?本地影片文件名稱"love.avi"。

影片就不在展示了,原始影片的起始頁面:

轉換HSV色彩空間之後提取白色生成的二值圖片,mask中的白色為想要提取指定顏色的位置,黑色為其餘位置。
