2

我正在按照Erik Buck 的指南为我的视频处理获得绿屏效果。这绝对很棒,但并不完全符合我的要求。我的任务是在我的 iOS 项目中使用 OpenGL使用相同的方法“切掉”白色。

下面是来自 Erik Buck 项目的 OpenGL 代码,用于查找每个纹理的绿色纹素并将其不透明度分配为零:

varying highp vec2 vCoordinate;
uniform sampler2D uVideoframe;


void main()
{
   // Look up the color of the texel corresponding to the fragment being
   // generated while rendering a triangle
   lowp vec4 tempColor = texture2D(uVideoframe, vCoordinate);

   // Calculate the average intensity of the texel's red and blue components
   lowp float rbAverage = tempColor.r * 0.5 + tempColor.b * 0.5;

   // Calculate the difference between the green element intensity and the
   // average of red and blue intensities
   lowp float gDelta = tempColor.g - rbAverage;

   // If the green intensity is greater than the average of red and blue
   // intensities, calculate a transparency value in the range 0.0 to 1.0
   // based on how much more intense the green element is
   tempColor.a = 1.0 - smoothstep(0.0, 0.25, gDelta);

   // Use the cube of the transparency value. That way, a fragment that
   // is partially translucent becomes even more translucent. This sharpens
   // the final result by avoiding almost but not quite opaque fragments that
   // tend to form halos at color boundaries.
   tempColor.a = tempColor.a * tempColor.a * tempColor.a;

      gl_FragColor = tempColor;
}

通过反复试验,我能够操纵此代码以使不同的颜色透明,但白色已被证明是一个挑战。

如何使背景中的白色透明?

在此处输入图像描述

4

2 回答 2

1

您将需要修改着色器中的算法以更改颜色。的值gDelta是像素输出不透明度的决定因素。在您发布的代码中,一旦绿色分量的值高于红色和蓝色的平均值,像素就会开始变得透明。

您基本上只需要决定要使用哪个公式来检测“白色”。一种非常简单(和类似)的方法是计算所有组件的平均值,并定义一些截止值。例如:

//...
float cutoff = 0.8f;
lowp float gDelta = cutoff - dot(tempColor, vec4(0.33, 0.33, 0.33, 0.0));
//...

您需要稍微修改一下,以提供适合您需要的颜色范围。

另外,这个过程是正式的 call chroma-keying。尽管您可以使用任何颜色,但通常是与“剪切”对象不匹配的颜色。鲜绿色是一种常见的选择,因为它很少与肤色或服装搭配。出于这个原因,白色可能是一个非常糟糕的选择。

于 2017-09-25T18:58:46.900 回答
1

白色其实很简单:

void main()
{
    lowp vec4 tempColor = texture2D(uVideoframe, vCoordinate);
    lowp float rgbAverage = tempColor.r + tempColor.b + tempColor.g;
    if (rgbAverage > 1.99) {
        tempColor.a = 0.0;
    }
    else {
        tempColor.a = 1.0;
    }
    gl_FragColor = tempColor;
}

我发现将阈值设置为1.99充分去除白色背景而不影响我手的白度。

于 2018-06-15T19:46:40.160 回答