OpenCV 2.4.10 人脸检测适用于视频,但无法在静态图像中检测

OpenCV 2.4.10 Face detection works with video but fails to detect in a static image

我正在使用 OpenCV 的级联分类器来检测人脸。我遵循了网络摄像头教程,并且能够使用 detectMultiScale 在我的面部从笔记本电脑的网络摄像头流式传输视频时查找和跟踪它。

但是当我从笔记本电脑的网络摄像头拍摄自己的照片时,我将该图像加载到 OpenCV 中,并对该图像应用 detectMultiScale,由于某种原因,级联分类器无法检测到该静态图像上的任何人脸!

如果静态图像是我的网络摄像头流中的一帧,肯定会被检测到,但是当我只拍摄那一张单独的图像时,没有检测到任何东西。

这是我使用的代码(只挑出相关行):

共同代码:

String face_cascade_name = "/path/to/data/haarcascades/haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;

Mat imagePreprocessing(Mat frame) {
    Mat processed_frame;
    cvtColor( frame, processed_frame, COLOR_BGR2GRAY );
    equalizeHist( processed_frame, processed_frame );
    return processed_frame;
}

对于网络摄像头流式面部检测:

int detectThroughWebCam() {
    VideoCapture capture;
    Mat frame;
    if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade\n"); return -1; };


    //-- 2. Read the video stream
    capture.open( -1 );
    if ( ! capture.isOpened() ) { printf("--(!)Error opening video capture\n"); return -1; }

    while ( capture.read(frame) )
    {
         if(frame.empty()) {
             printf(" --(!) No captured frame -- Break!");
             break;
         }
         //-- 3. Apply the classifier to the frame
         Mat processed_image = imagePreprocessing( frame);
         vector<Rect> faces;
         face_cascade.detectMultiScale( processed_frame, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, Size(30, 30) );
         if (faces.size() > 0) cout << "SUCCESS" << endl;
         int c = waitKey(10);
         if( (char)c == 27 ) { break; } // escape
    }
    return 0;
}

对于我的静态图像人脸检测:

void staticFaceDetection() {
    Mat image = imread("path/to/jpg/image");
    Mat processed_frame = imagePreprocessing(image);
    std::vector<Rect> faces;
    //-- Detect faces
    face_cascade.detectMultiScale( processed_frame, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, Size(30, 30) );
    if (faces.size() > 0) cout << "SUCCESS" << endl;
}

在我看来,这两个过程是相同的(唯一的区别是我获取原始图像的位置),但是视频流版本定期检测人脸,而静态方法似乎永远无法检测到找一张脸。

我是不是漏掉了什么?

有几个可能的原因。

  1. 您以低分辨率保存图像。尝试以原始分辨率保存

  2. 有损压缩。您是否将图像保存为 .jpg 文件?也许你的压力太大了。尝试保存为 BMP 文件(它保留了原始质量)。

  3. 图片格式。我不知道你的 imagePreprocessing() 方法是做什么的,但你可能会引入以下问题。摄像头以特定格式捕获视频(大多数摄像头使用 YUV)。通常,人脸检测是在第一个平面 Y 上执行的。当您保存图像并将其作为 RGB 从磁盘读取时,您不能 运行 在第一个平面上进行人脸检测。这将是 'B' 平面,蓝色存储关于面部的信息很少。请确保在 运行 人脸检测之前将图像正确转换为灰度。

  4. 图像的范围。这是一个常见的错误。确保图像的动态范围正确。有时,您可能会错误地将所有值乘以 255,从而有效地将整个图像变为白色。

  5. 也许图像上的人脸检测工作正常,但您在人脸检测后以某种方式清除了 faces 矢量。另一个错误可能是您读取了不同的图像文件。例如,您将图像保存到目录 'A' 但不小心从目录 'B'

  6. 中读取

如果以上 none 有帮助。进行如下调试。 对于视频帧 'i' - 将其存储在内存中。然后将其保存到磁盘并将其从文件读回内存。现在是最重要的部分:比较图像。如果它们不同——这就是人脸检测结果不同的原因。如果不是,则需要进一步调查。我很确定图像不会完全相同,这就是问题所在。您可以通过获取像素值之间的差异并显示差异图像来查看图像的不同之处。您可以使用比较 2 个内存块的 memcmp() 函数来比较图像。 祝你好运

解决了!

真是愚蠢的错误。我没有调用 facecascades.load 来为静态图像版本加载 haarcascades,但我为视频 cam 版本加载了 haarcascades。

现在一切正常。