LoginSignup
17
17

More than 5 years have passed since last update.

クロマキー抽出で人の肌色を抽出するシェーダ

Last updated at Posted at 2016-07-09

オノッチ https://twitter.com/onotchi_ さんのこちら http://onoty3d.hatenablog.com/entry/2016/02/06/141002 の記事を元にして、クロマキー合成(クロマキー透過)ではなくクロマキー抽出で肌の色を取り出すシェーダを作ってみた

ChromaKeyOverlay.shader

Shader "Custom/ChromaKeyOverlay" {
    Properties{
        _KeyColor("Key Color", Color) = (0,1,0)
        _HueNear("Hue Near", Range(0, 0.5)) = 0.1
        _SatNear("Saturation Near", Range(0, 0.5)) = 0.1
        _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
    }

        SubShader{
        Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }

        CGPROGRAM
#pragma surface surf Lambert alpha

        sampler2D _MainTex;
    fixed3 _KeyColor;
    fixed _HueNear;
    fixed _SatNear;

    struct Input {
        float2 uv_MainTex;
    };

    fixed GetHue(fixed3 rgb) {
        fixed hue = 0;
        fixed minValue = min(rgb.r, min(rgb.g, rgb.b));
        fixed maxValue = max(rgb.r, max(rgb.g, rgb.b));
        fixed delta = maxValue - minValue;
        if (delta != 0) {
            if (maxValue == rgb.r) {
                hue = (rgb.g - rgb.b) / delta;
            }
            else if (maxValue == rgb.g) {
                hue = 2.0 + (rgb.b - rgb.r) / delta;
            }
            else {
                hue = 4.0 + (rgb.r - rgb.g) / delta;
            }

            hue /= 6.0;

            if (hue < 0) {
                hue += 1.0;
            }
        }
        return hue;
    }

    fixed GetSaturation(fixed3 rgb) {
        fixed sat = 0;
        fixed minValue = min(rgb.r, min(rgb.g, rgb.b));
        fixed maxValue = max(rgb.r, max(rgb.g, rgb.b));
        sat = (maxValue - minValue) / maxValue;

        return sat;
    }

    void surf(Input IN, inout SurfaceOutput o) {
        fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
        fixed distance = GetHue(c.rgb) - GetHue(_KeyColor);
        fixed distance2 = GetSaturation(_KeyColor)- GetSaturation(c.rgb);
        fixed alpha = 0.0;
        if (distance > 0.5) {
            distance = 1.0 - distance;
        }
        else if (distance < -0.5) {
            distance = 1.0 + distance;
        }
        else {
            distance = abs(distance);
        }

        clip(_HueNear - distance);
        clip(_SatNear - distance2);
        alpha = ((_HueNear - distance)/ _HueNear +(_SatNear - distance2)/ _SatNear)*1.0;
        o.Albedo = c.rgb;
        o.Alpha = alpha;
    }

    ENDCG
    }

        Fallback "Transparent/Diffuse"
}

Webカメラ画像をリアルタイム表示するRenderTextureにこのシェーダーを適用したマテリアルを割り当てると、手など肌の色だけが取り出されて他の部分は透過になる

17
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17