基于detectMultiScale函数多尺度人脸检测确定目标尺寸
功能介绍
由于工作项目需求,需要我结合公司实际项目确定detectMultiScale函数中目标检测对象的最大尺寸和最小尺寸,从而达到加快检测速度、过滤噪点目标的目的。
实现步骤
1.detectMultiScale函数介绍
打开opencv源码,具体位置在opencv-3.2.0/modules/objdetect/src/cascadedetect.hpp 。 查看源代码可发现detectMultiscale函数有三种:
void detectMultiScale( InputArray image,
CV_OUT std::vector<Rect>& objects,
double scaleFactor = 1.1,
int minNeighbors = 3, int flags = 0,
Size minSize = Size(),
Size maxSize = Size() );
void detectMultiScale( InputArray image,
CV_OUT std::vector<Rect>& objects,
CV_OUT std::vector<int>& numDetections,
double scaleFactor=1.1,
int minNeighbors=3, int flags=0,
Size minSize=Size(),
Size maxSize=Size() );
void detectMultiScale( InputArray image,
CV_OUT std::vector<Rect>& objects,
CV_OUT std::vector<int>& rejectLevels,
CV_OUT std::vector<double>& levelWeights,
double scaleFactor = 1.1,
int minNeighbors = 3, int flags = 0,
Size minSize = Size(),
Size maxSize = Size(),
bool outputRejectLevels = false );
参数介绍:
参数1:image–待检测图片,一般为灰度图像加快检测速度;
参数2:objects–被检测物体的矩形框向量组;为输出量,如人脸检测矩阵Mat
参数3:scaleFactor–表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%;一般设置为1.1
参数4:minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个)。
如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。
如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,
这种设定值一般用在用户自定义对检测结果的组合程序上;
参数5:flags–要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域;
参数6、7:minSize和maxSize用来限制得到的目标区域的范围。也就是我本次训练得到实际项目尺寸大小
函数介绍:
detectMultiscale函数为多尺度多目标检测:
多尺度:通常搜索目标的模板尺寸大小是固定的,但是不同图片大小不同,所以目标对象的大小也是不定的,所以多尺度即不断缩放图片大小(缩放到与模板匹配),通过模板滑动窗函数搜索匹配;同一副图片可能在不同尺度下都得到匹配值,所以多尺度检测函数detectMultiscale是多尺度合并的结果。
多目标:通过检测符合模板匹配对象,可得到多个目标,均输出到objects向量里面。
2.代码思路
(1)导入opencv自带人脸分类器lbpcascade_frontalface.xml和人眼分类器haarcascade_eye_tree_eyeglasses.xml
(2)读取本地文件夹所有avi视频,参考我的另一篇博客c++读取文件夹文件名
(3)调用detectMultiscale函数,同时检测到人脸和人眼时确定为人脸目标存在,然后输出目标尺寸到vector里,然后排序,输出每个视频中的人脸尺寸最大值和最小值到本地txt文件。
(4)通过得到的尺寸极值确定目标【人脸】的范围
代码块
void detectAndDisplay( Mat frame )
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor( frame, frame_gray, COLOR_BGR2GRAY );
equalizeHist( frame_gray, frame_gray );
//-- Detect faces
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0, Size(80, 80) );
cout << faces.size();
//if(face.size()=)
for( size_t i = 0; i < faces.size(); i++ )
{
cout << faces[i].size() << endl;
Mat faceROI = frame_gray( faces[i] );
std::vector<Rect> eyes;
eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CASCADE_SCALE_IMAGE, Size(30, 30) );
if( eyes.size() == 2)
{
cout << "faces[i].width: "<< faces[i].width << " faces[i].height:" <<faces[i].height << "faces[i].size:" << faces[i].size() << " faces[i]:" <<faces[i] << endl;/////////////////////////////////////////////////////////////
Facesize.push_back(faces[i].width);
Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 0 ), 2, 8, 0 );
for( size_t j = 0; j < eyes.size(); j++ )
{ //-- Draw the eyes
Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
circle( frame, eye_center, radius, Scalar( 255, 0, 255 ), 3, 8, 0 );
}
}
}
imshow( window_name, frame );
}
备注
转载需注明