我正在研究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()));
我已经检查过多个帖子,但是我没有得到任何解决方案。 请告诉我该怎么做才能解决这个问题。
非常感谢任何帮助。谢谢。
答案 0 :(得分:9)
您应该注意detectMultiScale()
:
scaleFactor
- 参数指定每个图像比例下图像尺寸减少的程度。此参数用于创建比例金字塔。这是必要的,因为模型在训练期间具有固定的大小。没有金字塔,唯一要检测的大小就是这个修复(也可以从XML中读取)。然而,通过使用多尺度表示,即使用相同的检测窗口检测大面和小面,面部检测可以是尺度不变的。
scaleFactor
取决于训练有素的探测器的大小,但实际上,您需要将其设置得尽可能高,同时仍然能够获得良好的探测器。结果,所以这应该凭经验确定。
您的1.1值对于此目的而言可能是一个很好的价值。这意味着,使用相对较小的步长进行大小调整(将大小减小10%),可以增加与检测模型匹配大小的机会。如果训练有素的探测器尺寸为10x10,则可以检测尺寸为11x11,12x12的面部,依此类推。但实际上1.1因子要求金字塔中的层数(和2倍的计算时间)大约是1.2倍。
minNeighbors
- 参数指定每个候选矩形应保留多少个邻居。
级联分类器使用滑动窗口方法。通过应用此方法,您可以在窗口上滑动窗口,而不是调整窗口大小并再次搜索,直到无法进一步调整窗口大小。在每次迭代中,存储了(级联分类器的)真实输出,但不幸的是它实际上检测到许多误报。并且为了消除误报并从检测中获得正确的面部矩形,应用邻域方法。 3-6对它来说是一个很好的价值。如果该值太高,那么您也可能失去真正的积极因素。
minSize
- 关于minNeighbors
的滑动窗口方法,这是级联可以检测到的最小窗口。小于该值的对象将被忽略。通常cv::Size(20, 20)
足以进行面部检测。
maxSize
- 最大可能的对象大小。大于此的对象将被忽略。
最后,您可以尝试基于不同功能的不同分类器(例如Haar,LBP,HoG)。通常,LBP分类器比Haar快几倍,但也不太准确。
强烈建议您查看以下问题:
答案 1 :(得分:1)
相反,将图片作为Bitmap
进行阅读,然后使用Mat
将其转换为Utils.bitmapToMat(defaultBitmap,image)
,您可以直接使用Mat image = Highgui.imread(imagepath);
您可以here查看imread()
功能。
此外,由于探测器正在寻找至少具有相当小的尺寸(20,20)的面,因此下面的线花费太多时间。检查this视频,了解使用OpenCV进行人脸检测的可视化。
mJavaDetector.detectMultiScale(image,faceDetections,1.1, 10, 0, new Size(20,20), new Size(image.width(), image.height()));