OpenCVで特定の色を抽出するInRange関数を使ってみる

2022年5月28日土曜日

OpenCV Python

t f B! P L

この記事では、OpenCVの InRange 関数を使って、特定の色の範囲を抽出する方法を紹介する。

使用する画像

今回のサンプル画像は次のものを使用し、この画像から図形の色だけを抽出してみる。正方形の部分はグラデーションになっているが、その部分も考慮した処理にする。

enter image description here

スポンサーリンク

inRange

OpenCVで画像から特定の色の範囲を抽出する場合は、inRange 関数を使用する。この関数は、指定した色の範囲の画素を 255、それ以外の画素を0として2値化する関数である。

【使用例】

result = cv.inRange(src, lower, upper)

この関数は引数を 3つとり、1つ目は元の画像の多次元配列で、2つ目は抽出する画素の下限、3つ目は上限を指定する。戻り値には、元の画像を 255と 0で 2値化した多次元配列を返す。

inRange で色の範囲を指定する際、色の指定で一般的に用いられる RGBか、色を「色相」「彩度」「明度」の3種で指定する HSVのどちらかで指定する。

戻り値のイメージ

inRange 関数の戻り値は、元の画像を 2550 で 2値化した2次元配列となる。
例えば、5px x 7px の画像から、3 x 3 の正方形の色を抽出した場合の戻り値は次のようになる。

[[0, 0, 0, 0, 0],
 [0, 255, 255, 255, 0],
 [0, 255, 255, 255, 0],
 [0, 255, 255, 255, 0],
 [0, 0, 0, 0, 0],  
 [0, 0, 0, 0, 0],  
 [0, 0, 0, 0, 0]]

RGBで色の抽出をしてみる

RGB色指定で上のサンプル画像から、図形部分の色を抽出する。OpenCVでは、RGBはBGRの順に色を指定するので注意。

import cv2
import numpy as np
from IPython.display import Image, display

lower = np.array([200, 120, 0])           # 抽出する色の下限(BGR)
upper = np.array([255, 255 , 150])        # 抽出する色の上限(BGR)
img_mask = cv2.inRange(img, lower, upper) # inRangeで元画像を2値化

# 2値化した画像を表示
ret, encoded = cv2.imencode(".jpg", img)
display(Image(encoded))

【実行結果】
enter image description here

HSVで色の抽出をしてみる

次は、HSVで上と同じように色を抽出してみる。

HSV色空間は「色相(Hue)・彩度(Saturation)・明度(Value)」で色を表したもので、一般的に色の抽出をする場合は HSV 色空間に変換して行ったほうが選択しやすい。

OpenCVでのHSV色指定は、次の値の範囲で行う。

名前 値の範囲
色相(H) 0〜180
彩度(S) 0〜255
明度(V) 0〜255

実際に HSV色空間で上の図形の色を抽出するコードを書いてみる。


import cv2
import numpy as np
from IPython.display import Image, display

lower = np.array([70, 0 , 0])              # 抽出する色の下限(HSV)
upper = np.array([110, 255, 255])          # 抽出する色の上限(HSV)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 画像をHSV色空間に変換
img_mask = cv2.inRange(hsv, lower, upper)  # inRangeで元画像を2値化

# 2値化した画像を表示
ret, encoded = cv2.imencode(".jpg", img)
display(Image(encoded))

以下が実行結果。色指定の問題かもしれないが先ほどのRGBで抽出した物よりも、より鮮明に画像から図形の色を抽出できている。

【実行結果】
enter image description here

スポンサーリンク

まとめ

OpenCVで特定の色を抽出する方法を紹介した。

画像の2値化などは、画像認識処理における前処理で重要な部分であるため、inRange の使い方などはしっかり押さえておいた方が良さそうだ。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