質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • Unity

    4376questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

shaderについて

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 218

konpeitou_z2

score 4

現在unityでshaderを勉強しているものです。
shaderで2値表示をしたいと思っています。
以下のサイト
https://ics.media/entry/5535
を参考にし、
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
float d = c.x * 0.298912f + c.y * 0.586611f + c.z * 0.114478;

とし、
if (x <= d && d <= y) {
o.Albedo = 1.0;
}
として適切なxとyの値を使えばできるのではないかと思いました。
しかし肌色の場合どのようなxとyを使えばよいか調べ方が分かりませんでした。
なので
肌色の場合のx,v (できればその他の色の場合の調べ方)
が知りたいです。
また特定の色の2値表示はこのようなやり方でいいのかも気になりました。
分かる方いましたらどうか宜しくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

発想としては悪くないかと思うのですが、ご提示のやり方ですと、まず色をグレースケールにしてからその明るさだけを頼りに目的の色の領域を抜き出すという形ですので、色合いが大きく異なるのに明るさが近いような場合の区別が困難かと思います。何らかの形で色合いを考慮に入れないと、うまく目的色だけを抜き出すことは難しいのではないでしょうか。

即興ですが、

Shader "Unlit/ExtractAreaByColor"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _RefColor("Reference Color", Color) = (1.0, 1.0, 1.0, 1.0) // 抜き出したい色
        _DotThreshold("Dot Threshold", Float) = 0.01 // 色合いの許容度
        _DistanceThreshold("Distance Threshold", Float) = 0.5 // 明るさの許容度
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        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;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _RefColor;
            float _DotThreshold;
            float _DistanceThreshold;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 sampledColor = tex2D(_MainTex, i.uv).rgb; // テクスチャからサンプリングされた色
                float sampledColorDistance = length(sampledColor); // テクスチャ色の黒色からの距離...明るさの指標とする
                float3 sampledColorDirection = sampledColor / sampledColorDistance; // テクスチャ色の方角...色合いの指標とする

                float3 referenceColor = _RefColor.rgb; // 目的の色
                float referenceColorDistance = length(referenceColor); // 目的色の黒色からの距離...明るさの指標とする
                float3 referenceColorDirection = referenceColor / referenceColorDistance; // 目的色の方角...色合いの指標とする

                float colorDistance = abs(sampledColorDistance - referenceColorDistance); // 黒からの距離の差の絶対値...明るさが近いほど0に近づく
                float colorDot = dot(sampledColorDirection, referenceColorDirection); // 方角の内積...色合いが近いほど1に近づく

                float distanceMask = step(colorDistance, _DistanceThreshold); // 距離差がしきい値以下ならば1、さもなくば0
                float dotMask = step(1.0 - _DotThreshold, colorDot); // 方角内積が1-しきい値以上ならば1、さもなくば0

                float result = distanceMask * dotMask; // マスクの積...両者ともに1なら1、さもなくば0

                return fixed4(result, result, result, 1.0);
            }
            ENDCG
        }
    }
}


こんなようなものでもいくらかは特定の色を狙って抽出できるかと思います。

パラメーター設定例
例1

もっと精度よく抜き出したいとなると、コンピュータビジョン関連の論文を探してみるのがいいのではないでしょうか。
ちょっと検索したところ引っかかったA New System for Extracting and Detecting Skin Color Regions from PDF Documents, Tarek Abd El-Hafeezでは、内容はよく読んでいませんがHSV色空間に変換した上で色相やら彩度やらが一定範囲内にあるかどうかで判定しているようです。

            fixed4 frag(v2f i) : SV_Target
            {
                // 色空間を変換して肌色検出、オリジナルのコードをシェーダー向けに改造

                // A New System for Extracting and Detecting Skin Color Regions from PDF Documents
                // Tarek Abd El-Hafeez
                // International Journal on Computer Science and Engineering Vol. 02, No. 09, 2010, 2838 - 2846
                // Figure 11: The algorithm of the modified HSV technique for detecting skin color regions. 

                float3 c = tex2D(_MainTex, i.uv).rgb * 255.0;

                float I = dot(float3(0.596, -0.274, -0.322), c);
                float V = max(c.r, max(c.g, c.b));
                float D = V - min(c.r, min(c.g, c.b));
                float S = D / V;
                float3 H3 = float3(c.g - c.b, 2.0 - c.r + c.b, 4.0 - c.g + c.r) / (6.0 * D);
                float H = dot(floor(c / V) * H3, 1.0 - floor(saturate(dot(normalize(c), 1.0))));

                float result = step(0.20, S) * step(S, 0.75) * step(0.35, V) * step(0.0, H) * step(H, 25.0) * step(I, 90.0) * step(20.0, I);

                return fixed4(result, result, result, 1.0);
            }

Figure 11のコードを使った場合
※ちゃんと移植できたか自信がないので、オリジナルの論文をご覧になった方がいいかと思います...
例2

やはり撮影条件や背景によって抽出難易度はころころ変わってしまうようですね。うまくやるにはいろいろと試行錯誤が必要そうです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Unity

    4376questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。