如何在 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 人脸检测性能?的主要内容,如果未能解决你的问题,请参考以下文章

Android App实战项目之使用OpenCV人脸识别实现找人功能(附源码和演示 超详细)

使用OpenCV Android SDK从摄像头帧实时检测人脸

基于opencv的人脸采集训练及识别应用

使用android sdk而不是opencv的人脸识别

Android OpenCV实现人脸检测完成人脸检测功能

Android OpenCV实现人脸检测JNI层添加打印时间