如何删除"绿屏"肖像背景

Dan*_*röm 10 image-processing chromakey

我正在寻找一种从很多图片中自动删除(=透明)"绿色屏幕"肖像背景的方法.

我自己的尝试到目前为止......呃...不太成功.

我正在四处寻找有关该主题的任何提示,解决方案或论文.商业解决方案也很好.

在你发表评论之前说它不可能自动完成:不,不是.实际上有一家公司提供这种服务,如果我没有提出不同的解决方案,我们将使用它们.问题是他们用自己的生命保护算法,因此不会出售/许可他们的软件.相反,我们必须将所有图片FTP到处理完成的地方,然后我们将结果FTP回家.(不,他们没有在菲律宾隐藏的工资过低的工作人员手动处理这个问题,因为我们每天都在谈几千张图片 ......)但是,这种做法限制了它的用处,原因有几个.所以我真的很喜欢这样的解决方案,可以在互联网离线时立即完成.

编辑:我的"肖像"描绘了有头发的人 - 这是一个非常棘手的部分,因为绿色背景会流入头发.另一个棘手的部分是,如果有可能在背景中的绿色和人们衣服中的相同绿色之间进行distingush.我上面谈到的公司声称他们可以通过弄清楚绿色区域是否在焦点(锐利与模糊)来做到这一点.

Gab*_*njo 19

由于您没有提供任何图像,我选择了一个具有色度键的网络,该色度键具有不同的绿色阴影和由于JPEG压缩而产生的大量噪声.

没有技术规范,所以我使用了Java和Marvin Framework.

输入图像:

在此输入图像描述

步骤1简单地将绿色像素转换为透明度.基本上它在HSV颜色空间中使用过滤规则.

在此输入图像描述

正如您所提到的,头发和一些边界像素呈现出与绿色混合的颜色.为了减少这个问题,在步骤2中,对这些像素进行滤波和平衡以降低其绿色比例.

之前:

在此输入图像描述

后:

在此输入图像描述

最后,在步骤3中,将梯度透明度应用于所有边界像素.高质量图像的效果会更好.

最终输出:

在此输入图像描述

源代码:

import static marvin.MarvinPluginCollection.*;

public class ChromaToTransparency {

    public ChromaToTransparency(){
        MarvinImage image = MarvinImageIO.loadImage("./res/person_chroma.jpg");
        MarvinImage imageOut = new MarvinImage(image.getWidth(), image.getHeight());
        // 1. Convert green to transparency
        greenToTransparency(image, imageOut);
        MarvinImageIO.saveImage(imageOut, "./res/person_chroma_out1.png");
        // 2. Reduce remaining green pixels
        reduceGreen(imageOut);
        MarvinImageIO.saveImage(imageOut, "./res/person_chroma_out2.png");
        // 3. Apply alpha to the boundary
        alphaBoundary(imageOut, 6);
        MarvinImageIO.saveImage(imageOut, "./res/person_chroma_out3.png");

    }

    private void greenToTransparency(MarvinImage imageIn, MarvinImage imageOut){
        for(int y=0; y<imageIn.getHeight(); y++){
            for(int x=0; x<imageIn.getWidth(); x++){

                int color = imageIn.getIntColor(x, y);
                int r = imageIn.getIntComponent0(x, y);
                int g = imageIn.getIntComponent1(x, y);
                int b = imageIn.getIntComponent2(x, y);

                double[] hsv = MarvinColorModelConverter.rgbToHsv(new int[]{color});

                if(hsv[0] >= 60 && hsv[0] <= 130 && hsv[1] >= 0.4 && hsv[2] >= 0.3){
                    imageOut.setIntColor(x, y, 0, 127, 127, 127);
                }
                else{
                    imageOut.setIntColor(x, y, color);
                }

            }
        }
    }

    private void reduceGreen(MarvinImage image){
        for(int y=0; y<image.getHeight(); y++){
            for(int x=0; x<image.getWidth(); x++){
                int r = image.getIntComponent0(x, y);
                int g = image.getIntComponent1(x, y);
                int b = image.getIntComponent2(x, y);
                int color = image.getIntColor(x, y);
                double[] hsv = MarvinColorModelConverter.rgbToHsv(new int[]{color});

                if(hsv[0] >= 60 && hsv[0] <= 130 && hsv[1] >= 0.15 && hsv[2] > 0.15){
                    if((r*b) !=0 && (g*g) / (r*b) >= 1.5){
                        image.setIntColor(x, y, 255, (int)(r*1.4), (int)g, (int)(b*1.4));
                    } else{
                        image.setIntColor(x, y, 255, (int)(r*1.2), g, (int)(b*1.2));
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        new ChromaToTransparency();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 嗨加布里埃尔,我六年前写过这个问题,但显然有人对此表示赞赏 - 我希望他会评论你的努力.我已经有一个可接受的解决方案来解决这个问题,这个问 你提供了一个带有大量压缩工件的lores图像,因此它不适用于我正在使用的域,但有一天我会在我的测试图像上运行你的代码以查看差异.然而,我现在想要解决的问题是如何区分相同颜色的背景和布料,但这是另一个故事.干得好 - 干杯! (2认同)

soh*_*970 1

PaintShop Pro 允许您根据选择的颜色删除背景。他们还有一个删除背景棒,可以删除您触摸的任何内容(将这些像素转换为透明)。您可以调整魔杖的“容差”,使其消除与您触摸的像素相似的像素。过去这对我来说效果很好。

为了使其自动化,您可以在 PSP 中编写一个脚本来执行您想要的操作,然后从您的程序中调用它。这可能是一种笨拙的自动替换方法,但它将是最便宜、最快的解决方案,无需编写一堆 C#/C++ 成像代码或向商业机构付费。

他们说,一分钱一分货。

  • 我相信他正在寻找一种自动化的“服务器端”解决方案。 (2认同)