如何删除“绿屏"?肖像背景 [英] How to remove a "green screen" portrait background

查看:159
本文介绍了如何删除“绿屏"?肖像背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm looking for a way to automatically remove (=make transparent) a "green screen" portrait background from a lot of pictures.

到目前为止,我自己的尝试一直...嗯...不太成功.

My own attempts this far have been... ehum... less successful.

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

I'm looking around for any hints or solutions or papers on the subject. Commercial solutions are just fine, too.

在发表评论并说不可能自动执行此操作之前:不,不是.实际上,存在一家提供此服务的公司,如果我无法提出其他解决方案,我们将使用它们.问题在于他们一生都在保护自己的算法,因此不会出售/许可他们的软件.取而代之的是,我们必须将所有图片通过FTP发送到处理完成的地方,然后再将结果通过FTP发送回原处. (不,他们在菲律宾没有隐藏的薪水不足的员工来手动处理,因为我们每天要谈论几千张照片 ...)但是,这种方法限制了它的用处有几个原因.因此,我真的很想一个解决方案,可以在不连接Internet的情况下立即完成此操作.

And before you comment and say that it is impossible to do this automatically: no it isn't. There actually exists a company which offers exactly this service, and if I fail to come up with a different solution we're going to use them. The problem is that they guard their algorithm with their lives, and therefore won't sell/license their software. Instead we have to FTP all pictures to them where the processing is done and then we FTP the result back home. (And no, they don't have an underpaid staff hidden away in the Philippines which handles this manually, since we're talking several thousand pictures a day...) However, this approach limits its usefulness for several reasons. So I'd really like a solution where this could be done instantly while being offline from the internet.

编辑:我的人像"描绘的是确实有头发的人-这是一个非常棘手的部分,因为绿色背景会渗入头发.另一个棘手的部分是,是否有可能在背景中的绿色和人们衣服中的相同绿色之间做出区分.我在上面谈论的公司声称,他们可以通过确定绿色区域是否清晰(清晰还是模糊)来做到这一点.

EDIT: My "portraits" depictures persons, which do have hair - which is a really tricky part since the green background will bleed into hair. Another tricky part is if it is possible to distingush between the green in the background and the same green in peoples clothes. The company I'm talking about above claims that they can do it by figuring out if the green area are in focus (being sharp vs blurred).

推荐答案

由于您未提供任何图像,因此我从网络上选择了一个具有色度键的图像,该键具有不同的绿色阴影和大量噪点由于JPEG压缩.

Since you didn't provide any image, I selected one from the web having a chroma key with different shades of green and a significant amount of noise due to JPEG compression.

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

There is no technology specification so I used Java and Marvin Framework.

输入图片:

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

The step 1 simply converts green pixels to transparency. Basically it uses a filtering rule in the HSV color space.

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

As you mentioned, the hair and some boundary pixels presents colors mixed with green. To reduce this problem, in the step 2, these pixels are filtered and balanced to reduce its green proportion.

之前:

之后:

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

Finally, in the step 3, a gradient transparency is applied to all boundary pixels. The result will be even better with high quality images.

最终输出:

源代码:

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

这篇关于如何删除“绿屏"?肖像背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