opencv java中GrabCut的性能优化

opencv java中GrabCut的性能优化,java,algorithm,opencv,Java,Algorithm,Opencv,最近我接到一个项目,我必须从给定的图像中提取人脸(脸+头发) 我用以下方法解决这个问题 我正在从给定的图像中提取人脸位置。[我得到一个矩形] 我正在提取那个矩形,并将它放置在另一个与输入图像尺寸相同的图像中。[face_image] 我正在第2步的面部图像上应用grabCut算法 当人脸图像包含平滑背景时,算法grabCut运行良好,但当人脸图像的背景复杂时,算法grabCut也会在处理后的图像中提取部分背景 下面是我得到的结果的快照 这是我的抓取代码: public void extract

最近我接到一个项目,我必须从给定的图像中提取人脸(脸+头发)

我用以下方法解决这个问题

  • 我正在从给定的图像中提取人脸位置。[我得到一个矩形]
  • 我正在提取那个矩形,并将它放置在另一个与输入图像尺寸相同的图像中。[face_image]
  • 我正在第2步的面部图像上应用grabCut算法
  • 当人脸图像包含平滑背景时,算法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);
    }
    

    如何提高grabCut算法的性能,使其仅从给定图像中检测人脸和头发?

    您应该能够通过“帮助”
    grabCut
    了解一些前景和背景来做到这一点。有一个示例演示了如何通过选择前景和背景手动完成此操作

    要自动执行此操作,您需要找到编程方式来检测前景和背景。前景主要由头发和皮肤组成,因此您需要检测它们

    皮肤-有关于如何做到这一点的文件和建议。其中一些是,也可能有帮助。我已经找到了朴素的色调/饱和度,让我走得很远

    头发-这是,但仍然是。如果结果证明这是一项太多的工作,那么你可以使用头发和皮肤以及背景

    背景-您应该能够使用查找图像中紫色、绿色和蓝色的内容。你肯定知道这些东西不是皮肤或头发,因此是背景的一部分

    使用阈值创建最可能是皮肤、头发和背景的区域的遮罩。然后可以将它们用作
    bgdModel
    fgdModel
    (或皮肤和头发遮罩),而不是
    Mat()


    抱歉,这是如此高的级别。我希望有帮助

    我建议“玩”矩形坐标
    (intxone,intxtwo,intyone,intytwo)
    。使用你的代码和这些坐标1400,30400,我能够避开背景。(我试图发布我成功剪切的图像,但我至少需要10个声誉才能做到)

    对任何Java例程都可以进行的最佳优化是转换为本地语言。

    另一种方法,因为您已经检测到了人脸,就是简单地选择一个更好的初始掩码来初始化GrabCut-例如,使用椭圆形而不是矩形

  • 检测面矩形(正如您已经在做的那样)
  • 创建遮罩:

    a) 创建与输入图像大小相同的新黑色图像

    b) 绘制一个与面矩形具有相同高度、宽度、顶部和左侧位置的白色填充椭圆

  • 使用带有掩码的
    GC\u INIT\u调用GrabCut,而不是带有RECT的
    GC\u INIT\u调用GrabCut

    Imgproc.grabCut(image, mask, rectangle, bgdModel, fgdModel, 8, Imgproc.GC_INIT_WITH_MASK);
    

  • 这将使用更好的模型初始化前景,因为面形状更像椭圆形而不是矩形,因此它首先应该包含更少的背景。

    我已经尝试了许多这样的方法,这些东西并没有按照我的期望发挥作用……如果你能更详细地说明你尝试了什么,以及它是如何不起作用的,并将其添加到你的问题中,也许我可以提供更多的帮助。我有不同类型的图像,对于一些图像来说,背景与头发非常相似,程序无法区分它们,而且所提到的东西在所有情况下都不起作用……虽然GrabCut非常好,但它确实有其局限性。在GrabCut运行后,您可能需要执行自己的优化。不幸的是,您所做的仍然是一个开放的研究主题,因此很难找到能够为您完成所有工作的预先进行的库调用。您还可以尝试寻找/实现另一种分割算法,如TVSeg。祝你好运这并不能回答这个问题。要评论或要求作者澄清,请在他们的帖子下方留下评论-你可以随时在自己的帖子上发表评论,一旦你有足够的评论,你就可以发表评论了。嗨,拉姆,如果这不是发布的正确位置,我很抱歉。问:我如何提高grabCut算法的性能,使其只检测给定图像中的人脸和头发?我的回答是:直肠离脸部越近,结果就越好。我正在查看你的帖子,我选择了要显示的通用系统消息。它基本上是说这是一个有用的评论,而不是一个答案,因为它不够详细,不足以成为一个答案,它要求你把它作为一个评论发布。我知道你不能发表评论,因为你没有这样做的名声。请回答一些你知道的问题,以收集声誉,然后尝试评论或使你的答案更详细的例子和图像作为链接,我将通过添加链接到你的图像转换。java接口访问OpenCV库,这是在C++中实现的。这是一种“本地”语言,而且库也进行了大量优化。你在这里的断言是不正确的。