色空間の変換

目的

  • このチュートリアルでは、画像の色空間を変換する方法を学ぶ.例えばカラー空間からグレースケール空間へ変換したり、BGR空間からHSV空間へ変換したりできるようになる.
  • さらに,動画の中で特定の色を持つ物体を検出する方法も学ぶ.
  • 次の関数の使い方を学ぶ : cv2.cvtColor(), cv2.inRange().

色変換の変換

OpenCVは150種類以上の色空間の変換を用意しているが,その中で最も広く使われている変換方法は、BGR \leftrightarrow Gray変換とBGR \leftrightarrow HSV変換である。この2つを詳しく見ていく.

色変換に使う関数は cv2.cvtColor(image, flag) である.ここで imageは画像データ、flag は色変換の種類を指定するフラグである.

BGR \rightarrow Gray変換には cv2.COLOR_BGR2GRAY フラグ,BGR \rightarrow HSV変換には cv2.COLOR_BGR2HSV フラグを指定する.その他のフラグは,次のコマンドを実行すれば表示される :

>>> import cv2
>>> flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
>>> print flags

Note

HSVとは,Hueが色相,Saturation(Chroma)が彩度,Value(Lightness)が明度である.それぞれHueは[0,179], Saturationは[0,255],Valueは[0,255]の範囲の値をとるが、使用するソフトウェアによっては値の範囲が異なるので,OpenCVで得られた値と別ソフトウェアで得られた値を比較する場合は,値の正規化をしなければならない.

物体追跡

BGR画像をHSV画像へ変換する方法を学んだので,この方法を使って特定の色を持つ物体の検出ができるようになる.HSV空間では,RGB空間より色を表現するのが簡単だからである.ここでは青色をした物体の検出を試みよう.処理の流れは以下のようになる:

  • 動画のフレーム(画像)を取得
  • 画像をBGR空間からHSV空間へ色変換
  • HSV空間上で,青色に対応する領域を閾値処理により見つける
  • 青色の物体だけを検出できたので、それに対して好きな処理ができる

詳細なコメントをつけたコードを次に示す :(コード)

import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while(1):

    # 一フレーム取り出す
    _, frame = cap.read()

    # BGR空間から HSV空間に変換
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # HSV空間で青色の範囲を定義
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])

    # HSV イメージから青い物体だけを取り出すための閾値
    mask = cv2.inRange(hsv, lower_blue, upper_blue)

    # ビットごとのAND演算で元画像をマスク
    res = cv2.bitwise_and(frame,frame, mask= mask)

    cv2.imshow('frame',frame)
    cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

結果を以下に示す.:

Blue Object Tracking

Note

画像中にいくつかノイズが見えるが、このノイズの消し方は後のチュートリアルで紹介する.

Note

ここで紹介した方法は物体追跡の最も単純な方法である.輪郭処理に関する関数の使用方法を学べば,物体の重心位置を計算したり、カメラの前で手を振って図形を描くなど、いろいろな処理が行えるようになる.

追跡すべき色(HSV)を調べる方法

stackoverflow.com(技術者の質問サイト)でよく見る質問の一つがこれである.これはとても簡単で、まさに画像の色変換を行う cv2.cvtColor() 関数で実現できる。画像データを引数とする代わりに、特定の色の値(BGR値)を引数とすればよいのである。例えば,緑色に対応するHSVでの色を知りたければ,Pythonのターミナル上で次のようにコマンドを実行すればよい

>>> green = np.uint8([[[0,255,0 ]]])
>>> hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
>>> print hsv_green
[[[ 60 255 255]]]

これにより、下界と上界の値をそれぞれ [H-10, 100,100]と[H+10, 255, 255] に設定すればいいことが分かる.なおこれ以外の方法,例えばGIMPのような画像編集ソフトを使っても色相の値を調べらることができる.ただし,(前に注意したように!)OpenCVが設定している色相の範囲に正規化する必要があることをお忘れなく.

Note

このような答え方だとやはりstackoverflow.comに頼る人が出てくるだろう。HSVでは色はHueの値でほぼ決まるので、緑の場合Hue値の下限は60-10=50, 上限は60+10=70くらいとする。S値とV値は大きい方が鮮やかで明るくなり、小さいと黒くなるので、普通の色を考えているのであれば大きい値のほうがよい。その意味で[50,100,100]が下限、[70,255,255]が上限と答えているのである。なお、このサイトなどでも色を確かめることができる。

補足資料

課題

  1. 一色に限定せず、例えば赤,青,緑それぞれの色の物体を同時に検出する方法を考えてみよ.