最近,我得到了一个项目,在这个项目中,我必须从给定的图像中提取脸部(脸部+头发)。
我通过以下方式解决此问题。
当face_image包含平滑背景时,算法grabCut 可以很好地工作,但是当face_image的背景复杂时,grabCut 算法也会在处理后的图像中提取背景的一部分。
这是我得到的结果的快照。
这是我的grabCut 的代码:
public void extractFace(Mat image, String fileNameWithCompletePath,
int xOne, int xTwo, int yOne, int yTwo) throws CvException {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Rect rectangle = new Rect(xOne, yOne, xTwo, yTwo);
Mat result = new Mat();
Mat bgdModel = new Mat();
Mat fgdModel = new Mat();
Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3));
Imgproc.grabCut(image, result, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_RECT);
Core.compare(result, source, result, Core.CMP_EQ);
Mat foreground = new Mat(image.size(), CvType.CV_8UC3, new Scalar(255, 255, 255));
image.copyTo(foreground, result);
Imgcodecs.imwrite(fileNameWithCompletePath, foreground);
}
我如何才能改善catchCut算法的性能,使其仅检测给定图像中的脸和头发?
最佳答案
您应该能够通过“帮助” grabCut
来对前景和背景有所了解。有一个python tutorial,显示如何通过选择前景和背景来手动完成此操作。
要自动执行此操作,您将需要找到编程的方法来检测前景和背景。前景主要由头发和皮肤组成,因此您需要对其进行检测。
皮肤-关于如何执行此操作,有several论文和blogs。其中有些是pretty simple,而this OpenCV tutorial也可能会有所帮助。我发现淡淡的色调/饱和度使我走的很远。
头发-这是is trickier,但definitely仍然是doable。如果您发现这种工作量过多,则可能可以染发,仅使用皮肤和背景即可。
背景-您应该能够使用 range()
在图像中找到紫色,绿色和蓝色的东西。您肯定知道这些东西不是皮肤或头发,因此是背景的一部分。
使用阈值创建最可能是皮肤,头发和背景的区域的 mask 。然后,您可以将它们用作bgdModel
和fgdModel
(或皮肤和头发面具),而不是Mat()
。
抱歉,这是如此高级。希望对您有所帮助!