シヨツ鬼のブログ

初心者向けに分かりやすくIT関連の情報を発信しています。

【OpenCV C++】顔認識をリアルタイムで行いたい ~2日目~

f:id:shiyotsuki:20200426151531p:plain
どうも、プログラミングの鬼シヨツ鬼です。
OpenCV(C++)で顔認識をリアルタイムに行いたいぜ」って人に向けて、僕が試行錯誤した開発記を連載6回で書いています。

過去の記事は↓からどうぞ!
【OpenCV C++】顔認識をリアルタイムで行いたい ~1日目~ - シヨツ鬼のブログ


ちなみに、この記事は下記の動画と関連しています。
こちらの動画を先に見ていただくと、実際に動く際のイメージが掴めます。

YouTube:【自作】ゆゆうたさんをバーチャルユーチューバー化してみた

また、OpenCVのインストール方法はこちらの動画をご覧ください。
YouTube:OpenCVのインストール方法【Visual Studio】【C++】

2日目:検出範囲を半分にしたら、検出が早くなった!

1日目ではカメラの起動と単純な顔認識を行いましたが、検出に時間がかかるため、リアルタイムにおこなうというのは厳しそうでした。
2日目では、検出範囲を半分にすることで、検出速度を向上させてみます。

やりたいこと

・検出範囲を半分にして、検出速度を上げる

f:id:shiyotsuki:20200502160323p:plain
完成イメージ

ソースコード

#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
#include <vector>

using namespace cv;
using namespace std;

int main(void) {

	//デバイスのオープン
	VideoCapture cap(0);

	//カメラデバイスが正常にオープンしたか確認.
	if (!cap.isOpened())
	{
		//読み込みに失敗したときの処理
		return -1;
	}

	//取得したフレーム
	Mat frame;

	//カスケード分類器格納場所
	CascadeClassifier cascade; 

	//正面顔情報が入っているカスケード
	cascade.load("C:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml"); 
	
	//輪郭情報を格納場所
	vector<Rect> faces; 

	//次の顔検出対象を探る
	Mat detection_frame;

	//無限ループ
	while (1)
	{
		//USBカメラが得た動画の1フレームを格納
		cap >> frame;


		//検出範囲として上半分を切り出す
		Rect roi(Point(0, 0), Point(frame.cols, frame.rows / 2));
		detection_frame = frame(roi);

		//検出範囲を赤枠で囲む
		rectangle(frame, Point(0, 0), Point(detection_frame.cols, detection_frame.rows), Scalar(255, 0, 0), 3);

		//格納されたフレームに対してカスケードファイルに基づいて顔を検知
		cascade.detectMultiScale(detection_frame, faces, 1.1, 3, 0, Size(20, 20));

		//検出した顔の個数"faces.size()"分ループを行う
		for (int i = 0; i < faces.size(); i++) 
		{
			//検出した顔を赤色矩形で囲む
			rectangle(frame, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height), Scalar(0, 0, 255), 3); 
		}


		//画像を表示.
		imshow("win", frame);

		//キーボード入力を受け付ける	
		const int key = waitKey(1);

		//qボタンが押されたとき
		if (key == 'q'/*113*/)
		{
			break;//whileループから抜ける.
		}

	}
	//すべてのウィンドウを閉じる
	destroyAllWindows();

	return 0;
}

解説

ポイントは「detection_frame」です。
カメラキャプチャ映像の上半分のみを「detection_frame」に切り出し、その中のみを検知対象としています。

まとめ

検出速度は全体から検索するよりも早くなりました!
しかし、当然ながら顔が上半分に収まりきらない場合などは検出されなくなってしまいました。。。
また、検出速度もまだ十分とは言えません。
3日目では、より効率的に顔認識を行うための検出範囲の切り出しを、試行錯誤していきます。

続きはこちらの記事へ
https://shiyotsuki.hatenablog.com/entry/virtual_youtuber_3

最後まで読んでくれてありがとう。
参考になったら「☆」を押してね。そして僕のYouTubeTwitterもよろしくね。