記事検索

検索ワードを入力してください。
Sky Tech Blog
【OpenCV】C++で​YuNetに​よる​顔検出

【OpenCV】C++で​YuNetに​よる​顔検出

ここでは、OpenCV 4.5.4で新しく導入された顔検出APIをC++で試し、YuNetのAIモデルを使用して、リアルタイムで顔の位置とランドマークを検出する方法について説明しています。

OpenCV 4.5.4から新しく導入された顔検出のAPIをC++で試しました。

YuNetの​AIモデルを​ダウンロード

下記URLからface_detection_yunet_2023mar.onnx をダウンロードしてください。
https://github.com/opencv/opencv_zoo/tree/main/models/face_detection_yunet

ソースコード

動作環境

  • Visual Studio 2019
  • OpenCV 4.11.0
void main()
{
    // カメラを開く
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        std::cerr << "カメラを開けませんでした" << std::endl;
        return;
    }

    // モデルのパスを指定
    std::string modelPath = "face_detection_yunet_2023mar.onnx";

    // FaceDetectorYNオブジェクトを作成
    cv::Ptr<cv::FaceDetectorYN> detector = cv::FaceDetectorYN::create(modelPath, "", cv::Size(0, 0));

    while (true) {
        cv::Mat frame;
        cap >> frame; // カメラからフレームを取得

        if (frame.empty()) {
            std::cerr << "フレームを取得できませんでした" << std::endl;
            break;
        }

        // 入力画像のサイズを設定
        detector->setInputSize(frame.size());

        // 顔を検出
        cv::Mat faces;
        detector->detect(frame, faces);

        for (size_t i = 0; i < faces.rows; i++)
        {
            // 顔検出
            cv::rectangle(frame, cv::Rect(faces.at<float>(i,0), faces.at<float>(i, 1), faces.at<float>(i, 2), faces.at<float>(i, 3)), cv::Scalar(0, 255,0));

            // ランドマーク
            cv::circle(frame, cv::Point(faces.at<float>(i, 4), faces.at<float>(i, 5)), 3, cv::Scalar(255, 0, 0), cv::FILLED);
            cv::circle(frame, cv::Point(faces.at<float>(i, 6), faces.at<float>(i, 7)), 3, cv::Scalar(255, 0, 0), cv::FILLED);
            cv::circle(frame, cv::Point(faces.at<float>(i, 8), faces.at<float>(i, 9)), 3, cv::Scalar(255, 0, 0), cv::FILLED);
            cv::circle(frame, cv::Point(faces.at<float>(i, 10), faces.at<float>(i, 11)), 3, cv::Scalar(255, 0, 0), cv::FILLED);
            cv::circle(frame, cv::Point(faces.at<float>(i, 12), faces.at<float>(i, 13)), 3, cv::Scalar(255, 0, 0), cv::FILLED);

            // スコア
            cv::putText(frame, std::to_string(faces.at<float>(i, 14)), cv::Point(faces.at<float>(i, 0), faces.at<float>(i, 1) - 10), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255));
        }

        // 結果を表示
        cv::imshow("Detected Faces", frame);

        // 'q'キーが押されたらループを終了
        if (cv::waitKey(1) == 'q') {
            cv::destroyWindow("Detected Faces");
            break;
        }
    }
}

結果

顔の位置とランドマークの表示ができています。(顔を隠すためにニコちゃんマークも重畳させました)
実際に動かしてみるとわかりますが、リアルタイムで問題なく検出できます。
OpenCVで簡単に使用できる顔検出の方法として、「カスケード型分類器による顔検出」がありますが、こちらの方が精度も速度も良いように感じました。

普段はC#を使用しているので、後にライブラリにして呼び出せるようにC++で書いてみました。
(OpenCVSharpではこちらのAPIは対応しておらず…)
OpenCVも日々バージョンアップしているので、いろいろお試しできると楽しいですね!


\シェアをお願いします!/
  • X
  • Facebook
  • LINE
キャリア採用募集中!

入社後にスキルアップを目指す若手の方も、ご自身の経験を幅広いフィールドで生かしたいベテランの方も、お一人おひとりの経験に応じたキャリア採用を行っています。

Sky株式会社のソフトウェア開発や製品、採用に関するお問い合わせについては、下記のリンクをご確認ください。
お問い合わせ
ホーム