OpenCV 中的圖像處理 001_改變色彩空間

本文主要內容來自於 OpenCV-Python 教程OpenCV 中的圖像處理 部分,這個部分的主要內容如下:

這一部分無疑是 OpenCV 提供的核心能力的一部分了。

目標

  • 在這份教程中,我們將學習如何將圖像從一個色彩空間轉換到另一個。比如 BGR -> Gray,BGR -> HSV,等等。
  • 此外,我們將創建一個應用程序,從視頻中提取彩色的物品。
  • 我們將學習如下的函數:cv.cvtColor()cv.inRange() 等等。

改變色彩空間

在 OpenCV 中有超過 150 個色彩空間轉換方法可用。但我們只會深入瞭解其中的兩個,它們是最常用的:BGR -> Gray 和 BGR -> HSV。

對於色彩轉換,我們使用函數 cv.cvtColor(input_image, flag),其中的 flag 參數決定了轉換的類型。

對於 BGR -> Gray 轉換,我們使用 flag cv.COLOR_BGR2GRAY。類似地,對於 BGR -> HSV,我們使用 flag cv.COLOR_BGR2HSV。要獲得其它的 flags,可以執行如下這段代碼:

import cv2 as cv

def color_space():
    flags = [name for name in dir(cv) if name.startswith("COLOR_")]
    print("There is ", len(flags), " flags")
    flags = "\n".join(flags)
    print(flags)

OpenCV 4.5.4 版環境中執行這段代碼,輸出如下:

There is  346  flags
COLOR_BAYER_BG2BGR
COLOR_BAYER_BG2BGRA
COLOR_BAYER_BG2BGR_EA
. . . . . .

即可以執行的色彩空間轉換多達 346 種。

注意 對於 HSV,色調 (hue) 的範圍爲 [0,179],飽和度 (saturation) 的範圍爲 [0,255],明度 (value) 範圍爲 [0,255]。不同的軟件使用不同的尺度。因此,如果需要將 OpenCV 值與它們進行比較,則需要對這些範圍進行歸一化。

對象追蹤

現在我們知道如何將一幅 BGR 圖像轉換到 HSV 了,我們可以使用這種操作提取一個彩色的物體。在 HSV 中,表示彩色物體比在 BGR 色彩空間中更容易。在我們的應用程序中,我們將嘗試提取藍色物體。這是具體的方法:

  • 獲取視頻的每一幀
  • 將圖像從 BGR 轉換到 HSV 色彩空間
  • 我們將 HSV 圖像閾值設置爲藍色範圍
  • 現在單獨提取藍色物體,我們可以在該圖像上做任何我們想做的事情。

下面是詳細註釋的代碼:

def object_tracking():
    cap = cv.VideoCapture(0)

    while True:
        # Take each frame
        _, frame = cap.read()

        # Convert BGR to HSV
        hsv = cv.cvtColor(frame, cv.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 = cv.inRange(hsv, lower_blue, upper_blue)

        # Bitwise-AND mask and original image
        res = cv.bitwise_and(frame, frame, mask=mask)

        mask = cv.merge((mask, mask, mask))

        # print(frame.shape, mask.shape, res.shape)
        dest = cv.hconcat([frame, mask, res])
        cv.imshow('frame', dest)

        k = cv.waitKey(5) & 0xFF
        if k == 27:
            break

    cv.destroyAllWindows()

下圖展示了藍色物體的追蹤:

Image

注意 圖像中有一些噪聲。我們將在後面的章節中瞭解如何移除它。 這是對象追蹤中最簡單的方法。一旦我們學習了輪廓相關的函數,我們就可以做很多事情,比如找到物體的質心並用它來跟蹤物體,只需在相機前移動我們的手指就可以繪製圖表,以及其它有趣的事情。

如何找到要追蹤的 HSV 值

這是 stackoverflow.com 中的一個常見問題。它非常簡單,我們可以使用相同的函數,cv.cvtColor()。不是傳入一幅圖像,而是僅僅傳入我們需要的 BGR 值。比如,要找到藍色、綠色和紅色的 HSV 值,可以通過如下這段代碼實現:

def bgr_color_in_hsv():
    arr = np.zeros((1, 3, 3), np.uint8)
    arr[0][0] = (255, 0, 0)
    arr[0][1] = (0, 255, 0)
    arr[0][2] = (0, 0, 255)
    hsv = cv.cvtColor(arr, cv.COLOR_BGR2HSV)
    print("Blue HSV: ", hsv[0][0])
    print("Green HSV: ", hsv[0][1])
    print("Red HSV: ", hsv[0][2])

上面這段代碼的輸出如下:

Blue HSV:  [120 255 255]
Green HSV:  [ 60 255 255]
Red HSV:  [  0 255 255]

要探測藍色之外的其它顏色的物體,只需要將上面那段代碼中,cv.inRange(hsv, lower_blue, upper_blue) 的參數修改爲目標顏色的範圍即可。比如將 [H-10, 100,100] 和 [H+10, 255, 255] 分別作爲下限和上限,可以追蹤紅色物體。除了這種方法,還可以使用任何圖像編輯工具,如 GIMP 或任何在線轉換器來查找這些值,但不要忘記調整 HSV 範圍。

其它資源

練習

  1. 嘗試找到一種方法來提取多個彩色對象,例如同時提取紅色、藍色和綠色對象。

這裏給出一個參考實現。這段代碼分別將各個顏色的物體提取出來,然後再將各個物體的圖像相加,得到最終需要的圖像:

def multi_objects_tracking():
    cap = cv.VideoCapture(0)

    while True:
        # Take each frame
        _, frame = cap.read()

        # Convert BGR to HSV
        hsv = cv.cvtColor(frame, cv.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_blue = cv.inRange(hsv, lower_blue, upper_blue)

        # Bitwise-AND mask and original image
        blue_res = cv.bitwise_and(frame, frame, mask=mask_blue)

        # define range of green color in HSV
        lower_green = np.array([50, 50, 50])
        upper_green = np.array([70, 255, 255])

        # Threshold the HSV image to get only blue colors
        mask_green = cv.inRange(hsv, lower_green, upper_green)

        # Bitwise-AND mask and original image
        green_res = cv.bitwise_and(frame, frame, mask=mask_green)

        # define range of red color in HSV
        lower_red = np.array([0, 50, 50])
        upper_red  = np.array([0, 255, 255])

        # Threshold the HSV image to get only blue colors
        mask_red = cv.inRange(hsv, lower_red, upper_red)

        # Bitwise-AND mask and original image
        red_res = cv.bitwise_and(frame, frame, mask=mask_red)

        res = cv.add(blue_res, green_res)
        res = cv.add(res, red_res)

        dest = cv.hconcat([frame, res])
        cv.imshow('frame', dest)

        k = cv.waitKey(5) & 0xFF
        if k == 27:
            break

    cv.destroyAllWindows()

結果將類似於下面這樣:

Image

參考文檔

Changing Colorspaces

Done.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章