今回はpythonとOpenCVを使って画像の特定の色を抽出する方法の備忘録です。
OpenCVでは2つの方法で特定の色を抽出できるので、その2つの方法を説明していきます。
では始めます。
1:RGBでの色抽出方法
まず一つ目の方法としてRGBでの色の抽出方法があります。その方法は以下の記述でできます。
import cv2 import numpy as np image = cv2.imread('./test1.png') # ファイル読み込み # BGRでの色抽出 bgrLower = np.array([102, 255, 255]) # 抽出する色の下限(BGR) bgrUpper = np.array([102, 255, 255]) # 抽出する色の上限(BGR) img_mask = cv2.inRange(image, bgrLower, bgrUpper) # BGRからマスクを作成 result = cv2.bitwise_and(image, image, mask=img_mask) # 元画像とマスクを合成
※OpenCVでは「RGBではなくBGRになっている」ので色の順番には注意してください。
抽出する色の上限下限を作成してinRange関数でマスクを取得します。そのマスクを元画像に適応するとこで、範囲内の色以外を黒くするという方法になっています。
2:HSVでの色抽出方法
もう一つの方法としてHSVでの色の抽出方法があります。
HSVとは「色相(Hue)・彩度(Saturation)・明度(Value)」で色を表したもので、以下のリンクからRGB・HSVの変換ができます。
ちなみにOpenCVでのそれぞれの範囲は以下の通りとなっています。
名称 | 値の範囲 | 備考 |
---|---|---|
色相(H) | 0〜180 | 本来は0〜360だがOpenCVでは1/2の範囲になる |
彩度(S) | 0〜255 | 値が0に近づくほど白く、255に近づくほどHの色になる |
明度(V) | 0〜255 | 値が0に近づくほど黒く、255に近づくほどHの色になる |
そのHSVを使った色の抽出方法は以下の記述でできます。
import cv2 import numpy as np image = cv2.imread('./test1.png') # ファイル読み込み # HSVでの色抽出 hsvLower = np.array([30, 153, 255]) # 抽出する色の下限(HSV) hsvUpper = np.array([30, 153, 255]) # 抽出する色の上限(HSV) hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 画像をHSVに変換 hsv_mask = cv2.inRange(hsv, hsvLower, hsvUpper) # HSVからマスクを作成 result = cv2.bitwise_and(image, image, mask=hsv_mask) # 元画像とマスクを合成
1の手法と似ていますが、上限下限がHSVになっているのと一度画像をHSV形式に変換しているところが違っています。
3:実装例
色抽出の方法がわかったので実際に以下の画像から背景色を抽出してみたいと思います。
上記の画像を「test1.png」として保存し、同じ階層に以下のファイルを作成して実行します。
・colorExtraction.py
# # 色抽出のサンプルコード # import numpy as np import cv2 from time import sleep # メイン関数 def main(): image = cv2.imread('./test1.png') # ファイル読み込み # BGRでの色抽出 bgrLower = np.array([102, 255, 255]) # 抽出する色の下限 bgrUpper = np.array([102, 255, 255]) # 抽出する色の上限 bgrResult = bgrExtraction(image, bgrLower, bgrUpper) cv2.imshow('BGR_test1', bgrResult) sleep(1) # HSVでの色抽出 hsvLower = np.array([30, 153, 255]) # 抽出する色の下限 hsvUpper = np.array([30, 153, 255]) # 抽出する色の上限 hsvResult = hsvExtraction(image, hsvLower, hsvUpper) cv2.imshow('HSV_test1', hsvResult) sleep(1) while True: # キー入力を1ms待って、keyが「q」だったらbreak key = cv2.waitKey(1)&0xff if key == ord('q'): break cv2.destroyAllWindows() # BGRで特定の色を抽出する関数 def bgrExtraction(image, bgrLower, bgrUpper): img_mask = cv2.inRange(image, bgrLower, bgrUpper) # BGRからマスクを作成 result = cv2.bitwise_and(image, image, mask=img_mask) # 元画像とマスクを合成 return result # HSVで特定の色を抽出する関数 def hsvExtraction(image, hsvLower, hsvUpper): hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 画像をHSVに変換 hsv_mask = cv2.inRange(hsv, hsvLower, hsvUpper) # HSVからマスクを作成 result = cv2.bitwise_and(image, image, mask=hsv_mask) # 元画像とマスクを合成 return result if __name__ == '__main__': main()
すると以下のようにどちらの方法でも背景色のみが抽出できます。
以上がpythonとOpenCVで特定の色を抽出する方法です。
基本的に画像から色を抽出する時ははっきりとした色ではなくグラデーションがある場合が多いです。
どちらか一方だけではなく、画像の内容や目的によってBGRの方法とHSVの方法を使い分ける必要が出てくるかと思います。
・参考資料