Bootstrap

OpenCV2D 特征框架 (22)人脸检测的一个类cv::FaceDetectorYN的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

cv::FaceDetectorYN 是 OpenCV 中用于人脸检测的一个类,它基于深度学习模型实现。这个类是 OpenCV DNN(Deep Neural Network module)模块的一部分,利用预先训练好的深度神经网络模型来执行高效的人脸检测任务。

主要特性

  • 高效的检测:FaceDetectorYN 使用了 Yunet 模型,这是一个轻量级且高效的卷积神经网络(CNN),专门设计用于快速准确地在图像或视频帧中检测人脸 1。
  • 支持多种输入格式:可以处理静态图像、视频流以及实时摄像头输入。
  • 可配置性:允许用户调整置信度阈值、非极大值抑制(NMS)阈值等参数,以适应不同的应用场景5。
  • 硬件加速支持:可以通过选择不同的后端和目标设备(如 CPU、GPU 或 NPU)来加速推理过程

成员函数介绍

  • create:创建一个 FaceDetectorYN 对象。
    • model, config: 分别是模型文件路径和配置文件路径。对于大多数预训练模型,仅需提供模型文件路径即可。
    • input_size: 输入图像的尺寸(宽度, 高度)。这通常与模型训练时使用的输入尺寸相匹配。
    • score_threshold: 置信度阈值,低于此分数的人脸将被忽略,默认值为0.9。
    • nms_threshold: 非极大值抑制(NMS)阈值,用于去除重叠的人脸框,默认值为0.3。
    • top_k: 保留的最高得分边界框数量,默认值为5000。
    • setInputSize:设置输入图像的尺寸。
    • width, height: 输入图像的宽度和高度。
  • detect:执行人脸检测,并返回检测到的人脸信息。
    • image: 要检测的图像。
    • faces: 输出参数,包含检测到的所有人脸的位置信息和其他相关数据。具体的数据结构取决于实现细节,但通常每个条目会包含一个人脸的位置(如边界框)、置信度分数以及其他可能的关键点位置。
  • setScoreThreshold:设置置信度分数阈值。
    • threshold: 新的置信度分数阈值。
  • setNMSThreshold:设置非极大值抑制(NMS)阈值。
    • threshold: 新的NMS阈值。
  • setTopK:设置保留的最高得分边界框数量。
    • k: 新的最大边界框数量。
  • setPreferableBackend:设置首选的DNN后端。
    • backend: 后端标识符,例如 cv::dnn::DNN_BACKEND_OPENCV 或 cv::dnn::DNN_BACKEND_CUDA。
  • setPreferableTarget:设置首选的目标设备。
    • target: 目标设备标识符,例如 cv::dnn::DNN_TARGET_CPU 或 cv::dnn::DNN_TARGET_CUDA。

代码示例

#include <iostream>
#include <opencv2/dnn.hpp>
#include <opencv2/opencv.hpp>

int main()
{
    // 模型文件路径
    std::string model_path = "face_detection_yunet_2023mar.onnx";

    // 创建 FaceDetectorYN 对象
    cv::Ptr< cv::FaceDetectorYN > detector = cv::FaceDetectorYN::create( model_path, "", cv::Size( 320, 320 ),  // 输入尺寸,可以根据实际情况调整
                                                                         0.9f,                                  // 置信度阈值
                                                                         0.3f,                                  // NMS 阈值
                                                                         5000                                   // top_k 参数
    );

    // 加载测试图像
    cv::Mat img = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/zhou.png" );
    if ( img.empty() )
    {
        std::cerr << "无法读取图像" << std::endl;
        return -1;
    }

    // 设置输入尺寸为图像的实际尺寸
    detector->setInputSize( img.size() );

    // 进行人脸检测
    cv::Mat faces;
    detector->detect( img, faces );

    // 绘制检测到的人脸框和关键点
    for ( int i = 0; i < faces.rows; ++i )
    {
        float x     = faces.at< float >( i, 0 );
        float y     = faces.at< float >( i, 1 );
        float w     = faces.at< float >( i, 2 );
        float h     = faces.at< float >( i, 3 );
        float score = faces.at< float >( i, 14 );  // 分数

        // 绘制人脸框
        cv::rectangle( img, cv::Point( x, y ), cv::Point( x + w, y + h ), cv::Scalar( 0, 255, 0 ), 2 );
        

        // 打印分数
        std::cout << "Face " << i << ": Score = " << score << std::endl;
        cv::putText( img, "Face " +std::to_string( i )+": Score =" + std::to_string( score ), cv::Point( x, y - 10 ), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar( 0, 255, 0 ), 1 );

        // 绘制人脸关键点(如果有的话)
        for ( int j = 4; j <= 13; j += 2 )
        {
            int keypoint_x = static_cast< int >( faces.at< float >( i, j ) );
            int keypoint_y = static_cast< int >( faces.at< float >( i, j + 1 ) );
            cv::circle( img, cv::Point( keypoint_x, keypoint_y ), 3, cv::Scalar( 0, 0, 255 ), -1 );
        }
    }

    // 显示结果图像
    cv::imshow( "Detected Faces", img );
    cv::waitKey( 0 );

    return 0;
}

运行结果

在这里插入图片描述

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;