Python OpenCV基於HSV的顏色分割實現示例

前言

一周沒有更新博客瞭,這一周的時間內加強瞭對機器學習和圖像處理的學習。學的有點混亂,有必要記錄一下。

深度學習可以解決很多問題,但有時候深度學習和圖像處理相結合才能有更好的效果:比如,在進行交通信號燈檢測時,用目標檢測模型確定信號燈位置後,對信號燈進行顏色分割再識別可大大提高準確率。

機器學習領域中有句話:數據和特征決定瞭模型的上限,而算法隻不過是逼近這個上限而已,所以瞭解機器學習的常用算法,熟悉機器學習中的特征工程是很有必要的。

1、什麼是HSV

我們知道RGB顏色模式,通過不同的配比可以形成不同的顏色。HSV也是一種顏色模式,其模型如圖所示

通過圖示我們也能夠看到,他和RGB顏色模型相似,也是由三個屬性決定顏色,H、S、V分別是色彩、深度、明暗,按著圖中方向的變化,其對應的顏色也會改變,三者也同樣是有取值范圍的:

  • H(色調):用角度度量,取值范圍為0°~360°
  • S(飽和度):表示顏色接近光譜色的程度。通常取值范圍為0%~100%,值越大,顏色越飽和。
  • V(明度):表示顏色明亮的程度,對於光源色,明度值與發光體的光亮度有關;對於物體色,此值和物體的透射比或反射比有關。通常取值范圍為0%(黑)到100%(白)。

HSV空間中三個指標相互獨立,能夠非常直觀的表達色彩的明暗,色調,以及鮮艷程度,方便進行顏色之間的對比,所以經常在HSV中進行顏色的分割識別。在HSV中各個顏色的范圍見下表

2、代碼實戰

從網上下載瞭一張交通信號燈的圖片,如圖

我們的目的是進行顏色分割,將我們感興趣的區域提取出來以方便下一步的操作。

2.1 createTrackbar使用方法及步驟

在開始實際操作之前,來瞭解一下createTrackbar。createTrackbar是Opencv中的API,其可在顯示圖像的窗口中快速創建一個滑動控件,用於手動調節閾值,具有非常直觀的效果。可以直接觀察閾值選擇的效果,並確定想要的閾值。

使用Trackbar我們要瞭解兩個函數;

(1)創建滑動條函數 

一個滑動條隻能用於一個參數,如果需要改變多個參數,可以使用多個滑動條。

cv2.createTrackbar(trackbarName, windowName, value, count, onChange)

各參數意義: 

trackbarName:滑動空間的名稱; 

windowName:滑動空間用於依附的圖像窗口的名稱; 

value:初始化閾值; 

count:滑動控件的刻度范圍;最小值默認為0。 

onChange:回調函數(所謂回調函數即每次修改滑動條後,需要傳入新變量的函數)的名稱,其定義如下:

onchange:void foo(int,void*)。

其中第一個參數是滑動條位置,第二個參數是用戶數據(請參見下一個參數)。如果回調是空指針,則不調用回調,但隻更新值

用戶數據:按原樣傳遞給回調的用戶數據。它可以用來處理滑動條事件而不使用全局變量。

(2)獲取滑動條的值函數

cv.getTrackbarPos獲取滑動條位置處的值

g = cv2.getTrackbarPos(trackbarName2, windowName)
#第一個參數為滑動條1的名稱,第二個參數為窗口的名稱。

註意:需要在回調函數內部采用函數cv.getTrackbarPos獲取滑動條位置處的值,不然如果存在多個滑動條時,函數無法獲取更新後的參數值。

2.2 代碼詳解

import cv2
# 滑動條的回調函數,獲取滑動條位置處的值
def empty(a):
    h_min = cv2.getTrackbarPos("Hue Min","TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
    print(h_min, h_max, s_min, s_max, v_min, v_max)
    return h_min, h_max, s_min, s_max, v_min, v_max
path = 'Resources/11.jpg'
# 創建一個窗口,放置6個滑動條
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("Hue Min","TrackBars",0,179,empty)
cv2.createTrackbar("Hue Max","TrackBars",19,179,empty)
cv2.createTrackbar("Sat Min","TrackBars",110,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",240,255,empty)
cv2.createTrackbar("Val Min","TrackBars",153,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)
while True:
    img = cv2.imread(path)
    imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    # 調用回調函數,獲取滑動條的值
    h_min,h_max,s_min,s_max,v_min,v_max = empty(0)
    lower = np.array([h_min,s_min,v_min])
    upper = np.array([h_max,s_max,v_max])
    # 獲得指定顏色范圍內的掩碼
    mask = cv2.inRange(imgHSV,lower,upper)
    # 對原圖圖像進行按位與的操作,掩碼區域保留
    imgResult = cv2.bitwise_and(img,img,mask=mask)
    cv2.imshow("Mask", mask)
    cv2.imshow("Result", imgResult)
    cv2.waitKey(1)

其實在交通信號燈檢測中,我們隻需要獲得掩碼(mask圖像)就可以進行識別瞭。

3、總結

顏色分割在很多場景都可以用到,結合深度學習會有更好的效果。後續將記錄如何進行字符分割。字符分割的應用場景和思路應用同樣廣泛,更多關於Python OpenCV HSV顏色分割的資料請關註WalkonNet其它相關文章!

推薦閱讀: