用Qt和OpenCV实现了简单的人脸检测,检测器用的是LBP算法。实现步骤如下,
首先建立一个工程,我的是沿用之前的工程,因为这样不需要配置,直接在上面修改就好了。工程选用Qt Widgets application就可以,不用建立界面文件,因为用不到界面。基类选择QWidget就可以,其他应该都可以。之后直接把main函数里的内容删掉,main函数里面东西也很少,这样它就不会运行界面了,说道这,其实用console应用程序应该也是很好的。之后需要配置pro文件,这个方法可以看我之前的文章。
把所有的代码写进main函数,就可以实现。下面上代码:
int main(int argc, char *argv[])
{
qDebug()<<"hello world!";
VideoCapture cap(0);
cout << "Original size:" << cap.get(CV_CAP_PROP_FRAME_WIDTH) << " " << cap.get(CV_CAP_PROP_FRAME_HEIGHT) << endl;
cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
cap.set(CV_CAP_PROP_FPS, 16);
cout << "Modified size:" << cap.get(CV_CAP_PROP_FRAME_WIDTH) << " " << cap.get(CV_CAP_PROP_FRAME_HEIGHT) << endl;
cvNamedWindow("camera show", CV_WINDOW_AUTOSIZE);
Mat frame;
CascadeClassifier faceDetector;//加载检测器。
string faceDetFileName;
faceDetFileName="D:\\program\\opencv\\opencv\\sources\\data\\lbpcascades\\lbpcascade_frontalface.xml";
try{
faceDetector.load(faceDetFileName);
}catch(cv::Exception e){
}
if(faceDetector.empty()){
cerr<<"ERROR:Couldn't load Face Detector!";
}else{
qDebug()<<"Successfully Loaded!";
}
int i=0;
while (true)
{
cap >> frame;
const int DETECTION_WIDTH=320;
Mat smallImg;//视频的缩小
float scale=frame.cols/(float)DETECTION_WIDTH;
if(frame.cols>DETECTION_WIDTH){
int scaledHeight=cvRound(frame.rows/scale);
resize(frame,smallImg,Size(DETECTION_WIDTH,scaledHeight));
}else{
smallImg=frame;
}
Mat gray;
cvtColor(smallImg,gray,CV_BGR2GRAY);//图像灰度化
Mat equalizedImg;
equalizeHist(gray,equalizedImg);//直方图均衡
int flags=CASCADE_SCALE_IMAGE;
Size minFeatureSize(20,20);
float searchScaleFactor=1.1f;
int minNeighbors=4;
vector<Rect> faces;
faceDetector.detectMultiScale(equalizedImg,faces,searchScaleFactor,
minNeighbors,flags,minFeatureSize);//对处理过的图像进行识别,识别了的巨型框,放在数组faces中。
if(!faces.empty()){
i++;
qDebug()<<"Have detected a face"<<i<<"times!";
vector<Rect>::iterator it=faces.begin();
qDebug()<<"rect's x is"<<(*it).x<<"times!";
rectangle(equalizedImg,faces[0],Scalar(0,0,255),16);
}//如果数组部位空,表示检测到了人脸,并画出矩形。这里我的矩形框画的比较粗。
imshow("camera show1", gray);
imshow("camera show", frame);
imshow("small show2", equalizedImg);//这里可以不展示那么多窗口,展示这一个就够了。
if (waitKey(10) == 27) //press key “ESC” to quit from loop//按esc退出循环。
break;
}
}
要注意的是,画矩形那部分代码,包括对faces数组的引用,必须得写在if里面,刚开始我下载if块的后面的,总是报错,我想原因可能是对于有些帧,faces是空的,所以无法引用,导致报错。还有一个比较好的做法,就是用try,catch块,提供有提示的错误信息。有些配置是不能识别中文的,需要把中文的注释去掉。亲测无错,代码有些地方可以优化,还有一些废语句可以去掉。当时测试用的。