如何提升OpenCV人脸识别方法准确率

OpenCV自带的人脸识别方法会识别同一幅图像上所有的人脸,同时也会把并不是人脸的地方识别成人脸,这就对使用者带来不便。那么如何优化这个方法,使其能够正常有效地运行呢?

OpenCV人脸识别的不准问题

wrong_face

上图就是直接使用OpenCV人脸识别方法经常会发生的情况了。对于我目前的使用场景,我只想要图片中识别出唯一正确的人脸。所以我使用了如下两种改进方法:设置ROI和人脸排序。

设置ROI

ROI(region of interest)就是感兴趣区域,在此处具体来讲就是人脸比较容易出现的区域。由于我目前使用的是双目相机,根据双目相机的成像规律,人脸通常会出现在左相机的右侧,以及右相机的左侧,具体可以看下图

stereo1

从图中可以看出,人脸的图像总是会在左相机的右边,在右相机的左边,因此我把这两个区域设置为ROI,让OpenCV的人脸识别只识别ROI区域,这样非ROI区域就不会被识别了。

具体设置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cv::Rect RectROI1(300, 100, 340, 300);  //把ROI画出来,括号内分别是图像的x,y,width,height,注意x轴是从左往右为正,y轴是从上往下为正
cv::Rect RectROI2(0, 100, 340, 300);
cv::rectangle(image1, RectROI1, Scalar(0, 255, 0), 1);
cv::rectangle(image2, RectROI2, Scalar(0, 255, 0), 1);

cv::Mat imageROI1 = image1(Range(100, 340), Range(300, 640)); //正式设置每幅图像的ROI,四个参数分别是上下左右
cv::Mat imageROI2 = image2(Range(100, 340), Range(0, 340));

this->faceDetector.detectMultiScale(imageROI1, faces1);//这里再修改一下输入参数,不是原图像,而是ROI
this->faceDetector.detectMultiScale(imageROI2, faces2);

faces1[0] = faces1[0] + Point(300, 100); //识别出来的人脸的坐标是在ROI区域内的,需要转换到原图像中
faces2[0] = faces2[0] + Point(0, 100);

//其他步骤和前文就一致了

结果如下图:

ROI

可以看到,设置ROI之后,人脸检测的范围就被缩小到大的绿色框内了,识别成功的概率有提升。如果在你的应用场景中,人脸也是会通常出现在特定区域,那么你也可以利用这个方法试一试。

等等,右边图像的背景墙上有一部分还是被当做人脸,如何解决这个问题?

人脸排序

通过大量测试发现,OpenCV误把非人脸区域识别成人脸的情况下,错误人脸bounding-box是明显小于真正人脸bounding-box的,因此可以把识别到的所有“人脸”降序排列,第一个就是真正的人脸啦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//降序排列
bool comparison(cv::Rect a, cv::Rect b) {
return a.width > b.width;
}

std::sort(faces1.begin(), faces1.end(), comparison);
std::sort(faces2.begin(), faces2.end(), comparison);

//第一个人脸用绿框,其余用红框
for (int i = 0; i < faces1.size(); i++) {
if (i == 0)
cv::rectangle(img1, faces1[i], cv::Scalar(0, 255, 0));
else
cv::rectangle(img1, faces1[i], cv::Scalar(0, 0, 255));
}

for (int i = 0; i < faces2.size(); i++) {
if (i == 0)
cv::rectangle(img2, faces2[i], cv::Scalar(0, 255, 0));
else
cv::rectangle(img2, faces2[i], cv::Scalar(0, 0, 255));
}

sort

结果如图,这样就能确保得到真正的人脸了。这些框框只是为了讲明白是怎么一回事画的,实际上我的工程里面没有画这些红的绿的框,只标出了人脸特征点,需不需要画自己决定。

经过设置ROI和人脸排序两个步骤,OpenCV的人脸识别方法已经有很大的改良了,能够投入正常使用中。除此之外有没有其他比较方便的实现人脸识别的办法呢?你好,有的。那就是Dlib,下一篇文章就介绍如何在OpenCV里面使用Dlib进行人脸识别吧。