OpenCV 2.4.10人脸检测可以在视频中工作,但不能在静态图像中检测

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

本文关键字:检测 工作 图像 静态 但不能 视频 10人 OpenCV      更新时间:2023-10-16

我使用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 cascaden"); return -1; };

    //-- 2. Read the video stream
    capture.open( -1 );
    if ( ! capture.isOpened() ) { printf("--(!)Error opening video capturen"); 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'读取

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

解决了!

非常愚蠢的错误。我没有叫facecascade。加载haarcascades的静态图像版本,但我做了视频凸轮版本。

现在都工作了。