主要筛选准则:人脸面积>400, 轮廓长度>20, 0.5<轮廓长/宽<2.5;具体选择根据实际情况改动。
void findcontours(Mat *src,Mat mask)//mask为检测到的人脸二值图区域,src为源图。
{
Mat mask1;
mask.copyTo (mask1);
Mat mask2 (mask1.size(), CV_8UC1 );
Mat element1 = getStructuringElement (MORPH_RECT,Size(5,5));
erode(mask1, mask1,element1, Point(-1,-1), 1);
imshow ("腐蚀", mask1);
Mat element2 = getStructuringElement (MORPH_ELLIPSE, Size(5,5));
dilate (mask1, mask1,element2);
imshow("膨胀",mask1);
//imwrite ("mask1.jpg", mask2);
threshold(mask1, mask2, 0,255,CV_THRESH_BINARY );
mask2.convertTo (mask2, CV_8UC1 );
fillHole2(&mask2);//孔洞填充
imshow ("填充后", mask2);
//imshow("mask2图像", mask2);
//轮廓查找
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours (mask2, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );
//筛选轮廓
vector<int> label;
int add_lable = 0;
vector<Rect> boundRect(contours.size());//定义外接矩形集合
vector<RotatedRect > box(contours.size()); // 定义最小外接矩形几何
for (int i =0; i < contours.size(); i++)
{
double con_area = contourArea (contours[i]);
double con_length = arcLength (contours[i], true);
int x0 =0, y0 =0, w0 =0, h0 =0, w1 = 0, h1 = 0;
boundRect[i] = boundingRect(contours[i]);
//box[i] = minAreaRect (contours[i]);
x0 = boundRect[i].x;
y0 = boundRect[i].y;
w0 = boundRect[i].width;
h0 = boundRect[i].height;
/*w1 = box[i].size.width ;
h1 = box[i].size.height;*/
if (con_area > 400 && w0 > 20 && h0 > 20 && (h0/w0)>0.2 && (h0/w0)<2.5 )
{
drawContours (mask2, contours,i, Scalar (255, 0, 0), 1, 8);
rectangle (*src, Point(x0, y0), Point(x0+w0, y0+h0), Scalar (0, 255, 0), 2, 8);
putText (*src, "Face", Point(x0+w0/4, y0-5), CV_FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,255,0),1 );
label.push_back (i);
add_lable ++;
}
}
}
void fillHole2(Mat *src)//利用漫水填充进行孔洞填充
{
Mat temp = Mat::zeros((src->size().height ) + 2, (src->size().width)+2, src->type());
src->copyTo (temp(Range (1,(src->size().height ) + 1),Range (1,(src->size().width)+1)));
floodFill (temp, Point(0,0),Scalar (255));
//imshow("floodFill", temp);
Mat cutImg;//将图像还原为原来大小
temp(Range (1,(src->size().height ) + 1),Range (1,(src->size().width)+1)).copyTo (cutImg );
*src = (*src) | (~ cutImg );
}
参考文献
https://blog.csdn.net/mao19931004/article/details/48933435