用色彩空間做圖像處理,讓顏色提取更高效

RoboMaster 技術智囊團,用簡單的方式帶你入門機器人知識,每周日準時更新。

現在,有一些機器人可以快速識別出物體的顏色,然後作出判斷和操作,比如玩魔方機器人、彩色物塊分揀機器人、水果採摘機器人......這類機器人會根據物體的顏色進行識別,最終作出準確的判斷。

彩色物塊分揀機器人

如果我們想讓機器人在一堆彩虹糖里撿出紅色的糖果,就需要讓機器人對彩虹糖的圖像進行分割,割出紅色的部分,再伸手把它撿出來。

分揀機器人

但是機器人並不像人類一樣可以看到顏色,它們只能用數字交流,在之前有關圖像二值化的文章中,我們說過,彩色圖片一般是由一個三維數組表示的。

往期回顧:《二值化圖像切割,讓機器人視覺識別變得簡單高效》

三通道彩色

同時圖片也可以看作是三層二維數組的疊加,每一層二維數組都是一個通道。單通道的圖像是灰色的,每個像素只有一個數字,數字越高,顏色越白,也就越亮。

單通道灰度

那機器人如何找到自己想要的顏色,圖像中每個像素點的數值又是如何表示出顏色的呢?

其實,在一個定義好的色彩空間里,這三個數分別代表著這個點在三個通道的數值,然後計算機再根據這些數值來確定這一個像素點的顏色。

每個不同的色彩空間都有著自己的調色盤,不同的色彩空間對於數值有著不同的規定。根據調色盤,像素在屏幕上的顯示出自己的顏色。

RGB 色彩空間

橙色的蘿蔔君其實由三個蘿蔔一起構成的——一個「紅蘿蔔」,一個「綠籮卜」,一個「藍蘿蔔」。他們的顏色深淺就決定了蘿蔔君有多紅、有多綠、有多藍,然後疊加在一起,最後,我們看到了一個橙色的蘿蔔君。這就常見的 RGB 色彩空間的工作方式。

RGB 色彩空間

RGB 是最常用於顯示器的色彩空間,R(red)是紅色通道,G(green)是綠色,B(blue)是藍色通道。這三種顏色以不同的量進行疊加,就可以顯示出五彩繽紛的色彩。

RGB 色彩空間

在 RGB 格式里(0,0,0)代表著黑色,(255,255,255)代表著白色。R 通道數值越高,說明顏色中含有的紅色分量越多;G 通道數值越高,說明顏色中含有的綠色分量越多;B 通道數值越高,說明顏色中含有的藍色分量越多。

通常,RGB 格式的圖片都是用於計算機屏幕顯示。需要注意的是,在使用 OpenCV(開源計算機視覺庫,包含了許多可用的視覺演算法,圖像處理必備神器)的時候,圖像通道的默認排序是 BGR。

現在我們以這張草莓圖片為例,用 RGB 通道提取草莓,姑且把這張圖片叫做 Strawberry。

原圖

我們使用 OpenCV 的 Split 函數,對它進行分離通道的操作,把它分別變成三張單通道的圖片。 獻上代碼君:

B, G, R = cv2.split(Strawberry)

*本文的代碼都是在 python3.6+opencv3.2+numpy 環境運行。

R 通道、G 通道、B 通道

因為單通道的圖每個像素點只有一個數值,所以處理後的圖片是灰色的。我們發現處理後的草莓在 R 通道比較亮,但是在 G 通道和 B 通道都比較黑。

這是因為草莓含的紅色比較多,所以在 R 通道中的數值比較高,數值越高也就越亮。白色花瓣在三張圖中都是白色,因為白色含的紅、綠、藍色都很多,所以不管在哪個通道,都會很亮。

在關於二值化的文章中,我們提到,閾值分割需要設定一個數值,像素值高於此值的像素點變為白色,低於此值則變為黑色。這個數值就稱為閾值。但這種方法不適用於色彩太鮮艷的圖片。

通過設定單個閾值,無法得到草莓

這時,我們可以分別設定 R、G、B 通道的像素值範圍,在圖像 Strawberry 中,範圍內的像素值會變白,不在範圍內的會變黑

例如,我們設置 R 的範圍是 100~255,G 是 0~20,B 是 0~20,這時,只有紅色含量高,藍色綠色含量低的部分才會變白,其他部分都會變黑了,草莓也就隱約可見啦。貢獻代碼君:

Strawberry=cv2.imread("strawberry.jpg")nLower = np.array([0, 0, 100])nUpper = np.array([40, 40, 255])nBinary = cv2.inRange(Strawberry, Lower, Upper)ncv2.imshow("strawberry", Binary)ncv2.waitKey(0)n

此方法得到的草莓

