2

我一直在尝试使用 OpenCV 2.4.3 和 Logitech C920 相机,希望能够实现一种原始的面部识别方案。非常简单,不是很复杂。

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/features2d.hpp"


#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

/** Function Headers */
void grabcurrentuser();
void capturecurrentuser( Mat vsrc );

/** Global Variables **/
string face_cascade_name = "haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;

int main( void ){//[main]
    grabcurrentuser();

}//]/main]

void grabcurrentuser(){//[grabcurrentuser]
    CvCapture* videofeed;
    Mat videoframe;

    //Load face cascade
    if( !face_cascade.load( face_cascade_name ) ){
        printf("Can't load haarcascade_frontalface_alt.xml\n");
    }
    //Read from source video feed for current user
    videofeed = cvCaptureFromCAM( 1 );
    if( videofeed ){
            for(int i=0; i<10;i++){//Change depending on platform
            videoframe = cvQueryFrame( videofeed );

            //Debug source videofeed with display
            if( !videoframe.empty() ){
            imshow( "Source Video Feed", videoframe ); 
            //Perform face detection on videoframe
            capturecurrentuser( videoframe );
        }else{ 
            printf("Videoframe is empty or error!!!"); break; 
        }

            int c = waitKey(33);//change to increase or decrease delay between frames
            if( (char)c == 'q' ) { break; }

            }
    }
}//[/grabcurrentuser]

void capturecurrentuser( Mat vsrc ){//[capturecurrentuser]
    std::vector<Rect> faces;
    Mat vsrc_gray;
    Mat currentuserface;

    //Preprocess frame for face detection
    cvtColor( vsrc, vsrc_gray, CV_BGR2GRAY );
    equalizeHist( vsrc_gray, vsrc_gray );

    //Find face
    face_cascade.detectMultiScale( vsrc_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30,30) );
    //Take face and crop out into a Mat
    currentuserface = vsrc_gray( faces[0] );
    //Save the mat into a jpg file on disk
    imwrite( "currentuser.jpg", currentuserface );
    //Show saved image in a window  
    imshow( "Current User Face", currentuserface ); 

}//[/capturecurrentuser]

上面的代码是这个系统的第一个组件。它的工作是接受视频提要,拍摄 10 帧左右(因此是 for 循环)并在帧上运行 haar 级联以获得人脸。一旦获得了一张脸,它就会将该脸切割成一个 Mat 并将其以 jpg 格式保存在工作目录中。

到目前为止它已经工作了,但似乎是一段非常喜怒无常的代码。大多数时候它给了我想要的输出(我不打算在这里问我如何使事情更准确或更精确 - 但随时告诉我:D)但其他时候它以分段错误结束。以下是分段错误的正常输出示例(我环顾四周,发现 VIDIOC 无效参数是可以忽略的 - 再次,如果它很容易修复,请随时告诉我)。

VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
init done 
opengl support available 
Segmentation fault (core dumped)

谁能告诉我为什么有时在这个程序的并发运行中我会遇到像上面这样的单个或一系列分段错误结果,而其他时候则不是?该程序旨在创建一个输出,该输出被分流到我编写的另一个程序,所以我不能让它像这样抓住我。

非常感激!

4

1 回答 1

0

您的问题在以下行中:

currentuserface = vsrc_gray( faces[0] );

根据我的经验,当您访问不存在的内容时会出现分段错误。如果检测到人脸,程序可以正常工作,因为 faces[0] 包含数据。但是,当没有检测到人脸时(覆盖相机),没有矩形存储在 faces[0] 中。因此发生错误。

尝试像这样初始化,以便 imshow 和 imwrite 在未检测到任何内容时工作:

cv::Mat currentuserface = cv::Mat::zeros(vsrc.size(), CV_8UC1);

然后在用它初始化 currentuserface 之前检查 faces 是否为空:

if( !faces.empty() )

currentuserface = vsrc_gray( faces[0] );
于 2014-08-10T10:29:04.533 回答