最近,我得到了一个项目,在这个项目中,我必须从给定的图像中提取脸部(脸部+头发)。

我通过以下方式解决此问题。

  • 我正在从给定图像中提取脸部位置。 [我得到一个矩形]
  • 我正在提取该矩形并将其放置在与输入图像尺寸相同的另一个图像中。[face_image]
  • 我在步骤2的face_image上应用grabCut 算法。

  • 当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 。然后,您可以将它们用作bgdModelfgdModel(或皮肤和头发面具),而不是Mat()

    抱歉,这是如此高级。希望对您有所帮助!

    08-07 02:39