6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

3D SensorAdvent Calendar 2019

Day 13

AzureKinectでグリーンバック無しでクロマキー的な何か

Last updated at Posted at 2019-12-13

3D Sensor Advent Calendar 2019 の13日目の記事です。

##はじめに
LIVを使ってBeatSaberのMR動画を撮影してるときに、「これ自分でも実装できるんじゃないか??」と思ったのをきっかけに挑戦してみました。
2時間くらい頑張ったらサクッと出来たので記事を書いてみます。

出来たこと

環境

・Unity 2019.2.11.f
・Azure Kinect (Amazonで買った)

手順(ざっくり)

###1.ポイントクラウド表示
こちらの素晴らしいブログを参照してください。
 C#で始めるAzure Kinect開発⑥:Unity+C#でPoint Cloud表示

こんな感じに表示できるはず
K4A_NoGreenBack - AzureKinectSample - PC, Mac & Linux Standalone - Unity 2019.2.11f1 Personal_ OpenGL ES 3.2 2019-12-13 12-59-09_Moment.jpg

###2.クロマキー的な何か
今回のクロマキー的な何かはオブジェクトが重なった部分を描画しないようにして実現しました。
人物抽出ではなくて背景除去になります。

背景のみが映っている状態でポイントクラウドを複製、後述のシェーダーを適用したマテリアルに変更。
複製したポイントクラウドのPointSizeを少し大きくして、背景のポイントクラウドを覆うとこんな感じに。
K4A_NoGreenBack - AzureKinectSample - PC, Mac & Linux Standalone - Unity 2019.2.11f1 Personal_ OpenGL ES 3.2 2019-12-13 12-59-09_Moment(3).jpg

シェーダー素人なので、こちらの記事を参考にしました。
 【Unityシェーダ入門】オブジェクトが重なった部分をくり抜く

ポイントクラウド用に色々書き替えたのが以下です。

ColorutoutPoint.shader
Shader "Custom/ColorutoutPoint" {
	Properties{
	 _Size("ShaderSize", Float) = 1.000000
	 _PointSize("PointSize", Float) = 5.0
	 _Color("Color", Color) = (1,1,1,1)

	}
		SubShader{
		 Tags {"Queue" = "Geometry-1"}

		 Pass {
						Zwrite On
						ColorMask 0

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma target 2.0
		#include "UnityCG.cginc"
		#pragma multi_compile_fog
		#define USING_FOG (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))

		float _Size;
		float _PointSize;

		// uniforms
		// vertex shader input data
		struct appdata {
		  float3 pos : POSITION;
		  half4 color : COLOR;
		  UNITY_VERTEX_INPUT_INSTANCE_ID
		};

		// vertex-to-fragment interpolators
		struct v2f {
		  float psize : PSIZE;
		  fixed4 color : COLOR0;
		  #if USING_FOG
			fixed fog : TEXCOORD0;
		  #endif
		  float4 pos : SV_POSITION;
		  UNITY_VERTEX_OUTPUT_STEREO
		};

		// vertex shader
		v2f vert(appdata IN) {
			IN.pos.xyz = IN.pos.xyz * _Size;

		  v2f o;
		  UNITY_SETUP_INSTANCE_ID(IN);
		  UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
		  half4 color = IN.color;
		  float3 eyePos = mul(UNITY_MATRIX_MV, float4(IN.pos,1)).xyz;
		  half3 viewDir = 0.0;
		  o.color = saturate(color);
		  // compute texture coordinates
		  // fog
		  #if USING_FOG
			float fogCoord = length(eyePos.xyz); // radial fog distance
			UNITY_CALC_FOG_FACTOR_RAW(fogCoord);
			o.fog = saturate(unityFogFactor);
		  #endif
			// transform position
			o.pos = UnityObjectToClipPos(IN.pos);
			o.psize = _PointSize;
			return o;
		  }

		// fragment shader
		fixed4 frag(v2f IN) : SV_Target {
		  fixed4 col;
		  col = IN.color;
		  // fog
		  #if USING_FOG
			col.rgb = lerp(unity_FogColor.rgb, col.rgb, IN.fog);
		  #endif
		  return col;
		}
		ENDCG
		 }
	}
}
PointCloud.cs
        //背景除去用メッシュ生成
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (GameObject.Find("CutoutMesh"))
            {
                GameObject obj = GameObject.Find("CutoutMesh");
                Destroy(obj);
            }
            verticesGreenBack = vertices;
            greenBack = new GameObject();
            greenBack.name = "CutoutMesh";
            greenBack.AddComponent<MeshFilter>();
            meshRendererG = greenBack.AddComponent<MeshRenderer>();

            meshG = new Mesh();

            //65535点以上描画する際に下記を記述
            meshG.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

            //頂点座標と色をmeshに渡す
            meshG.vertices = verticesGreenBack;

            //リストに格納した番号の頂点座標を点として描画
            meshG.SetIndices(indices, MeshTopology.Points, 0);

            //メッシュをこのオブジェクトのMeshFilterに適用
            greenBack.GetComponent<MeshFilter>().mesh = meshG;

            meshRendererG.material = materialG;
        }

        // 削除
        if (Input.GetKey(KeyCode.Backspace))
        {
            GameObject obj = GameObject.Find("CutoutMesh");
            Destroy(obj);
        }

###3.おもむろにカメラの前へ。
いい感じに人だけ映る。

##さいごに
明日はtakminさんの「kalibrを使ってカメラ/IMUキャリブレーション」です。

6
3
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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?