Unity green screen video cutout algorithm & principle and implementation -- excellent results

  • Let’s talk about two things: one is how to play the video in Unity, and the other is how to remove the green part after playing it!

1 Unity plays video

1.1 Put the green screen video into Assets

This is too simple. Just drag the video to a directory under Assets, such as the video directory.

1.2 Create an object RawImage for playing videos

Hierarchy panel, UI -> Raw Image.
Insert image description here

1.3 Create RawImage input source, namely texture Render Texture

This will be the output of video playback and the input of RawImage.
In the Project panel, right-click on the directory you want and create Render Texture
Insert image description here
After it is created, in the Inspector panel, change the texture size, preferably with the video The source is the same width and height.
Insert image description here

1.4 Texture settings of Raw Image

Set its Texture to the texture created in the third step. (Just drag the texture file in the Project panel to the arrow area). Texture can be considered as the input source of Raw Image.
Insert image description here

1.5 Add video components to RawImage

Select the Raw Image and add the VideoPlayer component to it in the Inspector panel.
That is Add Component, select VideoPlayer.
Insert image description here

1.6 Configure Video Player

The video source, namely Video Clip, is selected as the green screen video imported earlier
Insert image description here
The Render Mode is selected as Render Texture, and then the Target Texture is selected as the texture created in the third step above. .

The process construction is completed.
The video is output to a texture, which is the input of Raw Image. The Raw Image is finally displayed on the screen.

Completed to 6, you can now play the video. However, what comes out is raw data, with a green screen!

1.7 Supplement: Adjust output width and height

What should you do if the display window is 1080P and the screen is full when you want to debug?
On the one hand, adjust the display window width and height:
That is, the Game window is modified as follows:
Insert image description here
Of course, if you default to Game If the window does not come out, open it manually:
Insert image description here
Don’t ask me what this window is for, this is a debugging window. Simulate the real output screen. Click this:
Insert image description here
and it will come out on its own. This is basic enough, but it's gone astray. .囧

Okay, the output window has been changed. Next, set the width and height of the Raw Image to 1080P, that is, make the following modifications to the Inspector. Then move the Raw Image position and display it in the center of the screen, and that's it.
Insert image description here

2 Video processing, i.e. cutout

Return to the Inspector panel of Raw Image again.
Insert image description here
Found that our Material has not been set in any way.

What does Material do? An introduction below

2.1 Introduction to Material

Material, also known as object texture, represents the color, texture, smoothness, transparency, reflectivity, refractive index, luminosity and other attributes of an object.
At the Unity level, the essence of a material is a Shader instance.

What is Shader? It is a GPU image algorithm program in the rendering pipeline. It can be understood as the way an object is rendered.

Therefore, if we add a material, it means how to render this object.

2.2 Add shader

This is a shader algorithm contributed by a master (see the appendix for the source code), professional green screen editing! Put this file in the Material directory under Assets:

// Created by Oliver Davies. Enjoy. 
// [email protected]

