見出し画像

OpenCV 入門 (10) - 色の抽出

OpenCVで任意の色を抽出する処理についてまとめました。

・Python 3.7
・OpenCV 4.5

前回

1. HSV

HSV」は、色相(Hue)、彩度(Saturation)、明度(Value)の3つの成分からなる色空間です。

画像1

・色相 (H) : 色の種類(赤青緑など)
・彩度 (S) : 色の鮮やかさ。
・明度 (V) : 色の明るさ。

照明条件が変わっても色相にあまり変化が及ばないため、WEBカメラや写真から任意の色を抽出する際によく利用されます。

2. HSVの値の範囲

お絵描きソフト(PhotoShopなど)なHSV値の範囲と、OpenCVのHSV値の範囲は異なります。お絵描きソフトの色相は0〜360°ですが、OpenCV(cv2.COLOR_BGR2HSV_FULL)では0〜255になります。

画像7

・色相 : 0〜360° (赤 0〜255 赤 ※ループ)
・彩度 : 0%〜100% (白黒 0〜255 赤青緑)
・明度 : 0%〜100% (黒 0〜255 白)

3. HSVの確認

HSVの確認のため、RGB画像「sample.jpg」を準備します。

画像2

RGBをHSVに変換して確認するコードは、次のとおりです。

import cv2

# イメージの読み込み
img = cv2.imread('sample.jpg')

# HSV変換
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL)

# イメージの表示
cv2.imshow('image', img_hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()

色相は赤、彩度は緑、明るさは青で表示されます。分割しないとわかりにくいです。

画像6

4. HSVを分割して確認

HSVを分割して確認するコードは、次のとおりです。

import cv2

# イメージの読み込み
img = cv2.imread('sample.jpg')

# HSV変換
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL)
img_h, img_s, img_v = cv2.split(img_hsv);

# イメージの表示
cv2.imshow('image', img_h)
cv2.waitKey(0)
cv2.imshow('image', img_s)
cv2.waitKey(0)
cv2.imshow('image', img_v)
cv2.waitKey(0)
cv2.destroyAllWindows()

◎ 色相
「色相」を見ると、「赤」と「青」と「緑」が分離されているのがわかります。「白」と「黒」は色相がないため、赤と同じにあつかいになっています。

画像3

◎ 彩度
「彩度」を見るとは、「赤青緑」と「白黒」が分離されているのがわかります。赤青緑の濃さが彩度になります。

画像4

◎ 明度
「明度」を見ると、「明るい部分」と「暗い部分」が分離されているのがわかります。

画像5

5. 色の抽出

◎ 青色の抽出
青色を抽出するコードは、次のとおりです。

import cv2
import numpy as np

# イメージの読み込み
img = cv2.imread('sample.jpg')

# HSV変換
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL)


# 値の範囲を指定してマスク生成
img_mask = cv2.inRange(img_hsv, np.array([159, 127,0]), np.array([177, 255, 255]))

# イメージの表示
cv2.imshow('image', img_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

マスク生成する値の範囲はお絵描きソフトで値を調べ、0〜255の値に変換して、設定します。範囲内が白、範囲外が黒になります。

画像8

◎ 赤色の抽出
赤色を抽出するコードは、次のとおりです。

import cv2
import numpy as np

# イメージの読み込み
img = cv2.imread('sample.jpg')

# HSV変換
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL)

# 値の範囲を指定してマスク生成
img_mask0 = cv2.inRange(img_hsv, np.array([0, 127,0]), np.array([7, 255, 255]))
img_mask1 = cv2.inRange(img_hsv, np.array([238, 127,0]), np.array([255, 255, 255]))
img_mask = img_mask0 | img_mask1

# イメージの表示
cv2.imshow('image', img_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

赤は「0〜7」と「238〜255」に分断されてるので、マスクを2つ作って合成する必要があります。

画像9

6. 色の範囲チェックツール

色の範囲の確認はチェックツールを作ると便利です。

画像10

import cv2
import numpy as np

# 無処理
def nothing(x):
    pass

# ウィンドウの生成
cv2.namedWindow('image', cv2.WINDOW_NORMAL)

# トラックバーの生成
cv2.createTrackbar('minH', 'image', 0, 255, nothing)
cv2.createTrackbar('maxH', 'image', 255, 255, nothing)
cv2.createTrackbar('minS', 'image', 0, 255, nothing)
cv2.createTrackbar('maxS', 'image', 255, 255, nothing)
cv2.createTrackbar('minV', 'image', 0, 255, nothing)
cv2.createTrackbar('maxV', 'image', 255, 255, nothing)

# イメージの読み込み
img = cv2.imread('sample.jpg')

# HSV変換
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL)

while True:
    # トラックバーの値の取得
    minH = cv2.getTrackbarPos('minH', 'image')
    minS = cv2.getTrackbarPos('minS', 'image')
    minV = cv2.getTrackbarPos('minV', 'image')
    maxH = cv2.getTrackbarPos('maxH', 'image')
    maxS = cv2.getTrackbarPos('maxS', 'image')
    maxV = cv2.getTrackbarPos('maxV', 'image')

    # 画像の更新
    img_mask = cv2.inRange(img_hsv, np.array([minH, minS, minV]), np.array([maxH, maxS, maxV]))
    cv2.imshow('image', img_mask)

    # qキーで終了
    if cv2.waitKey(16) & 0xFF == ord('q'):
        break

# 破棄
cv2.destroyAllWindows()
【注意】 macOSのOpenCV 4.5のトラックバーの表示がイマイチ(配置順がおかしくなることがある、数値が表示されない)だったので、4.4で動作確認しました。

7. ノイズ除去

今回は、カチっとした画像なので必要ありませんが、写真やWEBカメラなどから色抽出する場合にはノイズが入るため、「中央値フィルタ」などでノイズ除去を行う必要があります。

# ノイズ除去
img_mask = cv2.medianBlur(img_mask, 5)

次回


この記事が気に入ったらサポートをしてみませんか?