ラズパイで物体認識シリーズ HaarCascades を使った物体検出
OpenCV単体でできる物体検出を試してみます
【ラズパイで物体認識シリーズ】
・OpenCV の準備
・HaarCascades を使った物体検出 ←イマココ
・YOLO v5のセットアップ
・Xi IoTへの組み込み ちょっと延期
カメラの映像に文字を入れてみる
これはいたって簡単です
取り込んだカメラフレーム(ret, frame = cap.read())と表示(cv.imshow('OpenCV - test', frame))の間に”cv.putText()”をつっこみます
# ビデオ上にテキストを表示 (カメラデータ, 文字, (表示位置), フォント, フォントサイズ, 色, 太さ, 線の種類) cv.putText(frame, 'mokemoke', (200,50), cv.FONT_HERSHEY_PLAIN, 3, (0, 255,0), 3, cv.LINE_AA)
前回のコードと組み合わせるとこんな感じに
import cv2 as cv #カメラインスタンス作成 cap = cv.VideoCapture(0) try: while True: ret, frame = cap.read() if frame is None: print('--(!) No captured frame -- Break!') break # ビデオ上にテキストを表示 (カメラデータ, 文字, (表示位置), フォント, フォントサイズ, 色, 太さ, 線の種類) cv.putText(frame, 'mokemoke', (200,50), cv.FONT_HERSHEY_PLAIN, 3, (0, 255,0), 3, cv.LINE_AA) cv.imshow('OpenCV - test', frame) if cv.waitKey(10) == 27: break except KeyboardInterrupt: # except the program gets interrupted by Ctrl+C on the keyboard. print("\nCamera Interrupt") finally: cap.release() cv.destroyAllWindows()
mokemokeしました
OpenCVで顔検出
OpenCVでは、あらかじめ Haar-like特徴を用いた分類器 (haarcascade~.xml)という物体検出用の学習済みデータが用意されています
OpenCVのGithubから入手できます
opencv/data at master · opencv/opencv · GitHub
ファイル名 | 対象物体 |
---|---|
haarcascade_eye.xml | 目 |
haarcascade_eye_tree_eyeglasses.xml | メガネ |
haarcascade_frontalcatface.xml | 猫の顔(正面) |
haarcascade_frontalcatface_extended.xml | 猫の顔(正面) |
haarcascade_frontalface_alt.xml | 顔(正面) |
haarcascade_frontalface_alt2.xml | 顔(正面) |
haarcascade_frontalface_alt_tree.xml | 顔(正面) |
haarcascade_frontalface_default.xml | 顔(正面) |
haarcascade_fullbody.xml | 全身 |
haarcascade_lefteye_2spits.xml | 左目 |
haarcascade_licence_plate_rus_16stages.xml | ロシアのナンバープレート(全体) |
haarcascade_lowerbody.xml | 下半身 |
haarcascade_profileface.xml | 顔(証明写真) |
haarcascade_righteye_2splits.xml | 右目 |
haarcascade_russian_plate_number.xml | 笑顔 |
haarcascade_upperbody.xml | 上半身 |
これを使って人間の顔検出を実装してみます
チュートリアルを参照しながら、すすめていきましょう
OpenCV: Cascade Classifier
ポイントその1.顔検出データ(haarcascade_frontalface_default.xml)の読み込み
# ファイルパスの指定 face_cascade_name = 'opencv-master/data/haarcascades/haarcascade_frontalface_default.xml' # 物体検出用のインスタンス作成 face_cascade = cv.CascadeClassifier() face_cascade.load(cv.samples.findFile(face_cascade_name))
ポイントその2.グレースケールしてから検出
物体検出には大抵の場合カラー情報が必要になることはないので、白黒画像にして処理を軽くして検出します(逆にどういう時にカラーが必要なんだろう?)
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
frame_gray = cv.equalizeHist(frame_gray)
im.show('OpenCV - gray', frame_gray)
白黒画像に変更した図
ポイントその3.顔検出し場所に線を描画する
# 顔の検出 faces = face_cascade.detectMultiScale(frame_gray) # 複数の顔が検出された場合、ひとつづつ枠を付ける場所を決める for (x,y,w,h) in faces: center = (x + w//2, y + h//2) frame = cv.ellipse(frame, center, (w//2, h//2), 0, 0, 360, (255, 0, 255), 4) frame = frame_gray[y:y+h,x:x+w] # カラー画像の上に枠を描画する cv.imshow('OpenCV - facedetect', frame)
試しにYouTube動画にカメラを向けてみると顔が検出されました、できるもんですね
(吉Pとモルボルさんと、光の戦士まで)
【リバイバル放送】みんなで観よう! 第12回 PLLより
(https://www.youtube.com/watch?v=QQbr0xgafk0&feature=youtu.be)
もちろんカメラを向けるのではなく動画をそのまま読み込ませた方が、精度は上がります
目の検出とモザイク処理
同じ要領で目の検出を行なってみます
# 目の検出用がデータ eyes_cascade_name = 'opencv-master/data/haarcascades/haarcascade_eye.xml' # インスタンス作成 eyes_cascade = cv.CascadeClassifier() eyes_cascade.load(cv.samples.findFile(eyes_cascade_name))
顔検出した範囲の中で目の位置を検出
def detectAndDisplay(frame): frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) frame_gray = cv.equalizeHist(frame_gray) # 顔の検出 faces = face_cascade.detectMultiScale(frame_gray) # 複数の顔が検出された場合、ひとつづつ枠を付ける for (x,y,w,h) in faces: center = (x + w//2, y + h//2) frame = cv.ellipse(frame, center, (w//2, h//2), 0, 0, 360, (255, 0, 255), 4) faceROI = frame_gray[y:y+h,x:x+w] # 顔ごとに目を検出する eyes = eyes_cascade.detectMultiScale(faceROI) for (x2,y2,w2,h2) in eyes: eye_center = (x + x2 + w2//2, y + y2 + h2//2) radius = int(round((w2 + h2)*0.25)) frame = cv.circle(frame, eye_center, radius, (255, 0, 0 ), -1) cv.imshow('OpenCV - facedetect', frame)
なんだかそれっぽい箇所が青い丸で検出しています
目の部分にモザイクかけてみる
Python + OpenCVでモザイクをかけるというのを見つけたので、ちょっと目を検出した部分に使ってみます
モザイクをかける関数、定番らしい
def mosaic(src, ratio=0.1): small = cv.resize(src, None, fx=ratio, fy=ratio, interpolation=cv.INTER_NEAREST) return cv.resize(small, src.shape[:2][::-1], interpolation=cv.INTER_NEAREST) def mosaic_area(src, x, y, width, height, ratio=0.1): dst = src.copy() dst[y:y + height, x:x + width] = mosaic(dst[y:y + height, x:x + width], ratio) return dst
モザイクをかける部分の左上を指定してやる必要があるので、検出側も少し工夫してやります
def detectAndDisplay(frame): frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) frame_gray = cv.equalizeHist(frame_gray) # 顔の検出 faces = face_cascade.detectMultiScale(frame_gray) # 複数の顔が検出された場合、ひとつづつ枠を付ける for (x,y,w,h) in faces: center = (x + w//2, y + h//2) frame = cv.ellipse(frame, center, (w//2, h//2), 0, 0, 360, (255, 0, 255), 4) faceROI = frame_gray[y:y+h,x:x+w] # 顔ごとに目を検出する eyes = eyes_cascade.detectMultiScale(faceROI) for (x2,y2,w2,h2) in eyes: # 目を検出した場所の左上とモザイクの幅を決めてやる ex = int((x + x2) - w2 / 2) ey = int(y + y2) ew = int(w2 * 2.5) frame = mosaic_area(frame, ex, ey, ew, h2) cv.imshow('OpenCV - facedetect', frame)
怪しい感じでモザイクがかかりました
© 2010 - 2020 SQUARE ENIX CO., LTD. All Rights Reserved.
全容はコチラ
次はYOLOやってみます