如何删除“绿屏”肖像背景

时间:2010-05-11 13:16:07

标签: image-processing chromakey

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

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

我正在寻找关于此主题的任何提示或解决方案或论文。商业解决方案也很好。

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

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

5 个答案:

答案 0 :(得分:18)

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

没有技术规范,因此我使用了Java和Marvin Framework

输入图片:

enter image description here

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

enter image description here

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

<强>之前:

enter image description here

<强>后:

enter image description here

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

最终输出:

enter image description here

源代码:

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();
    }
}

答案 1 :(得分:3)

如果您知道“绿色”,您可以在opencv C / C ++ / Python中编写一个小程序来提取该颜色并替换为透明像素。

答案 2 :(得分:2)

看一下这个帖子: http://www.wizards-toolkit.org/discourse-server/viewtopic.php?f=2&t=14394&start=0

以及其中的教程链接: http://tech.natemurray.com/2007/12/convert-white-to-transparent.html

然后,只需编写一些脚本来查看完整的图像目录。很简单。

答案 3 :(得分:2)

123视频魔术绿屏背景软件还有一些刚刚删除绿屏的背景希望这有帮助

答案 4 :(得分:1)

PaintShop Pro允许您根据拾取颜色删除背景。他们还有一个删除背景棒,可以删除你触摸的任何东西(将这些像素转换为透明)。您可以调整魔杖的“容差”,使其取出与您正在触摸的像素类似的像素。这在过去对我来说非常有效。

要自动化它,您可以在PSP中编写一个脚本,它可以执行您想要的操作,然后从您的程序中调用它。这可能是一种自动替换的方法,但它是最便宜,最快的解决方案,无需编写大量C#/ C ++映像代码或支付商业代理费。

他们说,你付出的代价是什么。