温馨提示:本博文支持opencv-2.4及opencv-3.4版本,可通过宏 VERSION_2_4 控制。
上一篇文章只是简单地实现了图片与视频流的人脸检测,但这只是采用一种简单粗暴的方式,从效果上来看,视频检测卡顿问题较严重。这次主要针对该问题进行优化。
一、未作优化版本的程序
首先,摆上简单粗暴的opencv打开摄像头检测人脸的代码:
#include "opencv2/"
#include "opencv2/"
#include "opencv2/"
#include <iostream>
#include <>
using namespace cv;
using namespace std;
// 控制编译版本宏
//#define VERSION_2_4
int main()
{
CascadeClassifier faceCascade;
double t = 0;
int nRet = 0;
VideoCapture capture;
(0);
// ("");
if(!())
{
cout << "open camera failed. " << endl;
return -1;
}
/* 加载分类器 */
#ifdef VERSION_2_4
nRet = ("/root/library/opencv/opencv-2.4.13.6/data/haarcascades/haarcascade_frontalface_alt.xml");
#else
nRet = ("/root/library/opencv/opencv-3.4.0/data/haarcascades/haarcascade_frontalface_alt.xml");
#endif
if(!nRet)
{
printf("load xml failed.\n");
return -1;
}
Mat img, imgGray;
vector<Rect> faces;
while(1)
{
capture >> img;
if(())
{
continue;
}
cvtColor(img, imgGray, CV_RGB2GRAY);
/* 检测人脸 */
t = (double)getTickCount();
( imgGray, faces,
1.1, 2, 0
//|CASCADE_FIND_BIGGEST_OBJECT
//|CASCADE_DO_ROUGH_SEARCH
|CASCADE_SCALE_IMAGE,
Size(30, 30) );
t = (double)getTickCount() - t;
printf( "detection time = %g ms\n", t*1000/getTickFrequency());
/* 画矩形框出人脸 */
for(size_t i =0; i<(); i++)
{
rectangle(img, Point(faces[i].x, faces[i].y), Point(faces[i].x + faces[i].width, faces[i].y + faces[i].height),
Scalar(0, 255, 0), 1, 8);
}
imshow("CameraFace", img);
if(waitKey(1) > 0) // delay ms 等待按键退出
{
break;
}
}
return 0;
}
运行效果(人脸图像就不贴出来了):
detection time = 278.65 ms
detection time = 280.025 ms
detection time = 280.809 ms
detection time = 289.129 ms
detection time = 279.903 ms
detection time = 281.969 ms
二、优化处理
第三方库的使用,最权威的教程当属官方文档,opencv也一样。
所以,先参考/看懂官方的人脸检测例程:
官网: /3.4.0/db/d3a/facedetect_8cpp
库源码: opencv-3.4.0/samples/cpp/
官方示例主要对图像作以下处理:
1、缩放图像,可提高检测速率,减少检测时间
void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
double inv_scale_x, double inv_scale_y, int interpolation )
2、直方图均衡化,可提高图像质量
void equalizeHist(const oclMat &mat_src, oclMat &mat_dst)
本程序也主要作以上优化处理(能力有限,希望后续能有更多优化)
优化后的程序:
#include "opencv2/"
#include "opencv2/"
#include "opencv2/"
#include <iostream>
#include <>
using namespace cv;
using namespace std;
// 控制编译版本宏
//#define VERSION_2_4
/* 参数 : 输入图像、级联分类器、缩放倍数 */
void DetectAndDraw( Mat& img, CascadeClassifier& cascade, double scale);
int main()
{
CascadeClassifier faceCascade;
double scale = 4;
int nRet = 0;
VideoCapture capture;
(0);
// ("");
if(!())
{
cout << "open camera failed. " << endl;
return -1;
}
cout << "open camera succeed. " << endl;
/* 加载分类器 */
#ifdef VERSION_2_4
nRet = ("/root/library/opencv/opencv-2.4.13.6/data/haarcascades/haarcascade_frontalface_alt.xml");
#else
nRet = ("/root/library/opencv/opencv-3.4.0/data/haarcascades/haarcascade_frontalface_alt.xml");
#endif
if(!nRet)
{
printf("load xml failed.\n");
return -1;
}
Mat frame;
vector<Rect> faces;
while(1)
{
capture >> frame;
if(())
{
continue;
}
Mat frame1 = ();
DetectAndDraw( frame1, faceCascade, scale );
if(waitKey(1) > 0) // delay ms 等待按键退出
{
break;
}
}
return 0;
}
void DetectAndDraw( Mat& img, CascadeClassifier& cascade, double scale )
{
double t = 0;
vector<Rect> faces;
Mat gray, smallImg;
double fx = 1 / scale;
cvtColor( img, gray, COLOR_BGR2GRAY ); // 将源图像转为灰度图
/* 缩放图像 */
#ifdef VERSION_2_4
resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );
#else
resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT );
#endif
equalizeHist( smallImg, smallImg ); // 直方图均衡化,提高图像质量
/* 检测目标 */
t = (double)getTickCount();
( smallImg, faces,
1.1, 2, 0
//|CASCADE_FIND_BIGGEST_OBJECT
//|CASCADE_DO_ROUGH_SEARCH
|CASCADE_SCALE_IMAGE,
Size(30, 30) );
t = (double)getTickCount() - t;
printf( "detection time = %g ms\n", t*1000/getTickFrequency());
/* 画矩形框出目标 */
for ( size_t i = 0; i < (); i++ ) // ():检测到的目标数量
{
Rect rectFace = faces[i];
rectangle( img, Point(, ) * scale,
Point( + , + ) * scale,
Scalar(0, 255, 0), 2, 8);
}
imshow( "FaceDetect", img ); // 显示
}
运行效果:
detection time = 23.5718 ms
detection time = 27.5776 ms
detection time = 22.7952 ms
detection time = 31.5242 ms
detection time = 39.568 ms
detection time = 31.5325 ms
可以看到,检测速度提高了10倍左右,视频卡顿效果也基本消除了。