我正在关注Erik Buck的this指南,以便为我的视频处理获得绿屏效果。这非常了不起,但它并不完全符合我的要求。我的任务是在我的iOS项目中使用OpenGL来使用相同的方法“剪掉” white 。
以下是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;
}
通过反复试验,我能够操纵此代码,以便能够使不同的颜色透明,但白色已被证明是一种挑战。
如何让背景中的白色透明?
答案 0 :(得分:0)
您需要在着色器中修改算法以更改颜色。 gDelta
的值是像素输出的不透明度的决定因素。在您发布的代码中,一旦绿色分量的值高于红色和蓝色的平均值,像素就开始变得透明。
您基本上只需要决定使用哪个公式来检测“白色”。一种非常简单(和类似)的方法是计算所有组件的平均值,并定义一些截止值。例如:
//...
float cutoff = 0.8f;
lowp float gDelta = cutoff - dot(tempColor, vec4(0.33, 0.33, 0.33, 0.0));
//...
您需要稍微修改一下,以提出适合您需要的颜色范围。
此外,此过程正式调用chroma-keying
。虽然您可以使用任何颜色,通常是与“剪切”对象不匹配的颜色。鲜绿色是常见的选择,因为它很少与肤色或衣服相匹配。出于这个原因,白色可能是一个非常糟糕的选择。
答案 1 :(得分:0)
怀特其实非常简单:
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
可以充分消除白色背景,而不会影响我手的白度。