不過,這種方式的效果也難令人滿意,可以看到上圖中的草莓,較暗和較亮的部分並沒有被判定為紅色部分。

因為在比較暗的地方,整張圖的 RGB 的數值都很低,在比較亮的地方,數值又比較高。 RGB 三個通道的數值都很容易隨著光照的改變而改變,無法在複雜的環境中得到自己需要的特定區域。

明暗不同的畫面

所以在明暗變化比較大的地方,我們有一些更加適用於圖像處理的顏色空間——HSV 和 YUV。在介紹 HSV 和 YUV 色彩空間之前,我們先說如何轉換色彩空間。

色彩空間的轉換

當我們需要使用其他的色彩空間時,一般通過 RGB 色彩空間轉換得到。

RGB 轉換成 HSV 的轉換公式為:

從 RGB 到 HSV 轉化公式(如果得到的 H

RGB 轉換成 YUV 的轉換公式為:

轉換公式表示轉換的原理,實際使用中,我們直接用 OpenCV 視覺庫里的 cvtCOLOR()函數來做轉換:

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );

其中第一個參數是輸入圖像,第二個參數是輸出圖像,第三個參數是轉化的標識(即從什麼顏色空間轉換到什麼顏色空間),第四個參數是輸出圖片的維度(包含多少通道)。一般我們不用給出維度,默認參數為 0 時,維度是由輸入圖像和轉換的標識決定的,比如從 RGB 轉換成灰度圖,則輸出的圖像的維度是 3。

下面以葡萄的圖片為例。

原圖

我們將 src 作為輸入圖像,dst 作為輸出圖像,並將原先 RGB 通道的圖轉換成 HSV 通道的圖,則函數為:

cvtColor(src, dst, COLOR_BGR2HSV)

HSV 通道

dst 就是 src 轉化而來的 HSV 通道的圖像了,由於我們的顯示器通常是符合 RGB 色彩空間的,所以 HSV 的圖像在顯示屏中會比較奇怪。

當圖像的色彩信息對於後期工作沒有太大作用的時候,為了處理更加方便,我們也可以使用 cvtColor()函數把圖像轉換成單通道的灰度圖,只要把轉換的標識設為 COLOR_BGR2GRAY 即可。

單通道

HSV 色彩空間

在 HSV 色彩空間中 H,S,V 這三個通道分別代表著色相(Hue),飽和度(Saturation)明度(Value)

色相(Hue)

飽和度(Saturation)

明度(Value)

實際上,HSV 格式是 RGB 的一種變形。H 代表色彩,S 代表顏色的深淺,V 代表著顏色的明暗程度

HSV 顏色空間可以很好地把顏色信息和亮度信息分開,將它們放在不同的通道中,減小了光線對於特定顏色識別的影響。

在 OpenCV 視覺庫中,HSV 的數值被做了一些小的修改, H 的範圍調整為 0~180,S 和 V 的範圍為 0~255。

HSV 數值修改公式

當我們採用 HSV 的圖像閾值得到某一種顏色時,可以參考顏色分布表,先將 H 通道對應的顏色找到。表格中,每種顏色都對應了一個區間。

HSV 各顏色分布區間

假如我們要提取圖片的藍色部分,我們就在 H 通道取 100~124,S 通道取 43~255,V 通道取 35~255,範圍內的像素值變白,其餘的變黑,就可以得到很好的結果。

即使明度取值 255 也不會變為全白,因為這時,這個取值是指藍色的亮度,而不是像 RGB 一樣表示顏色。飽和度同理。

下面我們以這張蘋果的圖片為例,姑且給它取名為 Apple。

原圖

當我們想得到圖中蘋果的紅色部分時,通過以下的 python 代碼,就可以輕鬆得到:

HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #RGB 轉為 HSVnH, S, V = cv2.split(HSV) #分離 HSV 三通道nLowerred0 = np.array([155,43,35])nUpperred0 = np.array([180,255,255])nmask1 = cv2.inRange(HSV, Lowerred0, Upperred0) nLowerred1 = np.array([0,43,35])nUpperred1 = np.array([11,255,255])nmask2 = cv2.inRange(HSV, Lowerred1, Upperred1) #將紅色區域部分歸為全白,其他區域歸為全黑nApple = mask1 +mask2ncv2.imshow("apple", Apple)ncv2.waitKey(0)n

下圖為通過 HSV 三通道閾值出來的圖像 Apple。

處理後

YUV 色彩空間

YUV 色彩空間實際上是把一幅彩色的圖片分成了一個表示暗亮程度的亮度信號(Luminance)Y,和兩個表示顏色的色度信號(Chrominance)U 和 VU,V通道分別是藍色通道紅色通道Y 通道表示亮度信息

YUV 色彩空間

U 通道數值越高,顏色就越接近藍色,V 通道數值越高,顏色就越接近紅色,Y 通道數值越高,圖片則越亮。

