Почему OpenCV DNN (caffe) детектор лиц не смог найти лица? - PullRequest
1 голос
/ 29 января 2020

Используя OpenCV версии 4.2.0 в c ++ (VS 2019), я создал проект, который выполняет распознавание лиц на заданном изображении. Я использовал DNC детектор лица Opencv, который использует 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 , плавающие члены по мере необходимости.

Функция обнаруживает лица на данном изображении, но во время игры с этим я сравниваю с dlib's HOG + SVM детектором лица, поэтому сначала я делаю обнаружение лица с помощью dlib, а затем передается тот же путь к изображению эта функция.

Я нашел несколько изображений, где dlib может легко найти лица на изображении, но opencv не нашел ни одного лица, например, посмотрите на изображение ниже:

HOG+SVM

Как вы видите, HOG + SVM обнаружил 46 лиц примерно за 3 секунды c. Если я передам это же изображение вышеупомянутой функции, то opencv не обнаружит в нем ни одного лица. Почему? Нужны ли какие-либо улучшения в приведенном выше коде? Я не говорю, что функция не обнаруживает лица для какого-либо изображения, но делает это для некоторых изображений (как выше).

Для ссылки:

Я использовал https://pastebin.com/9rt9reNY эта python программа для обнаружения лиц с помощью dlib.

Ответы [ 2 ]

1 голос
/ 29 января 2020

После глубокого поиска, к сожалению, я не смог найти хорошего объяснения этой проблемы. Причина, по которой я попытался обрезать изображение, заключается в том, что я предположил, что может быть максимальный предел обнаруженного числа лиц. Это также не касается окклюзии.

Я пробовал несколько примеров изображений, которые включают более 20 (приблизительно) лиц, и результаты были такими же, но когда я обрезал эти изображения (уменьшил количество лиц), программа была Можно найти лица. Это также не относится к разрешению (размерам) изображения, потому что у пробованных изображений были разные размеры.

Я также изменил и перепробовал все параметры (номер итерации, sureThreshold et * 1020). *.), но результат все еще не был желаемым.

Мое предположение , но не ответ:

Программа не позволяет найти лица, если изображение включает в себя более максимального числа (приблизительно 20)

В качестве решения этого вопроса мы можем разделить исходное изображение на 2 части и найти прямоугольники для каждой из них, которые затем можно вставить в исходное изображение.

Примечание: После глубокого поиска по inte rnet я не смог найти topi c, связанный с этой проблемой. Мне также любопытно, какова главная причина этой проблемы, поэтому любая помощь будет оценена. Этот пост включает только мой опыт и предположения.

0 голосов
/ 05 марта 2020

изменить эту строку:

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);
...