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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

1回答

1151閲覧

shaderについて

konpeitou_z2

総合スコア12

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2018/05/01 12:22

編集2022/01/12 10:55

現在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値表示はこのようなやり方でいいのかも気になりました。
分かる方いましたらどうか宜しくお願い致します。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

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

即興ですが、

HLSL

1Shader "Unlit/ExtractAreaByColor" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 _RefColor("Reference Color", Color) = (1.0, 1.0, 1.0, 1.0) // 抜き出したい色 7 _DotThreshold("Dot Threshold", Float) = 0.01 // 色合いの許容度 8 _DistanceThreshold("Distance Threshold", Float) = 0.5 // 明るさの許容度 9 } 10 SubShader 11 { 12 Tags { "RenderType"="Opaque" } 13 LOD 100 14 15 Pass 16 { 17 CGPROGRAM 18 #pragma vertex vert 19 #pragma fragment frag 20 21 #include "UnityCG.cginc" 22 23 struct appdata 24 { 25 float4 vertex : POSITION; 26 float2 uv : TEXCOORD0; 27 }; 28 29 struct v2f 30 { 31 float2 uv : TEXCOORD0; 32 float4 vertex : SV_POSITION; 33 }; 34 35 sampler2D _MainTex; 36 float4 _MainTex_ST; 37 fixed4 _RefColor; 38 float _DotThreshold; 39 float _DistanceThreshold; 40 41 v2f vert (appdata v) 42 { 43 v2f o; 44 o.vertex = UnityObjectToClipPos(v.vertex); 45 o.uv = TRANSFORM_TEX(v.uv, _MainTex); 46 return o; 47 } 48 49 fixed4 frag (v2f i) : SV_Target 50 { 51 float3 sampledColor = tex2D(_MainTex, i.uv).rgb; // テクスチャからサンプリングされた色 52 float sampledColorDistance = length(sampledColor); // テクスチャ色の黒色からの距離...明るさの指標とする 53 float3 sampledColorDirection = sampledColor / sampledColorDistance; // テクスチャ色の方角...色合いの指標とする 54 55 float3 referenceColor = _RefColor.rgb; // 目的の色 56 float referenceColorDistance = length(referenceColor); // 目的色の黒色からの距離...明るさの指標とする 57 float3 referenceColorDirection = referenceColor / referenceColorDistance; // 目的色の方角...色合いの指標とする 58 59 float colorDistance = abs(sampledColorDistance - referenceColorDistance); // 黒からの距離の差の絶対値...明るさが近いほど0に近づく 60 float colorDot = dot(sampledColorDirection, referenceColorDirection); // 方角の内積...色合いが近いほど1に近づく 61 62 float distanceMask = step(colorDistance, _DistanceThreshold); // 距離差がしきい値以下ならば1、さもなくば0 63 float dotMask = step(1.0 - _DotThreshold, colorDot); // 方角内積が1-しきい値以上ならば1、さもなくば0 64 65 float result = distanceMask * dotMask; // マスクの積...両者ともに1なら1、さもなくば0 66 67 return fixed4(result, result, result, 1.0); 68 } 69 ENDCG 70 } 71 } 72}

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

パラメーター設定例
例1

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

HLSL

1 fixed4 frag(v2f i) : SV_Target 2 { 3 // 色空間を変換して肌色検出、オリジナルのコードをシェーダー向けに改造 4 5 // A New System for Extracting and Detecting Skin Color Regions from PDF Documents 6 // Tarek Abd El-Hafeez 7 // International Journal on Computer Science and Engineering Vol. 02, No. 09, 2010, 2838 - 2846 8 // Figure 11: The algorithm of the modified HSV technique for detecting skin color regions. 9 10 float3 c = tex2D(_MainTex, i.uv).rgb * 255.0; 11 12 float I = dot(float3(0.596, -0.274, -0.322), c); 13 float V = max(c.r, max(c.g, c.b)); 14 float D = V - min(c.r, min(c.g, c.b)); 15 float S = D / V; 16 float3 H3 = float3(c.g - c.b, 2.0 - c.r + c.b, 4.0 - c.g + c.r) / (6.0 * D); 17 float H = dot(floor(c / V) * H3, 1.0 - floor(saturate(dot(normalize(c), 1.0)))); 18 19 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); 20 21 return fixed4(result, result, result, 1.0); 22 }

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

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

投稿2018/05/01 20:00

編集2018/05/01 20:32
Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問