1

通过在 c++(VS 2019)中使用 OpenCV 4.2.0 版,我创建了对给定图像执行人脸检测的项目。我使用了 Opencv 的 DNN 人脸检测器,它使用res10_300x300_ssd_iter_140000_fp16.caffemodel模型来检测人脸。下面是该函数的代码:

//variables which are used in function
const double inScaleFactor = 1.0;
const cv::Scalar meanVal = cv::Scalar(104.0, 177.0, 123.0);
const size_t inWidth = 300;
const size_t inHeight = 300;

std::vector<FaceDetectionResult> namespace_name::FaceDetection::detectFaceByOpenCVDNN(std::string filename, FaceDetectionModel model)
{        

    Net net;        
    cv::Mat frame = cv::imread(filename);
    cv::Mat inputBlob;
    std::vector<FaceDetectionResult> vec;


    if (frame.empty())
        throw std::exception("provided image file is not found or unable to open.");

    int frameHeight = frame.rows;
    int frameWidth = frame.cols;

    if (model == FaceDetectionModel::CAFFE)
    {            
        net = cv::dnn::readNetFromCaffe(caffeConfigFile, caffeWeightFile);
        inputBlob = cv::dnn::blobFromImage(frame, inScaleFactor, cv::Size(inWidth, inHeight), meanVal, false, false);
    }
    else
    {            
        net = cv::dnn::readNetFromTensorflow(tensorflowWeightFile, tensorflowConfigFile);
        inputBlob = cv::dnn::blobFromImage(frame, inScaleFactor, cv::Size(inWidth, inHeight), meanVal, true, false);
    }

    net.setInput(inputBlob, "data");
    cv::Mat detection = net.forward("detection_out");

    cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());

    for (int i = 0; i < detectionMat.rows; i++)
    {            
        if (detectionMat.at<float>(i, 2) >= 0.5)
        {
            FaceDetectionResult res;
            res.faceDetected = true;
            res.confidence = detectionMat.at<float>(i, 2);

            res.x1 = static_cast<int>(detectionMat.at<float>(i, 3) * frameWidth);
            res.y1 = static_cast<int>(detectionMat.at<float>(i, 4) * frameHeight);
            res.x2 = static_cast<int>(detectionMat.at<float>(i, 5) * frameWidth);
            res.y2 = static_cast<int>(detectionMat.at<float>(i, 6) * frameHeight);

            vec.push_back(res);
        }
#ifdef aDEBUG
        else
        {

            cout << detectionMat.at<float>(i, 2) << endl;

        }
#endif
    }                
    return vec;
}

在上面的代码中,在人脸检测之后,我分配了自定义类中检测到的人脸的置信度和坐标FaceDetectionResult,这是一个根据需要具有 bool 和 int,float 成员的简单类。

函数检测给定图像中的人脸,但是在玩这个时我正在与dlib'sHOG+SVM 人脸检测器进行比较,所以首先我通过 dlib 进行人脸检测,然后将相同的图像路径传递给这个函数。

我发现了一些图像,其中 dlib 可以很容易地在图像中找到人脸,但 opencv 没有找到一个人脸,例如看下图:

HOG+SVM

如您所见,HOG+SVM 在大约 3 秒内检测到 46 张人脸,如果我将相同的图像传递给上述函数,那么 opencv 没有在其中检测到一张人脸。为什么?我需要对上述代码进行任何增强吗?我并不是说该功能不会检测任何图像的人脸,它确实可以,但对于某些图像(如上)它不能。

参考:

我使用https://pastebin.com/9rt9reNY这个 python 程序使用 dlib 检测人脸。

4

2 回答 2

1

经过深入搜索,不幸的是我找不到这个问题的好解释。我尝试裁剪图像的原因是我假设可能存在最大检测到的人脸数量限制。这也与遮挡无关。

我尝试了一些包含超过 20 个(appx.)人脸的图像示例,结果是相同的,但是当我裁剪这些图像(减少人脸数量)时,程序能够找到这些人脸。这也与分辨率无关(尺寸)图像,因为我尝试的图像尺寸不同。

我还更改并尝试了所有参数(迭代次数、confidenceThreshold 等),但结果仍然不是我们想要的。

我的假设但不是答案:

如果图像包含的数量超过最大数量(大约 20 个),则程序不会让您找到人脸

作为这个问题的解决方案,我们可以将源图像分成两部分,并为每个部分找到矩形,然后可以将其粘贴到源图像中。

注意: 在互联网上深入挖掘后,我找不到与此问题相关的话题。我也很好奇导致此问题的主要原因,因此将不胜感激。这篇文章只包括我的经验和假设。

于 2020-01-29T10:00:15.793 回答
0

改变这一行:

inputBlob = cv::dnn::blobFromImage(frame, inScaleFactor, cv::Size(inWidth, inHeight), meanVal, false, false);

通过这一行:

frameHeightinputBlob = cv::dnn::blobFromImage(frame, inScaleFactor, cv::Size(inWidth, inHeight), meanVal, false, false);
于 2020-03-05T18:21:46.660 回答