如何在 android 中提高 OpenCV 人脸检测性能?
Posted
技术标签:
【中文标题】如何在 android 中提高 OpenCV 人脸检测性能?【英文标题】:How to improve OpenCV face detection performance in android? 【发布时间】:2015-02-20 06:20:55 【问题描述】:我正在开发一个 android 项目,在该项目中我使用 OpenCV 从图库中的所有图像中检测人脸。从图像中获取人脸的过程在服务中执行。服务持续工作,直到处理完所有图像。它将检测到的人脸存储在内部存储中,如果活动打开,也会显示在网格视图中。
我的代码是:
CascadeClassifier mJavaDetector=null;
public void getFaces()
for (int i=0 ; i<size ; i++)
File file=new File(urls.get(i));
imagepath=urls.get(i);
defaultBitmap=BitmapFactory.decodeFile(file, bitmapFatoryOptions);
mJavaDetector = new CascadeClassifier(FaceDetector.class.getResource("lbpcascade_frontalface").getPath());
Mat image = new Mat (defaultBitmap.getWidth(), defaultBitmap.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(defaultBitmap,image);
MatOfRect faceDetections = new MatOfRect();
try
mJavaDetector.detectMultiScale(image,faceDetections,1.1, 10, 0, new Size(20,20), new Size(image.width(), image.height()));
catch(Exception e)
e.printStackTrace();
if(faceDetections.toArray().length>0)
一切都很好,但是检测面孔非常慢。性能非常缓慢。当我调试代码时,我发现需要时间的行是:
mJavaDetector.detectMultiScale(image,faceDetections,1.1, 10, 0, new Size(20,20), new Size(image.width(), image.height()));
我已经检查了多个帖子来解决这个问题,但我没有得到任何解决方案。 请告诉我应该怎么做才能解决这个问题。
任何帮助将不胜感激。谢谢。
【问题讨论】:
我会从减小 maxSize 开始。你真的需要整个图像吗?例如看看你自己的个人资料照片。 是的,我需要整张图片,因为可能有一张集体照片,可以在整张图片的任何地方找到人脸。如果我减小尺寸,那么它会丢失一些面孔。 还是单个检测的大小,iirc 我通过减小 maxSize 进行了检查,但性能没有提高。 【参考方案1】:注意detectMultiScale()
的参数:
scaleFactor
– 指定在每个图像比例下图像尺寸减小多少的参数。此参数用于创建比例金字塔。这是必要的,因为模型在训练期间具有固定的大小。如果没有金字塔,唯一要检测的尺寸就是这个修复尺寸(也可以从 XML 中读取)。然而,通过使用多尺度表示,人脸检测可以是尺度不变的,即使用相同的检测窗口检测大小人脸。scaleFactor
取决于您训练的检测器的大小,但实际上,您需要将其设置得尽可能高,同时仍能获得“良好”的结果,因此应根据经验确定。
为此,您的 1.1 值可能是一个很好的值。这意味着,一个相对较小的步骤用于调整大小(将大小减小 10%),您增加了找到与检测模型匹配大小的机会。如果您训练的检测器大小为 10x10,那么您可以检测大小为 11x11、12x12 等的人脸。但实际上 1.1 倍数需要的金字塔层数大约是 1.2 倍数的两倍(以及 2 倍的计算时间)。
minNeighbors
– 指定每个候选矩形应保留多少邻居的参数。
级联分类器使用滑动窗口方法。通过应用这种方法,您在图像上滑动一个窗口而不是调整它的大小并再次搜索,直到您无法进一步调整它的大小。在每次迭代中,(级联分类器的)真实输出都被存储,但不幸的是它实际上检测到许多误报。为了消除误报并从检测中获得正确的面部矩形,应用了邻域方法。 3-6对它来说是一个很好的价值。如果该值太高,那么您也可能会丢失真阳性。
minSize
- 关于minNeighbors
的滑动窗口方法,这是级联可以检测到的最小窗口。小于该值的对象将被忽略。通常cv::Size(20, 20)
足以进行人脸检测。
maxSize
– 最大可能的对象大小。大于此的对象将被忽略。
最后你可以尝试基于不同特征的不同分类器(如 Haar、LBP、HoG)。通常,LBP 分类器比 Haar 的分类器快几倍,但也不太准确。
并且强烈建议您查看这些问题:
Recommended values for OpenCV detectMultiScale() parameters
OpenCV detectMultiScale() minNeighbors parameter
【讨论】:
我已经检查了所有这些参数。所以我发现 LBP 分类器比 Haar 和 Hog 更快更准确。 如果图像的分辨率大于 0.9-1.0 MP,您可以选择缩小图像,然后将面部矩形缩小到原始大小。【参考方案2】:而不是将图像读取为Bitmap
,然后通过使用Utils.bitmapToMat(defaultBitmap,image)
将它们转换为Mat
,您可以直接使用Mat image = Highgui.imread(imagepath);
您可以查看here以获得imread()
功能。
此外,下一行需要太多时间,因为检测器正在寻找至少具有相当小的 Size(20, 20) 的人脸。查看this 视频,了解使用 OpenCV 进行人脸检测的可视化。
mJavaDetector.detectMultiScale(image,faceDetections,1.1, 10, 0, new Size(20,20), new Size(image.width(), image.height()));
【讨论】:
你好我喜欢最初我使用 Mat image = Highgui.imread(imagepath);但性能是一样的。它给了我灰色的脸。那么我怎样才能从 Highgui.imread(imagepath);Highgui.imread(imagepath, CV_LOAD_IMAGE_COLOR);
来自link,CV_LOAD_IMAGE_COLOR - 如果设置,则始终将图像转换为颜色一
感谢 melike 分享有用的信息。我不明白如何设置 CV_LOAD_IMAGE_COLOR 值并使用它,请解释一下。
你不需要设置它,它是在 Highgui 模块中定义的 OpenCV 标志。像下面这样使用它,Highgui.imread(imagepath, org.opencv.highgui.Highgui.CV_LOAD_IMAGE_COLOR);
以上是关于如何在 android 中提高 OpenCV 人脸检测性能?的主要内容,如果未能解决你的问题,请参考以下文章
opencv中检测出人脸之后,需要把检测出的人脸区域提取出来,用作人脸识别,那么如何提取人脸区域