如何从边缘羽化色度蒙版 [英] How to feather the chroma mask from edges

查看:292
本文介绍了如何从边缘羽化色度蒙版的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我用来做色度键的着色器,该着色器很好用,但是我需要对色度蒙版的边缘进行羽化处理.

This is the shader i am using to do chroma key , the shader works well but i need to feather the edges of the chroma mask.

我该怎么做?

#version 430 core

uniform sampler2D u_tex;     
vec4 keyRGBA = vec4(86.0 / 255.0 , 194.0 / 255.0, 46.0 / 255.0 , 1.0);    // key color as rgba
vec2 keyCC;      // the CC part of YCC color model of key color
uniform vec2 rangeSpill = vec2(0.1, .52);      // the smoothstep range for spill detection
uniform vec2 range = vec2(0.05, 0.21);      // the smoothstep range for chroma detection
in vec2 texCoord;
out vec4 FragColor;

vec2 RGBToCC(vec4 rgba) {
    float Y = 0.299 * rgba.r + 0.587 * rgba.g + 0.114 * rgba.b;
    return vec2((rgba.b - Y) * 0.565, (rgba.r - Y) * 0.713);
}       

vec2 RGBAToCC (float r, float g, float b) {
    
    float y = 0.299 * r + 0.587 * g + 0.114 * b;    
    return vec2((b - y) * 0.565, (r - y) * 0.713);
}


vec3 RGBToYCC( vec3 col )
{
    float y = 0.299 * col.r + 0.587 * col.g + 0.114 * col.b;    
    return vec3( y ,(col.b - y) * 0.565, (col.r - y) * 0.713);

}


vec3 YCCToRGB( vec3 col )
{
   float R  = col.x + (col.z - 128) *  1.40200;
   float G  = col.x + (col.y - 128) * -0.34414 + (col.z - 128) * -0.71414;
   float B  = col.x + (col.y - 128) *  1.77200;
   return vec3( R , G , B);

}


vec3 hueShift( vec3 color, float hueAdjust ){ 
     vec3  kRGBToYPrime = vec3 (0.299, 0.587, 0.114);
     vec3  kRGBToI      = vec3 (0.596, -0.275, -0.321);
     vec3  kRGBToQ      = vec3 (0.212, -0.523, 0.311);
     vec3  kYIQToR     = vec3 (1.0, 0.956, 0.621);
     vec3  kYIQToG     = vec3 (1.0, -0.272, -0.647);
     vec3  kYIQToB     = vec3 (1.0, -1.107, 1.704);
     float   YPrime  = dot (color, kRGBToYPrime);
     float   I       = dot (color, kRGBToI);
     float   Q       = dot (color, kRGBToQ);
     float   hue     = atan (Q, I);
     float   chroma  = sqrt (I * I + Q * Q);
     hue += hueAdjust;
     Q = chroma * sin (hue);
     I = chroma * cos (hue);
     vec3    yIQ   = vec3 (YPrime, I, Q);
     return vec3( dot (yIQ, kYIQToR), dot (yIQ, kYIQToG), dot (yIQ, kYIQToB) );
}


float GetYComponent( vec3 color){ 
     vec3  kRGBToYPrime = vec3 (0.299, 0.587, 0.114);
     vec3  kRGBToI      = vec3 (0.596, -0.275, -0.321);
     vec3  kRGBToQ      = vec3 (0.212, -0.523, 0.311);
     vec3  kYIQToR     = vec3 (1.0, 0.956, 0.621);
     vec3  kYIQToG     = vec3 (1.0, -0.272, -0.647);
     vec3  kYIQToB     = vec3 (1.0, -1.107, 1.704);
     float   YPrime  = dot (color, kRGBToYPrime);
     return YPrime;
}

        
void main() {
    vec4 src1Color = texture2D(u_tex,  texCoord);   
    keyCC = RGBAToCC( keyRGBA.r , keyRGBA.g , keyRGBA.b  );
    vec2 CC = RGBToCC(src1Color);   
    float mask = sqrt(pow(keyCC.x - CC.x, 2.0) + pow(keyCC.y - CC.y, 2.0));     
    mask = smoothstep(rangeSpill.x + 0.5, rangeSpill.y, mask);
    if (mask > 0.0 && mask < .8)
    {
      src1Color = vec4( hueShift(src1Color.rgb , 1.8 ) , src1Color.a );  // spill remover           
    }   
    
    // Now the spill is removed do the chroma
     vec2 CC2 = RGBToCC(src1Color);
     float mask2 = sqrt(pow(keyCC.x - CC2.x, 2.0) + pow(keyCC.y - CC2.y, 2.0));
     mask2 = smoothstep(range.x, range.y, mask2);       
    if (mask2 == 0.0) { discard; }
            else if (mask2 == 1.0)
        {   
        FragColor = vec4(src1Color.rgb ,  mask2);
        }
        else 
        {
            vec4 col = max(src1Color - (1.0 - mask2) * keyRGBA, 0.0);               
            FragColor = vec4(hueShift(col.rgb , 0.3 ) , col.a); // do color correction      
        }
        
}

这是基本图像

这是色度键控后的结果.

This is the result after chroma keying.

如果有人还可以提供一些有关在着色器中添加更多细节的信息,那么色度键控也没有太多可用的信息.

Also there is not much information avaliable for chroma keying if someone could also give some information about adding more details in the shader.

推荐答案

有效地,您需要挤出与色度键匹配的区域.尽管您只可以在单个渲染过程中对模式(而不是单个点)进行采样,但这并不是很有效.

Effectively, you need to extrude the areas where the Chroma key matched. While you could just sample in a pattern (instead of a single point) in a single render pass, that's not quite efficient.

相反,您应该先将遮罩写入1位(或与透明度相同的大小).然后,您可以在该蒙版上沿X和Y方向运行一个简单的1D着色器,以将已排除的区域挤出固定量.无论哪种方式,您都需要一个临时纹理来打乒乓球,而拆分X和Y维度所需的样本总数要少得多.

Instead you should rather write the mask to a 1bit (or as much as you would like for transparency) mask texture first. Then you can run a simple 1D shader in X and Y direction over that mask to extrude the already excluded areas by a fixed amount. You need a temporary texture for playing ping-pong either way, and splitting X and Y dimensions requires far less samples in total.

例如最小不透明度在5像素范围内,或者使用缩放器/钳位器进行高斯模糊,以使已经完全透明的像素保持透明.

E.g. the minimum opacity in a range of 5px, or a Gaussian blur with a scaler / clamp to keep already full transparent pixels still transparent.

最终,像往常一样,将最终蒙版与源图像结合起来.

Ultimately, combine your final mask with the source image as usual.

这篇关于如何从边缘羽化色度蒙版的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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