2017/11/28 通信処理ネットワーク研究室 河田直樹
今回は Pythonで画像処理と画像認識の体験 を行う.
画像処理・画像認識をする上で便利なOpenCVを利用する.
なお,SSH接続では画像が表示されないため,ディスプレイ接続もしくはVNC接続でラズパイを操作する必要がある.
OpenCV(Open Source Computer Vision Library)とは,Intelが開発した画像処理・画像解析および機械学習等の機能を持つオープンソースのライブラリである.
Pythonではパッケージをインストールするだけで環境作りができるため,ここではその導入方法を紹介する.
ラズパイのターミナル(端末)を起動し,以下のコマンドを入力する.
約5分ほどでインストールが終わる.
$ sudo apt-get install -y python-opencv libopencv-dev
環境作りおしまい.
インストールしたOpenCVを利用して画像の入出力を行う.
ここでは例としてLenna画像(図1)を利用する.
図1
まず,使用する画像を各自で用意する.
以下の"wget"コマンドよりネットから任意データをDLすることが可能だ.
【使用例】
$ wget http://icrus.org/kawada/dsp/opencv/Lenna.jpg
テキストエディタ等で以下のサンプルプログラムを作り,Python2で実行する.
imgio.py
import cv2 img = cv2.imread("Lenna.jpg", 1) cv2.imshow("souce", img) cv2.waitKey(0)
図2のように画像が出力された.
図2
以上のように画像が表示されれば,OpenCVのインストール及びインポートは正しくできている.
import cv2 よりOpenCVモジュールを使える状態にする.
cv2.imread(ファイル名, x)で画像ファイルを行列データとして読み込む.→変数imgに保存した. 2つ目の変数では 1…カラーモード(デフォルト), 0…グレースケール, -1…アルファチャンネルも含めてそのまま読み込む, が指定できる.
cv2.imshow(ウィンドウ名,画像)で指定した画像をウィンドウ内に表示させる.
cv2.waitKey(時間)で指定した時間だけキー入力を待機する. 時間が0以下を指定した場合は無限にキー入力を待機する. それ以外は時間ミリ秒だけキー入力を待機する.
画像処理とは,画像をぼかしたり,逆に輪郭などのエッジ部分を強調したり,モザイクをかけたりといった,画像を変換して別の画像を作成する処理のことである.
ここでは画像処理のうちの一つ,エッジ抽出を例に紹介する.
使用する画像を用意する.
サンプルプログラムではLenna.jpgを使用する.
テキストエディタ等で以下のサンプルプログラムを作り,Python2で実行する.
edge.py
import cv2 img = cv2.imread("Lenna.jpg") edge_img = cv2.Canny(img, 70, 150) cv2.imshow("edge", edge_img) cv2.waitKey(0)
図3のように画像が出力された.
図3
cv2.Canny(画像,l,h)で指定した画像をキャニー法使ってエッジを検出する. エッジ勾配の大きさがhよりも大きい場合は,強い境界と判断される. hよりも小さくlよりも大きい場合も,他の強い境界に接していれば,弱い境界であっても境界と考えられる. 2つの閾値と考えてよい.
コンピュータは,「このピクセルは赤,このピクセルは青,……」ということは理解している.
だが,「この画像には人の顔が映っている」というのは理解できない.
このようにコンピュータに画像に何が映っているのかを理解させるのが,画像認識である.
今回は画像認識の例として,顔認識を体験してもらう.
あらかじめ用意された分類器を使用して顔の検出を行う.
使用する画像を用意する.
サンプルプログラムではLenna.jpgを使用する.
テキストエディタ等で以下のサンプルプログラムを作り,Python2で実行する.
detect.py
import cv2 face_cascade = cv2.CascadeClassifier("/opt/Wolfram/WolframEngine/11.3/SystemFiles/Data/Haarcascades/frontalface.xml") img = cv2.imread("Lenna.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2) cv2.imshow("detected",img) cv2.waitKey(0)
図4のように顔が赤い四角で囲われており,顔認識されたことがわかる.
図4
Haar Cascadeという物体検出の分類器の1つ.詳しくは以下のサイトで原理を解説しているので参照せよ.
【参考】https://algorithm.joho.info/machine-learning/haar-like-cascades-face-detection/
cv2.CascadeClassifier("ファイル")では使用するカスケード識別器のファイルパスを指定する.ここではラズパイで標準インストールされるWolframにある顔認識の学習データを指定する.
cv2.cvtColor(画像, 変換方法)で指定した画像の変換を行う。ここではグレースケールに変換している。 グレースケールへの変換だけなので,imreadで読み込む際にグレースケールを指定してもよい.
#gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.imread("Lenna.jpg", 0)
※「#」はコメントアウト記号
face_cascade.detectMultiScale(画像, 縮小量, 最小サイズ)では画像の中で顔を探して,その顔の位置の座標を戻す.既に学習済みの識別データに基づいて分類器を使う.
cv2.rectangle(画像, 左上座標, 右下座標, 色, 線の太さ)では指定した画像の任意の座標に四角形を描くことができる.線の太さを -1 にすると指定した色で塗りつぶされる.
OpenVCを利用せずに画像フィルタを自作する方法もある。時間があったらやってみて!
【参考】http://karaage.hatenadiary.jp/entry/2017/07/31/073000
今回の簡単な方法だとOpenCV2.4.9がインストールされる.しかし,OpenCVには3系のバージョンもあり,以下のサイトを参考にインストールできる.
【参考】https://tomosoft.jp/design/?p=7476