Shader "Unlit/ChromaKey"
{
    
    
    Properties
    {
    
    
        _MainTex ("Texture", 2D) = "white" {
    
    }
        _KeyColor("KeyColor", Color) = (0,1,0,0)
        _TintColor("TintColor", Color) = (1,1,1,1)
        _ColorCutoff("Cutoff", Range(0, 1)) = 0.2
        _ColorFeathering("ColorFeathering", Range(0, 1)) = 0.33
        _MaskFeathering("MaskFeathering", Range(0, 1)) = 1
        _Sharpening("Sharpening", Range(0, 1)) = 0.5

        _Despill("DespillStrength", Range(0, 1)) = 1
        _DespillLuminanceAdd("DespillLuminanceAdd", Range(0, 1)) = 0.2
    }
    SubShader
    {
    
    
        Tags
        {
    
    
            "RenderPipeline"="HDRenderPipeline"
            "RenderType"="HDUnlitShader"
            "Queue" = "Transparent+1"
        }

        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite Off
        cull off

        Pass
        {
    
    
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
    
    
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
    
    
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
				//float4 uvgrab : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_TexelSize;
            float4 _MainTex_ST;
            float4 _KeyColor;
            float4 _TintColor;
            float _ColorCutoff;
            float _ColorFeathering;
            float _MaskFeathering;
            float _Sharpening;
            float _Despill;
            float _DespillLuminanceAdd;
			//sampler2D _GrabTexture;
			//float4 _GrabTexture_TexelSize;

			#define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))



            // Utility functions -----------

            float rgb2y(float3 c) 
            {
    
    
                return (0.299*c.r + 0.587*c.g + 0.114*c.b);
            }

            float rgb2cb(float3 c) 
            {
    
    
                return (0.5 + -0.168736*c.r - 0.331264*c.g + 0.5*c.b);
            }

            float rgb2cr(float3 c) 
            {
    
    
                return (0.5 + 0.5*c.r - 0.418688*c.g - 0.081312*c.b);
            }

            float colorclose(float Cb_p, float Cr_p, float Cb_key, float Cr_key, float tola, float tolb)
            {
    
    
                float temp = (Cb_key-Cb_p)*(Cb_key-Cb_p)+(Cr_key-Cr_p)*(Cr_key-Cr_p);
                float tola2 = tola*tola;
                float tolb2 = tolb*tolb;
                if (temp < tola2) return (0);
                if (temp < tolb2) return (temp-tola2)/(tolb2-tola2);
                return (1);
            }

            float maskedTex2D(sampler2D tex, float2 uv)
            {
    
    
                float4 color = tex2D(tex, uv);
                
                // Chroma key to CYK conversion
                float key_cb = rgb2cb(_KeyColor.rgb);
                float key_cr = rgb2cr(_KeyColor.rgb);
                float pix_cb = rgb2cb(color.rgb);
                float pix_cr = rgb2cr(color.rgb);

                return colorclose(pix_cb, pix_cr, key_cb, key_cr, _ColorCutoff, _ColorFeathering);
            }

            //-------------------------

            v2f vert (appdata v)
            {
    
    
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
				//o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y) + o.vertex.w) * 0.5;
				//o.uvgrab.zw = o.vertex.zw;
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
    
    
                // Get pixel width
                float2 pixelWidth = float2(1.0 / _MainTex_TexelSize.z, 0);
                float2 pixelHeight = float2(0, 1.0 / _MainTex_TexelSize.w);


				//float2 uv = i.uv.xy;
				//half4 grab = GRABXYPIXEL(0,0);

                // Unmodified MainTex
                float4 color = tex2D(_MainTex, i.uv);

                // Unfeathered mask
                float mask = maskedTex2D(_MainTex, i.uv);

                // Feathering & smoothing
                float c = mask;
                float r = maskedTex2D(_MainTex, i.uv + pixelWidth);
                float l = maskedTex2D(_MainTex, i.uv - pixelWidth);
                float d = maskedTex2D(_MainTex, i.uv + pixelHeight); 
                float u = maskedTex2D(_MainTex, i.uv - pixelHeight);
                float rd = maskedTex2D(_MainTex, i.uv + pixelWidth + pixelHeight) * .707;
                float dl = maskedTex2D(_MainTex, i.uv - pixelWidth + pixelHeight) * .707;
                float lu = maskedTex2D(_MainTex, i.uv - pixelHeight - pixelWidth) * .707;
                float ur = maskedTex2D(_MainTex, i.uv + pixelWidth - pixelHeight) * .707;
                float blurContribution = (r + l + d + u + rd + dl + lu + ur + c) * 0.12774655;
                float smoothedMask = smoothstep(_Sharpening, 1, lerp(c, blurContribution, _MaskFeathering));
                float4 result = color * smoothedMask;

                // Despill
                float v = (2*result.b+result.r)/4;
                if(result.g > v) result.g = lerp(result.g, v, _Despill);
                float4 dif = (color - result);
                float desaturatedDif = rgb2y(dif.xyz);
                result += lerp(0, desaturatedDif, _DespillLuminanceAdd);
                
                return float4(result.xyz, smoothedMask);
            }
            ENDCG
        }
    }
}

Next, still in the Assets/Materail directory, customize a Material:
Insert image description here
Then, change the name, and then select the Material, and the Inspector panel will display its specific parameters. Its Shader is configured with Standard by default. Let's change it to Unlit -> ChromaKey.
Insert image description here
Where does this Unlit-> ChromaKey come from?
is defined in the first sentence of the shader script above:

Shader "Unlit/ChromaKey"

When you import this shader, this option will be displayed on the menu!

After selecting, the various options on the panel are closely related to the code:
Insert image description here
You can study the code carefully.

2.3 Material customization of RawImage

I added Material above, and now I can drag it to the Material option of Raw Image.
Insert image description here

2.4 Playback effect

Insert image description here
This is the playback effect I have here. You need to adjust some parameters of the arrow to ensure a perfect cutout effect. The default parameters may not be correct, or they may be masked or something.

Unity project source code

https://github.com/newchenxf/UnityCutGreenVideo

Guess you like

Origin blog.csdn.net/Chj1319261607/article/details/133885712