為什麼會有這種顏色通道呢?其實這是被歐洲的電視系統採用的一種顏色編碼方式,主要是為了讓信號支持新的彩色電視,但也繼續支持黑白電視。如果是黑白電視,只使用 Y 通道信號就足夠了。

不同亮度的草莓和對應的 V 通道

從上圖我們可以看到,即使是光線發生了很大的改變,V 通道還是能很好的體現出紅色來。所以當我們要識別紅藍色物體時,使用 YUV 通道就會有較好的效果。

下面我們以莓果的圖片為例。

紅藍色的莓果

如果想要提取樹莓和藍莓,我們就分別單獨取 V、U 通道數值比較高的部分。獻上代碼君:

fruit = cv2.imread("fruits.jpg")nfruit = cv2.cvtColor(fruit,cv2.COLOR_BGR2YUV)nY,U,V = cv2.split(fruit)nBlueberry = cv2.inRange(U,130,255)nStrawberry = cv2.inRange(V,170,255)ncv2.imshow("blueberry",Blueberry)ncv2.imshow("strawberry",Strawberry)ncv2.waitKey(0)n

V 通道提取紅色

U 通道提取藍色

YUV 的計算相對簡單,圖像處理的速度很快,而且 YUV 格式對於紅、藍色都有很好的識別效果,即使光線變化,演算法也可以比較穩定。所以戶外的水果採摘機器人,一般都採用了該色彩空間來識別紅藍果實。

有時,你可能會看到 YCbCrYPbPr 等類似的名詞,其實它們都可以被稱為 YUV,區別只是適用於不同的顯示設備。在計算機上適用的一種 YUV 類型是 YCbCr,同樣 Cb 指藍色色度,Cr 指紅色色度。

YCbCr 顏色空間

其他色彩空間

除了上面三種,還有其他的色彩空間,比如 CMYK 色彩空間,LAB 色彩空間等。

CMYK 色彩空間

CMYK 色彩空間中,C(cyan)代表青色,M(magenta)代表洋紅色,Y(yellow)代表黃色,K(black)代表黑色

CMYK 色彩空間

CMYK 主要使用在印刷方面,比如噴墨印表機一般都是使用這四種顏色的墨盒。在 RGB 色彩空間里紅色,綠色和藍色疊加起來的時候是白色,但在 CMYK 色彩空間中,青色,洋紅色,黃色疊加起來是黑色。

但是實際情況中,顏色疊加起來會是褐色,所以還是會加上單獨的黑色。相比於 RGB,CMYK 更加實用於在白色的介質上列印圖像。

LAB 色彩空間

LAB 色彩空間是由 CIE(國際照明委員會)制定的一種色彩模式。自然界中任何一點色都可以在 LAB 空間中表達出來,這種模式是以數字化方式來描述人的視覺感應。

LAB 色彩空間

在 LAB 色彩空間中,L 通道範圍是 0~100,表示亮度A 通道的範圍是 -128~+127,表示從綠色到洋紅B通道的範圍是 -128~+127,表示從藍色到黃色

A,B 通道都是負值表示冷色,正值表示暖色,而對於表示亮度的 L 來說,L=100 時為白色,L=0 時為黑色。

◆◆◆

綜上,當圖像處於複雜的環境時,我們可以先觀察圖片的顏色,如果色彩比較單一,我們可以優先考慮灰度圖(比如二維碼),這樣處理更簡單速度更快。

如果要識別特定的顏色的目標(比如水果)時,我們應該優先選用 HSV,YUV 等色彩空間,因為它們將圖像的顏色與亮度分離開來,在一定程度上避免了不同強度的光照對於顏色數值的影響。

若想學習更多,可閱讀書籍:

《數字圖像處理》;作者: [美]岡薩雷斯;出版社: 電子工業出版社

本期作者

北方工業大學 吳勁松

RoboMaster2017 校機器人隊視覺組

熱愛吉他和動漫,偏文藝的非標準理工男

本文來自 RoboMaster 技術智囊團吳勁松,文章部分有修改。如果你也希望加入技術智囊團,請通過 robomaster@dji.com 聯繫我們。

往期視覺識別文章回顧:

1、無論你走到天涯海角,我都能找到你

2、機器人如何在複雜的環境下進行視覺識別?

3、二值化圖像切割,讓機器人視覺識別變得簡單高效

閱讀原文可學習往期機器人的技術文章。

weixin.qq.com/r/BUz64l7 (二維碼自動識別)

點個贊,給 RoboMaster 和機器人宣傳加油!


推薦閱讀:

1.26【OpenCV圖像處理】模板匹配
opencv Mat類型的轉換問題?
【小林的OpenCV基礎課 0】一切為了學習!

TAG:计算机视觉 | OpenCV | 图像处理 |