OpenCVで人間を画像認識してみた。
1.環境
作業環境としては、いつもお世話になっているGoogle Colabratoryを今回も使う。
2.画像データ表示
書籍を参考にとりあえず画像をGoogle Colaboratoryで表示するコードを書いてみたが、
import cv2 # OpenCV
img = cv2.imread("img/img01.jpg")
cv2.imshow("img", img)
いきなりエラーが発生した。
cv2.imshowはだめだから、代わりのライブラリを使えとのこと。
DisabledFunctionError: cv2.imshow() is disabled in Colab, because it causes Jupyter sessions
to crash; see https://github.com/jupyter/notebook/issues/3935.
As a substitution, consider using
from google.colab.patches import cv2_imshow
指示に従ってコード修正すると正常に画像が表示された。☺
いきなり躓くとは思わなった。
import cv2 # OpenCV
from google.colab.patches import cv2_imshow # OpenCVの一部問題回避用
img = cv2.imread("img/img01.jpg")
cv2_imshow(img)
3.動画データ表示
次に動画データも表示できるようにしておく。
ここでも書籍を参考にしてaviデータを表示するコードを書いてみた。同じミスをしないようにcv2.imshowの代わりにcv2_imshowを使ってみた。
結果は、動画ではなく画像が連続で表示されつづけるという結果になった。さらに、Colaboratoryの切断、接続を繰り返し、暴走状態みたいになってしまった。
import cv2 # OpenCV
from google.colab.patches import cv2_imshow # OpenCVの一部問題回避用
# 動画ファイル読み込み
cap = cv2.VideoCapture("mov/mov01.avi")
# 動画出力
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
cv2_imshow(frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
調べてみると同じように困っている人は結構いるらしく、情報がたくさんあった。
下記のサイトを参考にして、OpenCVではなく、HTMLで動画表示する方式に変更した。しかしこのコードだとMP4対象だったので、事前にaviからmp4への変換も仕込んでおくと、正常に動画ウィンドウが表示されて、再生ボタンまでついてきた。
しかしOpenCVを使いたかったのにいきなりOpenCVからHTMLへ変わってしまった。
# 動画フォーマット変換
!ffmpeg -i mov/mov01.avi mov/mov01.mp4
# 動画データmp4の再生
from IPython.display import HTML # jupyter notebook内にHTMLを出力するためのモジュール
from base64 import b64encode
def show_video( video_path, video_width = 600):
video_file = open(video_path, "r+b").read()
video_url = f"data:video/mp4;base64,{b64encode(video_file).decode()}"
return HTML(f"""<video width={video_width} controls>
<source src="{video_url}">
</video>""")
show_video("mov/mov01.mp4")
4.動画データの画像ファイル化
次に動画データをフレームごとに画像ファイル化をしてみる。今度は正常に動作してくれた。
while(cap.isOpened()):
ret, frame = cap.read()
if ret:
filepath = "snapshot/snapshot_" + str(num) + ".jpg"
cv2.imwrite(filepath,frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
num = num +1
else :
break
cap.release()
cv2.destroyAllWindows()
補足VideoCaptureクラス
5. 人間検出_画像版
OpenCVのHOGDescriptorという学習済みモデルを使って画像中の人間を検出してみる。
結果はちょっとひどいが、一応動いてはいる。
import cv2
from google.colab.patches import cv2_imshow
# 人間検出モデル準備
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
hogParams = {'winStride':(8,8), 'padding':(32,32), 'scale':1.05,'hitThreshold':0,'finalThreshold':5}
# 人間検出実施
img = cv2.imread("img/img01.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # imreadの出力はBGR形式である。BGR形式→グレースケールへ変換
human, r = hog.detectMultiScale(gray, **hogParams) # 人間を検出
# 検出結果の四角を画像へ重ね書き
if (len(human)>0):
for (x, y , w, h) in human:
cv2.rectangle(img, (x,y), (x+w,y+h), (255,255,255),3)
cv2_imshow(img)
cv2.waitKey(0)
参考
http://opencv.jp/opencv-2.1/cpp/miscellaneous_image_transformations.html
6.人間の顔を検出_画像版
今度は人間の顔のみを検出する。
こんどは、OpenCVのCascadeClassifier モデルを使ってみる。
このモデル、人間の顔がどこを向いているかまで細かく設定ができる。ひとまず正面を向いている人間を検出してみると、見事に成功!!
正面ではなく多少顔を傾けている人間は検出していない。
# 検出モデル準備
cascade_file = "haarcascade_frontalface_alt.xml" # 正面を向いている顔の特徴ファイル
cascade = cv2.CascadeClassifier(cascade_file)
# 顔検出
img = cv2.imread("img/people-face.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face_list = cascade.detectMultiScale(gray, minSize=(50,50))
# 検出結果を描画
for (x, y , w, h) in face_list:
color = (0,0,255)
pen_w = 3
cv2.rectangle(img, (x,y), (x+w,y+h), color, thickness = pen_w)
cv2_imshow(img)
下記を参考にさせて頂きますた。
終わり
静止画がなんとか出来たので次は動画の人検出をしてみよう。