1

我正在使用 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;
}

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

我在这里错过了什么吗?

4

2 回答 2

0

有几个可能的原因。

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

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

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

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

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

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

于 2015-05-31T09:24:16.763 回答
0

解决了!

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

现在一切正常。

于 2015-06-02T02:55:09.683 回答