さて、本日は OpenCV を使って画像処理をしてみようと思います。私は最近画像を扱うことが多く、OpenCV を使ってもう少し画像関連の知識の幅を広げようと思っています。
今回のテーマは GIS とは直接は関係ないのですが、GIS の世界では航空写真など多くの画像を扱います。GIS のお仕事に興味がある方は画像の扱いにも慣れておくことをおすすめします。
画像関連のエントリーをいくつか書いていますので、興味のある方はぜひ読んでみてください。
OpenCV とは?
オープンソースのコンピュータビジョン向けのライブラリですね。要するに画像や動画用のライブラリですね。OpenCV は元々 C/C++ で使えるライブラリでしたが、Python でも動作するようになりました。ありがたい話です。
今回試すこと
まずは以下の基本的な機能を試してみたいと思います。
- 画像を読み込む
- 興味領域(ROI)の抽出
- 画像のブレンド
- 画像の重ね合わせ
- 画像から顔と目を検出
実行環境
Windows 10 64bit
Python 3.6.6
使用する画像
大田区公式PRキャラクターの「はねぴょん」の画像を使用します。
サンプルコード
画像を読み込む
# -*- coding: utf-8 -*- import cv2 def main(): img = cv2.imread(r"D:\blog\data\opencv\hane.jpg", 1) # カラーで読込 cv2.imshow("test", img) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': main()
このようにはねぴょんの画像が読み込まれたことが確認できました。
興味領域(ROI)の抽出
ROIとは、Region of Interestの略で、処理対象とする領域のことですね。以下を ROI としてみます。「ペイント」アプリを使えば ROI とする座標がわかります。
# -*- coding: utf-8 -*- import cv2 def main(): img = cv2.imread(r"D:\blog\data\opencv\hane.jpg", 1) # カラーで読込 roi = img[68:128, 35:143] # ROI領域 cv2.imwrite(r"D:\blog\data\opencv\hane_roi.jpg", roi) # 保存 if __name__ == '__main__': main()
このように ROI を抽出することができました。
画像のブレンド
以下の画像をはねぴょんの画像にブレンディングします(はねぴょんの画像の重みを0.7、上の画像の重みを0.3に設定)。
# -*- coding: utf-8 -*- import cv2 def main(): img1 = cv2.imread(r"D:\blog\data\opencv\hane.jpg") img2 = cv2.imread(r"D:\blog\data\opencv\opencv_logo.png") # 画像の大きさをあわせる img1 =cv2.resize(img1,(200,200)) img2 =cv2.resize(img2,(200,200)) img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) blended = cv2.addWeighted(src1=img1,alpha=0.7,src2=img2,beta=0.3,gamma=0) cv2.imshow("blended",blended) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': main()
このように画像がブレンドされたことがわかります。
画像の重ね合わせ
今度はブレンドではなく、画像を重ね合わせてみようと思います。
# -*- coding: utf-8 -*- import cv2 def main(): img1 = cv2.imread(r"D:\blog\data\opencv\hane.jpg") img2 = cv2.imread(r"D:\blog\data\opencv\opencv_logo.png") # 片方の画像を小さくする img2 =cv2.resize(img2,(100,100)) #img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB) #img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB) large_img = img1 small_img = img2 large_img[0:small_img.shape[0], 0:small_img.shape[1]] = small_img cv2.imshow("large_img", large_img) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': main()
このように画像が重なったことがわかります。
画像から顔と目を検出
OpenCV では顔,目,笑顔などを検出することができます(検出させるものを学習させることも可能です)。今回は顔と目を検出してみようと思いますが、はねぴょんでは検出ができないので以下の画像を使用します。
# -*- coding: utf-8 -*- import os import cv2 # OpenCVのディレクトリ opencv_path = r"C:\Python\Lib\site-packages\cv2\data" def main(): # 顔検出用データ face_cascade = cv2.CascadeClassifier(os.path.join(opencv_path, "haarcascade_frontalface_default.xml")) # 目検出用データ eye_cascade = cv2.CascadeClassifier(os.path.join(opencv_path, "haarcascade_eye.xml")) # 画像読込 img = cv2.imread(r"D:\blog\data\opencv\CR7.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 顔検出 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors = 5, minSize=(30, 30)) for (x,y,w,h) in faces: # 顔検出した部分に枠を描画 img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] # 目検出 eyes = eye_cascade.detectMultiScale(roi_gray) for (ex,ey,ew,eh) in eyes: # 目検出した部分に枠を描画 cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2) cv2.imshow("img", img) cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == '__main__': main()
このように顔と目を検出することができることがわかります。
さいごに
まだまだ OpenCV の基本機能を触れただけですが、簡単なコードで画像から顔と目を検出できたり非常に便利なライブラリということがわかりました。OpenCV はすごく多機能なライブラリのため、次回以降でもOpenCV の紹介をしていこうと思います。本日は以上です。