🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

Q&A

解決済

2回答

1523閲覧

Unity : ウェブカメラで取得した画像から黒色以外を白に

hideyuki_aka

総合スコア6

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

0グッド

0クリップ

投稿2019/11/11 14:58

前提・実現したいこと

Unityで、影を用いたインタラクティブなゲームを制作しております。

以前にこちらの質問で、ウェブカメラの画像を2値化して黒い部分にのみポリゴンコライダーを当てることをサポートさせていただきました。

しかし、それでは以下の画像のようなピンクや青といった彩度・明度の高い他のオブジェクトも
認識してしまい、2値化処理が行われ続けるほどに画面が真っ黒になります。

今回は、ウェブカメラの画像であらかじめ黒以外を白(0,0,0)に置き換えする前処理がしたく、質問を投稿しました。イメージ説明

宜しくお願い致します!

追記

上画像では顔が白抜きになっていますが、本来は影を読み取るので真っ黒です。
シルエットをウェブカメラで取得します。

試したこと

2値化する際の、閾値を調整しましたがやはり周辺のオブジェクトは残るままで
改善できませんでした。

補足情報(FW/ツールのバージョンなど)

Unity2019.2.5f1 Personal
macOS Sierra

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

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

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

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

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

Bongo

2019/11/11 21:39

以前のご質問だとWebカメラで被写体自身を撮影されていたようですが、今回は状況がちょっと違うということでしょうかね? ご質問文から想像しますに、「プロジェクターがスクリーンに映像を投射する...プロジェクターは被写体の影を作るための光源も兼ねており、スクリーンには投射した映像と被写体の影が重なった状態になる」→「Webカメラは被写体自身は映らないように配置して、スクリーンを撮影する」→「Webカメラが撮影した映像から被写体の影だけを抽出して利用する」といった感じでしょうか。 閾値調整だけだとうまくいかなかったようですが、詳しくはどのような様子でしょうか?閾値を下げるほど周辺のオブジェクトは除外されていくと思うのですが、オブジェクトが全部除外されるほど閾値を下げると被写体の影まで削れ始めてしまう...というような状況でしょうか。
hideyuki_aka

2019/11/11 23:42

Bongo様、ありがとうございます。 構成ならびに問題は全くのその通りでございます。少し表現をややこしくしてしまいました。 周りのオブジェクトが消えるまで閾値を下げていくと影が細ってしまい、ほとんど消えてしまいます。 そこで、ウェブカメラの映像から周りのオブジェクトを前処理できたらと考えました。
guest

回答2

0

ベストアンサー

四隅調整機能追加版

ShaderLab

1Shader "Hidden/Silhouette" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 _Color ("Color", Color) = (0, 0, 0, 1) 7 _SaturationThreshold ("Saturation Threshold", Range(0.0, 1.0)) = 0.25 8 _ValueThreshold ("Value Threshold", Range(0.0, 1.0)) = 0.25 9 } 10 SubShader 11 { 12 Cull Off ZWrite Off ZTest Always 13 14 Pass 15 { 16 CGPROGRAM 17 #pragma vertex vert 18 #pragma fragment frag 19 20 #include "UnityCG.cginc" 21 22 struct appdata 23 { 24 float4 vertex : POSITION; 25 float2 uv : TEXCOORD0; 26 }; 27 28 struct v2f 29 { 30 // UV座標をfloat4型に変更 31 float4 uv : TEXCOORD0; 32 float4 vertex : SV_POSITION; 33 }; 34 35 // UV変換用行列をセットするための変数を追加 36 float4x4 _HomographyMatrix; 37 38 v2f vert (appdata v) 39 { 40 v2f o; 41 o.vertex = UnityObjectToClipPos(v.vertex); 42 43 // 元のUV座標をUV変換用行列で変換してからセットする 44 o.uv = mul(_HomographyMatrix, float4(v.uv, 0.0, 1.0)); 45 46 return o; 47 } 48 49 sampler2D _MainTex; 50 float4 _Color; 51 float _SaturationThreshold; 52 float _ValueThreshold; 53 54 fixed4 frag (v2f i) : SV_Target 55 { 56 // Webカメラ上の色をtex2Dに代わってtex2Dprojでサンプリングする 57 float3 rawColor = tex2Dproj(_MainTex, i.uv).rgb; 58 59 float value = max(max(rawColor.r, rawColor.g), rawColor.b); 60 float lowestValue = min(min(rawColor.r, rawColor.g), rawColor.b); 61 float difference = value - lowestValue; 62 float saturation = (value > 0.01) ? (difference / value) : 0.0; 63 return fixed4(_Color.rgb, step(value, _ValueThreshold) * step(saturation, _SaturationThreshold)); 64 } 65 ENDCG 66 } 67 68 Pass 69 { 70 CGPROGRAM 71 #pragma vertex vert 72 #pragma fragment frag 73 74 #include "UnityCG.cginc" 75 76 struct appdata 77 { 78 float4 vertex : POSITION; 79 }; 80 81 struct v2f 82 { 83 float4 vertex : SV_POSITION; 84 }; 85 86 v2f vert (appdata v) 87 { 88 v2f o; 89 o.vertex = UnityObjectToClipPos(v.vertex); 90 return o; 91 } 92 93 float4 _Color; 94 95 fixed4 frag (v2f i) : SV_Target 96 { 97 return fixed4(_Color.rgb, 1.0); 98 } 99 ENDCG 100 } 101 } 102}

C#

1using System.Collections; 2using UnityEngine; 3 4[RequireComponent(typeof(SpriteRenderer), typeof(PolygonCollider2D))] 5public class Silhouette : MonoBehaviour 6{ 7 private static readonly int SaturationThresholdProperty = Shader.PropertyToID("_SaturationThreshold"); 8 private static readonly int ValueThresholdProperty = Shader.PropertyToID("_ValueThreshold"); 9 private static readonly int HomographyMatrixProperty = Shader.PropertyToID("_HomographyMatrix"); 10 11 [SerializeField] private int width = 320; 12 [SerializeField] private int height = 240; 13 [SerializeField] private int floorHeight = 16; 14 [SerializeField] private int resolutionMultiplier = 1; 15 [SerializeField] private Color color = Color.black; 16 [SerializeField][Range(0.0f, 1.0f)] private float saturationThreshold = 0.25f; 17 [SerializeField][Range(0.0f, 1.0f)] private float valueThreshold = 0.25f; 18 [SerializeField] private Shader silhouetteShader; 19 20 // 四隅の位置を指定するためのフィールドを追加 21 [Header("Corners")] 22 [SerializeField] private Vector2 bottomLeft = new Vector2(0.125f, 0.0625f); 23 [SerializeField] private Vector2 topLeft = new Vector2(0.1875f, 0.875f); 24 [SerializeField] private Vector2 topRight = new Vector2(0.75f, 0.75f); 25 [SerializeField] private Vector2 bottomRight = new Vector2(0.9375f, 0.375f); 26 27 private new SpriteRenderer renderer; 28 private new PolygonCollider2D collider; 29 private Sprite sprite; 30 private Texture2D spriteTexture; 31 private Material silhouetteMaterial; 32 private WebCamTexture webCamTexture; 33 34 // 以前作成したHomographyShaderGUIのものと同様の変換行列作成メソッドを定義 35 private static Matrix4x4 HomographyMatrix(Vector2 bl, Vector2 tl, Vector2 tr, Vector2 br) 36 { 37 var cf = bl; 38 Inverse(br - tr, tl - tr, out var ghMatR0, out var ghMatR1); 39 var v = (bl + tr) - (tl + br); 40 var gh = new Vector2(Vector2.Dot(ghMatR0, v), Vector2.Dot(ghMatR1, v)); 41 var ad = ((gh.x + 1.0f) * br) - bl; 42 var be = ((gh.y + 1.0f) * tl) - bl; 43 var result = Matrix4x4.identity; 44 result.SetColumn(0, new Vector4(ad.x, ad.y, 0.0f, gh.x)); 45 result.SetColumn(1, new Vector4(be.x, be.y, 0.0f, gh.y)); 46 result.SetColumn(2, new Vector4(0.0f, 0.0f, 1.0f, 0.0f)); 47 result.SetColumn(3, new Vector4(cf.x, cf.y, 0.0f, 1.0f)); 48 return result; 49 } 50 51 private static void Inverse(Vector2 column0, Vector2 column1, out Vector2 inverseRow0, out Vector2 inverseRow1) 52 { 53 var determinant = Cross(column0, column1); 54 inverseRow0 = new Vector2(column1.y, -column1.x) / determinant; 55 inverseRow1 = new Vector2(-column0.y, column0.x) / determinant; 56 } 57 58 private static float Cross(Vector2 a, Vector2 b) 59 { 60 return (a.x * b.y) - (b.x * a.y); 61 } 62 63 private IEnumerator Start() 64 { 65 if (WebCamTexture.devices.Length <= 0) 66 { 67 Destroy(this); 68 yield break; 69 } 70 this.width = Mathf.Max(this.width, 100); 71 this.height = Mathf.Max(this.height, 100); 72 this.webCamTexture = new WebCamTexture(WebCamTexture.devices[0].name, this.width, this.height); 73 this.webCamTexture.Play(); 74 while (this.webCamTexture.width < 100) 75 { 76 yield return null; 77 } 78 79 this.width = this.webCamTexture.width * this.resolutionMultiplier; 80 this.height = this.webCamTexture.height * this.resolutionMultiplier; 81 var pixelsPerUnit = (float)this.height; 82 var mainCamera = Camera.main; 83 if (mainCamera.orthographic) 84 { 85 pixelsPerUnit = (0.5f * Screen.height * this.resolutionMultiplier) / mainCamera.orthographicSize; 86 } 87 88 this.renderer = this.GetComponent<SpriteRenderer>(); 89 this.collider = this.GetComponent<PolygonCollider2D>(); 90 this.spriteTexture = new Texture2D(this.width, this.height, TextureFormat.ARGB32, false); 91 this.sprite = Sprite.Create( 92 this.spriteTexture, 93 new Rect(0, 0, this.width, this.height), 94 Vector2.zero, 95 pixelsPerUnit); 96 this.renderer.sprite = this.sprite; 97 98 this.silhouetteMaterial = new Material(this.silhouetteShader); 99 100 // 下のwhileループ中でマテリアルのプロパティをセットする方式ならば、プレイモード中に 101 // インスペクタ上の値を書き換えるとそれが反映されるため調整が容易かと思いますが 102 // (ただしコライダーを常時付け外ししているため、再生状態のままでは書き換えが 103 // 困難かと思います...一時停止ボタンで止めた状態で書き換える必要があるでしょう)、 104 // あらかた調整が済んだら、マテリアルへのプロパティ設定をwhileループの外に出してやれば 105 // ループ内でいちいちプロパティ再設定が行われなくなるため、実行する上での効率が少しだけ 106 // よくなるかと思います。 107 /* 108 this.silhouetteMaterial.color = this.color; 109 this.silhouetteMaterial.SetFloat(SaturationThresholdProperty, this.saturationThreshold); 110 this.silhouetteMaterial.SetFloat(ValueThresholdProperty, this.valueThreshold); 111 112 // 四隅の座標からUV変換行列を作成してマテリアルにセットする 113 this.silhouetteMaterial.SetMatrix(HomographyMatrixProperty, HomographyMatrix( 114 this.bottomLeft, 115 this.topLeft, 116 this.topRight, 117 this.bottomRight)); 118 */ 119 120 while (true) 121 { 122 this.silhouetteMaterial.color = this.color; 123 this.silhouetteMaterial.SetFloat(SaturationThresholdProperty, this.saturationThreshold); 124 this.silhouetteMaterial.SetFloat(ValueThresholdProperty, this.valueThreshold); 125 126 // 四隅の座標からUV変換行列を作成してマテリアルにセットする 127 this.silhouetteMaterial.SetMatrix(HomographyMatrixProperty, HomographyMatrix( 128 this.bottomLeft, 129 this.topLeft, 130 this.topRight, 131 this.bottomRight)); 132 133 var renderTexture = RenderTexture.GetTemporary(this.width, this.height, 0, RenderTextureFormat.ARGB32); 134 Graphics.Blit(this.webCamTexture, renderTexture, this.silhouetteMaterial, 0); 135 var activeTexture = RenderTexture.active; 136 RenderTexture.active = renderTexture; 137 138 var floorY = ((float)(this.floorHeight * this.resolutionMultiplier) / this.height); 139 GL.PushMatrix(); 140 this.silhouetteMaterial.SetPass(1); 141 GL.Begin(GL.QUADS); 142 GL.LoadOrtho(); 143 GL.Color(this.color); 144 GL.Vertex(Vector3.zero); 145 GL.Vertex3(0.0f, floorY, 0.0f); 146 GL.Vertex3(1.0f, floorY, 0.0f); 147 GL.Vertex(Vector3.right); 148 GL.End(); 149 GL.PopMatrix(); 150 151 this.spriteTexture.ReadPixels(new Rect(0, 0, this.width, this.height), 0, 0); 152 RenderTexture.active = activeTexture; 153 RenderTexture.ReleaseTemporary(renderTexture); 154 this.spriteTexture.Apply(); 155 156 Destroy(this.collider); 157 this.collider = this.gameObject.AddComponent<PolygonCollider2D>(); 158 yield return null; 159 } 160 } 161}

投稿2019/11/16 18:02

Bongo

総合スコア10811

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

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

hideyuki_aka

2019/11/20 15:26

ありがとうございます!! 実装することができました。 何から何まで教えていただきありがとうございます。 これでおおもとのシステムは出来上がりました。
guest

0

おそらく、周囲のオブジェクトの色を影と誤認識されないような色だけにしてしまうのがいいんじゃないかと思います。

現状だと、特に頭の横に浮かんでいる赤黒い球なんかは厳しいんじゃないでしょうか。
ご提示の画像の状態でもかなり影の色に近いうえに、実際にはこの映像をスクリーンに映してWebカメラで撮影するというプロセスが入ることを考慮するとさらに難しくなるはずです。微妙な色の差を識別するために判定を厳しくすれば、今度は影の部分が撮影条件の微妙な変動などにより判定に落ちてしまうリスクが大きくなるでしょう。

グレースケール化して視覚的明るさだけで二値判定するのではなく、たとえば色相・彩度・明度の3成分を利用すればいくらかは精度を高められるかもしれませんが、それでも劇的な改善は見込めないように思います。
今回の場合はかなり黒に近い色について判定を行いたいという状況ですが、このような領域だと色相・彩度が不確かになって(極端な話だと、完全な真っ黒では色相・彩度がちゃんと定義できなくなってしまうはずです)、色判定の材料としてはあまり役に立たないんじゃないでしょうか。

以前お出ししました二値化スクリプトを彩度・明度を使って判定するよう改造してみました(色相は計算コストが大きめなわりに前述の理由から有用でなさそうだったため省きました)。
試した感じでは、以前の加重平均によるグレースケール化からの二値化と比べると鮮やかな色を除去する効果が上がったように思います(鮮やかな色は赤・緑・青のいずれにしろ高めの成分を持っているはずなので、明度も高くなり除去されやすくなるはずです)。主に調整するべきは明度の閾値で、彩度による判定は甘めでいいかもしれませんね。ですがそれでもご提示の画像のような赤黒い色を影の色と区別するのは困難そうです...

ShaderLab

1Shader "Hidden/Silhouette" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 _Color ("Color", Color) = (0, 0, 0, 1) 7 _SaturationThreshold ("Saturation Threshold", Range(0.0, 1.0)) = 0.25 8 _ValueThreshold ("Value Threshold", Range(0.0, 1.0)) = 0.25 9 } 10 SubShader 11 { 12 Cull Off ZWrite Off ZTest Always 13 14 Pass 15 { 16 CGPROGRAM 17 #pragma vertex vert 18 #pragma fragment frag 19 20 #include "UnityCG.cginc" 21 22 struct appdata 23 { 24 float4 vertex : POSITION; 25 float2 uv : TEXCOORD0; 26 }; 27 28 struct v2f 29 { 30 float2 uv : TEXCOORD0; 31 float4 vertex : SV_POSITION; 32 }; 33 34 v2f vert (appdata v) 35 { 36 v2f o; 37 o.vertex = UnityObjectToClipPos(v.vertex); 38 o.uv = v.uv; 39 return o; 40 } 41 42 sampler2D _MainTex; 43 float4 _Color; 44 float _SaturationThreshold; 45 float _ValueThreshold; 46 47 float3 RGBToHSV(float3 rgbColor) 48 { 49 float value = max(max(rgbColor.r, rgbColor.g), rgbColor.b); 50 if (value <= 0.0) 51 { 52 return 0.0; 53 } 54 55 float lowestValue = min(min(rgbColor.r, rgbColor.g), rgbColor.b); 56 float difference = value - lowestValue; 57 if (difference <= 0.0) 58 { 59 return float3(0.0, 0.0, value); 60 } 61 62 float saturation = difference / value; 63 float highestIndex = value == rgbColor.r ? 0 : (value == rgbColor.g ? 1 : 2); 64 float hue = ((highestIndex * 2) + (rgbColor[(highestIndex + 1) % 3] - rgbColor[(highestIndex + 2) % 3]) / difference) / 6.0; 65 hue = fmod(hue + 1.0, 1.0); 66 return float3(hue, saturation, value); 67 } 68 69 fixed4 frag (v2f i) : SV_Target 70 { 71 float3 rawColor = tex2D(_MainTex, i.uv).rgb; 72 73 // 彩度、明度を求める 74 float value = max(max(rawColor.r, rawColor.g), rawColor.b); 75 float lowestValue = min(min(rawColor.r, rawColor.g), rawColor.b); 76 float difference = value - lowestValue; 77 float saturation = (value > 0.01) ? (difference / value) : 0.0; 78 79 // 彩度、明度ともにしきい値以下ならアルファ1.0、さもなくば0.0 80 return fixed4(_Color.rgb, step(value, _ValueThreshold) * step(saturation, _SaturationThreshold)); 81 } 82 ENDCG 83 } 84 85 Pass 86 { 87 CGPROGRAM 88 #pragma vertex vert 89 #pragma fragment frag 90 91 #include "UnityCG.cginc" 92 93 struct appdata 94 { 95 float4 vertex : POSITION; 96 }; 97 98 struct v2f 99 { 100 float4 vertex : SV_POSITION; 101 }; 102 103 v2f vert (appdata v) 104 { 105 v2f o; 106 o.vertex = UnityObjectToClipPos(v.vertex); 107 return o; 108 } 109 110 float4 _Color; 111 112 fixed4 frag (v2f i) : SV_Target 113 { 114 return fixed4(_Color.rgb, 1.0); 115 } 116 ENDCG 117 } 118 } 119}

C#

1using System.Collections; 2using UnityEngine; 3 4[RequireComponent(typeof(SpriteRenderer), typeof(PolygonCollider2D))] 5public class Silhouette : MonoBehaviour 6{ 7 private static readonly int SaturationThreshold = Shader.PropertyToID("_SaturationThreshold"); 8 private static readonly int ValueThreshold = Shader.PropertyToID("_ValueThreshold"); 9 10 [SerializeField] private int width = 320; 11 [SerializeField] private int height = 240; 12 [SerializeField] private int floorHeight = 16; 13 [SerializeField] private int resolutionMultiplier = 1; 14 [SerializeField] private Color color = Color.black; 15 16 // 彩度のしきい値 17 // これよりも彩度が高ければ除外する 18 [SerializeField][Range(0.0f, 1.0f)] private float saturationThreshold = 0.25f; 19 20 // 明度のしきい値 21 // これよりも明度が高ければ除外する 22 [SerializeField][Range(0.0f, 1.0f)] private float valueThreshold = 0.25f; 23 24 [SerializeField] private Shader silhouetteShader; 25 26 private new SpriteRenderer renderer; 27 private new PolygonCollider2D collider; 28 private Sprite sprite; 29 private Texture2D spriteTexture; 30 private Material silhouetteMaterial; 31 private WebCamTexture webCamTexture; 32 33 private IEnumerator Start() 34 { 35 if (WebCamTexture.devices.Length <= 0) 36 { 37 Destroy(this); 38 yield break; 39 } 40 this.width = Mathf.Max(this.width, 100); 41 this.height = Mathf.Max(this.height, 100); 42 this.webCamTexture = new WebCamTexture(WebCamTexture.devices[0].name, this.width, this.height); 43 this.webCamTexture.Play(); 44 while (this.webCamTexture.width < 100) 45 { 46 yield return null; 47 } 48 49 this.width = this.webCamTexture.width * this.resolutionMultiplier; 50 this.height = this.webCamTexture.height * this.resolutionMultiplier; 51 var pixelsPerUnit = (float)this.height; 52 var mainCamera = Camera.main; 53 if (mainCamera.orthographic) 54 { 55 pixelsPerUnit = (0.5f * Screen.height * this.resolutionMultiplier) / mainCamera.orthographicSize; 56 } 57 58 this.renderer = this.GetComponent<SpriteRenderer>(); 59 this.collider = this.GetComponent<PolygonCollider2D>(); 60 this.spriteTexture = new Texture2D(this.width, this.height, TextureFormat.ARGB32, false); 61 this.sprite = Sprite.Create( 62 this.spriteTexture, 63 new Rect(0, 0, this.width, this.height), 64 Vector2.zero, 65 pixelsPerUnit); 66 this.renderer.sprite = this.sprite; 67 68 this.silhouetteMaterial = new Material(this.silhouetteShader); 69 while (true) 70 { 71 this.silhouetteMaterial.color = this.color; 72 73 // 二値化に使うパラメーターとして、従来の_Thresholdに代わって 74 // 彩度のしきい値(_SaturationThreshold)、明度のしきい値(_ValueThreshold)の2つを渡す 75 this.silhouetteMaterial.SetFloat(SaturationThreshold, this.saturationThreshold); 76 this.silhouetteMaterial.SetFloat(ValueThreshold, this.valueThreshold); 77 78 var renderTexture = RenderTexture.GetTemporary(this.width, this.height, 0, RenderTextureFormat.ARGB32); 79 Graphics.Blit(this.webCamTexture, renderTexture, this.silhouetteMaterial, 0); 80 var activeTexture = RenderTexture.active; 81 RenderTexture.active = renderTexture; 82 83 var floorY = ((float)(this.floorHeight * this.resolutionMultiplier) / this.height); 84 GL.PushMatrix(); 85 this.silhouetteMaterial.SetPass(1); 86 GL.Begin(GL.QUADS); 87 GL.LoadOrtho(); 88 GL.Color(this.color); 89 GL.Vertex(Vector3.zero); 90 GL.Vertex3(0.0f, floorY, 0.0f); 91 GL.Vertex3(1.0f, floorY, 0.0f); 92 GL.Vertex(Vector3.right); 93 GL.End(); 94 GL.PopMatrix(); 95 96 this.spriteTexture.ReadPixels(new Rect(0, 0, this.width, this.height), 0, 0); 97 RenderTexture.active = activeTexture; 98 RenderTexture.ReleaseTemporary(renderTexture); 99 this.spriteTexture.Apply(); 100 101 Destroy(this.collider); 102 this.collider = this.gameObject.AddComponent<PolygonCollider2D>(); 103 yield return null; 104 } 105 } 106}

投稿2019/11/12 05:24

Bongo

総合スコア10811

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

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

hideyuki_aka

2019/11/16 05:32

ご連絡が遅くなり申し訳ございません。 実際に組み込んでみましたが、前回よりも狙った2値化を行うことができました。 周辺に表示させるオブジェクトも閾値を下回る色に限定してランダム生成するように設計変更いたしました。 また、本サイト内でBongo様がい回答されたページを拝見しました(https://teratail.com/questions/88695) 私の場合、カメラをスクリーンの上方に設置して映像を得るため、射影変換をする必要があります。 組み込もうとスクリプトを書き入れてみましたが、Shilouetteというオブジェクトに追加しようとすると、「Can't add script behaviour HomographyShaderGUI. The script needs to derive from MonoBehaviour!」と表示されます。しかしMonobehaviourを継承すると、OnGUIの定義がなかったりとビルドに失敗します。 重ね重ねで申し訳ないですが、回答頂けますでしょうか よろしくお願いいたします。
hideyuki_aka

2019/11/16 06:46 編集

すみません、マテリアルにHomography.shaderをアタッチして、2値化した映像を表示するゲームオブジェクトのマテリアルに設定したらできました。 が、射影変換のC#スクリプトがどこに紐づいているのかがわからないのと これでは、PolygonCollider2Dが更新されないため、spriteに適用するのではなく webcamtextureに適用しなければいけないのでしょうか?
Bongo

2019/11/16 18:03

あちらの回答で提示しましたコードをそのまま使うよりも、Silhouetteと合体させてしまった方が楽な気がします。 シェーダー側はUV座標変換行列を受け取れるようにして、それを使ってUV座標を変換した上でWebカメラから色を取得することにし、スクリプト側には四隅のUV座標用のフィールドを追加、それらからUV座標変換行列を作成してシェーダーに渡すようにしてはいかがでしょうか。改造案を検討してみました(字数制限に達してしまったため別回答に記入しました)。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問