次のソフトウェアがインストールされていることを前提条件とします。インストールのパスが異なる場合は適宜読み替えて下さい。
Visual Studio 2017 Professional/Community を使う場合は、 「C++ によるデスクトップ開発」の「Windows 8.1 SDK と UCRT SDK」オプションが必要 |
実行ファイルのパス | C:\opencv\bin | <-- 環境変数のPathに追加しておくこと |
インクルードファイルのパス | C:\opencv\include | |
ライブラリのパス | C:\opencv\lib |
インクルードファイルのパス | $(KINECTSDK20_DIR)inc | |
ライブラリのパス | $(KINECTSDK20_DIR)Lib\x64 |
NtKinectDLL 経由で Kinect V2 を利用する Unity のプロジェクトを作成します。
Unity(C#) のデータは managed (ガベージコレクタによって管理されており場所を移動することがある) な状態であり、DLL(C++) のデータは unmanaged (場所が移動することはない) な状態です。 この間でデータを受け渡すには、状態を変換する必要があり、 それにはC# の System.Runtime.InteropServices.Marshal クラス のメソッドを利用します。
C#と他の言語の間でデータを受け渡しを行うには、 Blittable type な変数を用います。
NtKinectDLL/x64/Release/の下から NtKinectDLL.dll, NtKinectDLL.lib を、
NtKinectDLL/NtKinectDLL/ の下から NtKinectDLL.h をコピーします。
(2017/09/08 変更)
「$(KINECTSDK20_DIR)Redist\Face\x64\の下の全てのファイル」をコピーします。
[注意]$(KINECTSDK20_DIR)は手元の環境では "C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\" に設定されています。 各自の環境にしたがって読み替えて下さい。
「$(KINECTSDK20_DIR)Redist\VGB\x64\の下の全てのファイル」をコピーします。
[注意]$(KINECTSDK20_DIR)は手元の環境では "C:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\" に設定されています。 各自の環境にしたがって読み替えて下さい。
上部のメニューから「Assets」-> 「Create」 -> 「C# Script」 -> ファイル名は NtUnity
NtUnity.cs |
/* * Copyright (c) 2017 Yoshihisa Nitta * Released under the MIT license * http://opensource.org/licenses/mit-license.php */ /* * NtUnity.cs version 1.2 2017/10/05 * http://nw.tsuda.ac.jp/lec/NtKinectDLL/ * * requires: * NtKinectDLL version 1.2.4 or later */ using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.Runtime.InteropServices; namespace NtUnity { public class Kinect { public const int // Number bodyCount = 6, jointCount = 25, rgbCols = 1920, rgbRows = 1080, depthCols = 512, depthRows = 424, // JointType JointType_SpineBase= 0, JointType_SpineMid= 1, JointType_Neck= 2, JointType_Head= 3, JointType_ShoulderLeft= 4, JointType_ElbowLeft= 5, JointType_WristLeft= 6, JointType_HandLeft= 7, JointType_ShoulderRight= 8, JointType_ElbowRight= 9, JointType_WristRight= 10, JointType_HandRight= 11, JointType_HipLeft= 12, JointType_KneeLeft= 13, JointType_AnkleLeft= 14, JointType_FootLeft= 15, JointType_HipRight= 16, JointType_KneeRight= 17, JointType_AnkleRight= 18, JointType_FootRight= 19, JointType_SpineShoulder= 20, JointType_HandTipLeft= 21, JointType_ThumbLeft= 22, JointType_HandTipRight= 23, JointType_ThumbRight= 24, // TrackingState TrackingState_NotTracked= 0, TrackingState_Inferred= 1, TrackingState_Tracked= 2, // FacePoint FacePointType_None= -1, FacePointType_EyeLeft= 0, FacePointType_EyeRight= 1, FacePointType_Nose= 2, FacePointType_MouthCornerLeft= 3, FacePointType_MouthCornerRight= 4, FacePointType_Count= ( FacePointType_MouthCornerRight + 1 ) , // a_FaceProperty FaceProperty_Happy= 0, FaceProperty_Engaged= 1, FaceProperty_WearingGlasses= 2, FaceProperty_LeftEyeClosed= 3, FaceProperty_RightEyeClosed= 4, FaceProperty_MouthOpen= 5, FaceProperty_MouthMoved= 6, FaceProperty_LookingAway= 7, FaceProperty_Count= ( FaceProperty_LookingAway + 1 ) , // FaceDetectionResult DetectionResult_Unknown= 0, DetectionResult_No= 1, DetectionResult_Maybe= 2, DetectionResult_Yes= 3, // HDFace HDFaceVerticesSize = 1347, // dummy NtKinectdummy = 0; [DllImport ("NtKinectDLL")] private static extern IntPtr getKinect(); [DllImport ("NtKinectDLL")] private static extern void stopKinect(IntPtr ptr); // OpenCV [DllImport ("NtKinectDLL")] private static extern void imshow(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern void imshowBlack(IntPtr ptr); // CoordinateMapper [DllImport ("NtKinectDLL")] private static extern void mapCameraPointToColorSpace(IntPtr ptr,IntPtr sv,IntPtr cv,int n); [DllImport ("NtKinectDLL")] private static extern void mapCameraPointToDepthSpace(IntPtr ptr,IntPtr sv,IntPtr dv,int n); [DllImport ("NtKinectDLL")] private static extern void mapDepthPointToColorSpace(IntPtr ptr,IntPtr dv,IntPtr dth,IntPtr cv,int n); [DllImport ("NtKinectDLL")] private static extern void mapDepthPointToCameraSpace(IntPtr ptr,IntPtr dv,IntPtr dth,IntPtr sv,int n); // Multi Thread [DllImport ("NtKinectDLL")] private static extern void acquire(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern void release(IntPtr ptr); // Audio [DllImport ("NtKinectDLL")] private static extern void setAudio(IntPtr ptr, bool flag); [DllImport ("NtKinectDLL")] private static extern float getBeamAngle(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern float getBeamAngleConfidence(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern ulong getAudioTrackingId(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern void openAudio(IntPtr ptr, IntPtr filename); [DllImport ("NtKinectDLL")] private static extern void closeAudio(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern bool isOpenedAudio(IntPtr ptr); // RGB [DllImport ("NtKinectDLL")] private static extern void setRGB(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern int getRGB(IntPtr ptr, IntPtr data); // Depth [DllImport ("NtKinectDLL")] private static extern void setDepth(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern int getDepth(IntPtr ptr, IntPtr data); // Infrared [DllImport ("NtKinectDLL")] private static extern void setInfrared(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern int getInfrared(IntPtr ptr, IntPtr data); // BodyIndex [DllImport ("NtKinectDLL")] private static extern void setBodyIndex(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern int getBodyIndex(IntPtr ptr, IntPtr data); // Skeleton [DllImport ("NtKinectDLL")] private static extern void setSkeleton(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern int getSkeleton(IntPtr ptr, IntPtr skelton, IntPtr state, IntPtr id, IntPtr tid); [DllImport ("NtKinectDLL")] private static extern int handState(IntPtr ptr,int id,bool isLeft); // Face [DllImport ("NtKinectDLL")] private static extern void setFace(IntPtr ptr, bool isColorSpace); [DllImport ("NtKinectDLL")] private static extern int getFace(IntPtr ptr, IntPtr point,IntPtr rect,IntPtr direction,IntPtr property,IntPtr tid); // HDFace [DllImport ("NtKinectDLL")] private static extern void setHDFace(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern int getHDFace(IntPtr ptr, IntPtr point, IntPtr tid, IntPtr status); // Gesture [DllImport ("NtKinectDLL")] private static extern void setGestureFile(IntPtr ptr, IntPtr filename); [DllImport ("NtKinectDLL")] private static extern int setGestureId(IntPtr ptr, IntPtr name, int id); // id: non-zero [DllImport ("NtKinectDLL")] private static extern void setGesture(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern int getDiscreteGesture(IntPtr ptr, IntPtr gid, IntPtr confidence, IntPtr tid); [DllImport ("NtKinectDLL")] private static extern int getContinuousGesture(IntPtr ptr, IntPtr gid, IntPtr progress, IntPtr tid); [DllImport ("NtKinectDLL")] private static extern int getGidMapSize(); // Video [DllImport ("NtKinectDLL")] private static extern void openVideo(IntPtr ptr, IntPtr filename); [DllImport ("NtKinectDLL")] private static extern void writeVideo(IntPtr ptr); [DllImport ("NtKinectDLL")] private static extern void closeVideo(IntPtr ptr); private IntPtr kinect; //public Vector3[] joint = new Vector3[jointCount]; //public int[] jointState = new int[jointCount]; // audio public float beamAngle; public float beamAngleConfidence; public ulong audioTrackingId; // images public Color32[] rgbImage; public ushort[] depthImage; public ushort[] infraredImage; public byte[] bodyIndexImage; // skeleton public List<List<Vector3>> skeleton; public List<List<int>> skeletonState; public List<int> skeletonId; public List<ulong> skeletonTrackingId; // skeleton (internal) private float[] skel; private int[] skelState; private int[] skelId; private ulong[] skelTrackingId; // face public List<List<Vector2>> facePoint; public List<Vector4> faceRect; public List<Vector3> faceDirection; public List<List<int>> faceProperty; public List<ulong> faceTrackingId; // face (internal) private float[] fcPoint; private float[] fcRect; private float[] fcDirection; private int[] fcProperty; private ulong[] fcTrackingId; // hdface public List<List<Vector3>> hdfacePoint; public List<ulong> hdfaceTrackingId; public List<int> hdfaceStatus; // hdface (internal) private float[] hdfcPoint; private ulong[] hdfcTrackingId; private int[] hdfcStatus; // gesture public List<int> discreteGesture; public List<float> gestureConfidence; public List<ulong> discreteGestureTrackingId; public List<int> continuousGesture; public List<float> gestureProgress; public List<ulong> continuousGestureTrackingId; // gesture (internal) private int[] gstId; private float[] gstFloat; private ulong[] gstTrackingId; public Kinect() { kinect = getKinect(); //rgbImage = new byte[rgbRows * rgbCols * 4]; rgbImage = new Color32[rgbRows * rgbCols]; depthImage = new ushort[depthRows * depthCols]; infraredImage = new ushort[depthRows * depthCols]; bodyIndexImage = new byte[depthRows * depthCols]; skeleton = new List<List<Vector3>>(); skeletonState = new List<List<int>>(); skeletonId = new List<int>(); skeletonTrackingId = new List<ulong>(); skel = new float[bodyCount * jointCount * 3]; skelState = new int[bodyCount * jointCount]; skelId = new int[bodyCount]; skelTrackingId = new ulong[bodyCount]; facePoint = new List<List<Vector2>>(); faceRect = new List<Vector4>(); faceDirection = new List<Vector3>(); faceProperty = new List<List<int>>(); faceTrackingId = new List<ulong>(); fcPoint = new float[bodyCount * FacePointType_Count * 3]; fcRect = new float[bodyCount * 4]; fcDirection = new float[bodyCount * 3]; fcProperty = new int[bodyCount * FaceProperty_Count]; fcTrackingId = new ulong[bodyCount]; hdfacePoint = new List<List<Vector3>>(); hdfaceTrackingId = new List<ulong>(); hdfaceStatus = new List<int>(); hdfcPoint = new float[bodyCount * HDFaceVerticesSize * 3]; hdfcTrackingId = new ulong[bodyCount]; hdfcStatus = new int[bodyCount * 2]; discreteGesture = new List<int>(); gestureConfidence = new List<float>(); discreteGestureTrackingId = new List<ulong>(); continuousGesture = new List<int>(); gestureProgress = new List<float>(); continuousGestureTrackingId = new List<ulong>(); gstId = new int[bodyCount * 100]; gstFloat = new float[bodyCount * 100]; gstTrackingId = new ulong[bodyCount * 100]; } public void stopKinect() { stopKinect(kinect); } // OpenCV public void imshow() { imshow(kinect); } public void imshowBlack() { imshowBlack(kinect); } // coordinateMapper public void mapCameraPointToColorSpace(List<Vector3> skel,ref List<Vector2> color,int n) { float[] sv = new float[n * 3]; float[] cv = new float[n * 2]; for (int i=0; i<n; i++) { sv[3*i] = skel[i].x; sv[3*i+1] = skel[i].y; sv[3*i+2] = skel[i].z; } GCHandle gch = GCHandle.Alloc(sv,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(cv,GCHandleType.Pinned); mapCameraPointToColorSpace(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),n); gch.Free(); gch2.Free(); color.Clear(); for (int i=0; i<n; i++) { color.Add(new Vector2(cv[2*i],cv[2*i+1])); } } public void mapCameraPointToDepthSpace(List<Vector3> skel, ref List<Vector2> depth, int n) { float[] sv = new float[n * 3]; float[] dv = new float[n * 2]; for (int i=0; i<n; i++) { sv[3*i] = skel[i].x; sv[3*i+1] = skel[i].y; sv[3*i+2] = skel[i].z; } GCHandle gch = GCHandle.Alloc(sv,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(dv,GCHandleType.Pinned); mapCameraPointToDepthSpace(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(), n); gch.Free(); gch2.Free(); depth.Clear(); for (int i=0; i<n; i++) { depth.Add(new Vector2(dv[2*i],dv[2*i+1])); } } public void mapDepthPointToColorSpace(List<Vector2> depth,ushort[] dth,ref List<Vector2> color,int n) { float[] dv = new float[n * 2]; float[] cv = new float[n * 2]; for (int i=0; i<n; i++) { dv[2*i] = depth[i].x; dv[2*i+1] = depth[i].y; } GCHandle gch = GCHandle.Alloc(dv,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(dth,GCHandleType.Pinned); GCHandle gch3 = GCHandle.Alloc(cv,GCHandleType.Pinned); mapDepthPointToColorSpace(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),gch3.AddrOfPinnedObject(), n); gch.Free(); gch2.Free(); gch3.Free(); color.Clear(); for (int i=0; i<n; i++) { color.Add(new Vector2(cv[2*i],dv[2*i+1])); } } void mapDepthPointToCameraSpace(List<Vector2> depth,ushort[] dth,ref List<Vector3> skel,int n) { float[] dv = new float[n * 2]; float[] sv = new float[n * 3]; for (int i=0; i<n; i++) { dv[2*i] = depth[i].x; dv[2*i+1] = depth[i].y; } GCHandle gch = GCHandle.Alloc(dv,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(dth,GCHandleType.Pinned); GCHandle gch3 = GCHandle.Alloc(sv,GCHandleType.Pinned); mapDepthPointToCameraSpace(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),gch3.AddrOfPinnedObject(),n); gch.Free(); gch2.Free(); gch3.Free(); skel.Clear(); for (int i=0; i<n; i++) { skel.Add(new Vector3(sv[3*i],sv[3*i+1],sv[3*i+2])); } } // Multi Thread public void acquire() { acquire(kinect); } public void release() { release(kinect); } // Audio public void setAudio(bool flag) { setAudio(kinect,flag); beamAngle = getBeamAngle(kinect); beamAngleConfidence = getBeamAngleConfidence(kinect); audioTrackingId = getAudioTrackingId(kinect); } /* public float getBeamAngle() { return getBeamAngle(kinect); } public float getBeamAngleConfidence() { return getBeamAngleConfidence(kinect); } */ public void openAudio(string filename) { System.IntPtr fname = Marshal.StringToHGlobalUni(filename); openAudio(kinect,fname); Marshal.FreeHGlobal(fname); } public void closeAudio() { closeAudio(kinect); } public bool isOpenedAudio() { return isOpenedAudio(kinect); } // RGB public void setRGB() { setRGB(kinect); getRGB2(); } public int getRGB2() { GCHandle gch = GCHandle.Alloc(rgbImage,GCHandleType.Pinned); int n = getRGB(kinect,gch.AddrOfPinnedObject()); gch.Free(); return n; } // Depth public void setDepth() { setDepth(kinect); getDepth(); } public int getDepth() { GCHandle gch = GCHandle.Alloc(depthImage,GCHandleType.Pinned); int n = getDepth(kinect,gch.AddrOfPinnedObject()); gch.Free(); return n; } // Infrared public void setInfrared() { setInfrared(kinect); getInfrared(); } public int getInfrared() { GCHandle gch = GCHandle.Alloc(infraredImage,GCHandleType.Pinned); int n = getInfrared(kinect,gch.AddrOfPinnedObject()); gch.Free(); return n; } // BodyIndex public void setBodyIndex() {setBodyIndex(kinect); getBodyIndex(); } public int getBodyIndex() { GCHandle gch = GCHandle.Alloc(bodyIndexImage,GCHandleType.Pinned); int n = getBodyIndex(kinect,gch.AddrOfPinnedObject()); gch.Free(); return n; } // Skeleton public void setSkeleton() { setSkeleton(kinect); getSkeleton(); } public int getSkeleton() { GCHandle gch = GCHandle.Alloc(skel,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(skelState,GCHandleType.Pinned); GCHandle gch3 = GCHandle.Alloc(skelId,GCHandleType.Pinned); GCHandle gch4 = GCHandle.Alloc(skelTrackingId,GCHandleType.Pinned); int n = getSkeleton(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),gch3.AddrOfPinnedObject(),gch4.AddrOfPinnedObject()); gch.Free(); gch2.Free(); gch3.Free(); gch4.Free(); skeleton.Clear(); skeletonState.Clear(); skeletonId.Clear(); skeletonTrackingId.Clear(); int idx = 0, st=0; for (int i=0; i<n; i++) { skeleton.Add(new List<Vector3>()); skeletonState.Add(new List<int>()); for (int j=0; j<jointCount; j++) { skeleton[i].Add(new Vector3(skel[idx++], skel[idx++], skel[idx++])); skeletonState[i].Add(skelState[st++]); } skeletonId.Add(skelId[i]); skeletonTrackingId.Add(skelTrackingId[i]); } return n; } private int faceFailCount = 0; // Face public void setFace() { setFace(kinect,true); getFace(); } public int getFace() { GCHandle gch = GCHandle.Alloc(fcPoint,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(fcRect,GCHandleType.Pinned); GCHandle gch3 = GCHandle.Alloc(fcDirection,GCHandleType.Pinned); GCHandle gch4 = GCHandle.Alloc(fcProperty,GCHandleType.Pinned); GCHandle gch5 = GCHandle.Alloc(fcTrackingId,GCHandleType.Pinned); int n = getFace(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),gch3.AddrOfPinnedObject(),gch4.AddrOfPinnedObject(),gch5.AddrOfPinnedObject()); gch.Free(); gch2.Free(); gch3.Free(); gch4.Free(); gch5.Free(); if (n == 0) { faceFailCount++; if (faceFailCount < 10) { return 0; } else { faceFailCount = 0; } } facePoint.Clear(); faceRect.Clear(); faceDirection.Clear(); faceProperty.Clear(); faceTrackingId.Clear(); int idx=0, ridx=0, didx=0, pidx = 0; for (int i=0; i<n; i++) { facePoint.Add(new List<Vector2>()); for (int j=0; j<FacePointType_Count; j++) { facePoint[i].Add(new Vector2(fcPoint[idx++],fcPoint[idx++])); } faceRect.Add(new Vector4(fcRect[ridx++],fcRect[ridx++],fcRect[ridx++],fcRect[ridx++])); faceDirection.Add(new Vector3(fcDirection[didx++],fcDirection[didx++],fcDirection[didx++])); faceProperty.Add(new List<int>()); for (int j=0; j<FaceProperty_Count; j++) { faceProperty[i].Add(fcProperty[pidx++]); } faceTrackingId.Add(fcTrackingId[i]); } return n; } public Vector3 getFaceDirectionByTrackingId(ulong tid) { for (int i=0; i<faceTrackingId.Count; i++) { if (faceTrackingId[i] == tid) { return faceDirection[i]; } } return Vector3.zero; } // HDFace public void setHDFace() { setHDFace(kinect); getHDFace(); } public int getHDFace() { GCHandle gch = GCHandle.Alloc(hdfcPoint,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(hdfcTrackingId,GCHandleType.Pinned); GCHandle gch3 = GCHandle.Alloc(hdfcStatus,GCHandleType.Pinned); int n = getHDFace(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),gch3.AddrOfPinnedObject()); gch.Free(); gch2.Free(); gch3.Free(); hdfacePoint.Clear(); hdfaceTrackingId.Clear(); hdfaceStatus.Clear(); int idx = 0; for (int i=0; i<n; i++) { hdfacePoint.Add(new List<Vector3>()); for (int j=0; j < HDFaceVerticesSize; j++) { hdfacePoint[i].Add(new Vector3(hdfcPoint[idx++],hdfcPoint[idx++],hdfcPoint[idx++])); } hdfaceTrackingId.Add(hdfcTrackingId[i]); hdfaceStatus.Add(hdfcStatus[i]); } return n; } // Gesture public void setGestureFile(string filename) { IntPtr gbd = Marshal.StringToHGlobalUni(filename); setGestureFile(kinect,gbd); Marshal.FreeHGlobal(gbd); } public int setGestureId(string name, int id) { System.IntPtr g = Marshal.StringToHGlobalUni(name); // discrete int n = setGestureId(kinect,g,id); Marshal.FreeHGlobal(g); return n; } public void setGesture() { setGesture(kinect); } public int getDiscreteGesture() { int size = bodyCount * getGidMapSize(); if (gstId.Length < size) { gstId = new int[size]; gstFloat = new float[size]; gstTrackingId = new ulong[size]; } GCHandle gch = GCHandle.Alloc(gstId,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(gstFloat,GCHandleType.Pinned); GCHandle gch3 = GCHandle.Alloc(gstTrackingId,GCHandleType.Pinned); int n = getDiscreteGesture(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),gch3.AddrOfPinnedObject()); gch.Free(); gch2.Free(); gch3.Free(); discreteGesture.Clear(); gestureConfidence.Clear(); discreteGestureTrackingId.Clear(); for (int i=0; i<n; i++) { discreteGesture.Add(gstId[i]); gestureConfidence.Add(gstFloat[i]); discreteGestureTrackingId.Add(gstTrackingId[i]); } return n; } public int getContinuousGesture() { int size = bodyCount * getGidMapSize(); if (gstId.Length < size) { gstId = new int[size]; gstFloat = new float[size]; gstTrackingId = new ulong[size]; } GCHandle gch = GCHandle.Alloc(gstId,GCHandleType.Pinned); GCHandle gch2 = GCHandle.Alloc(gstFloat,GCHandleType.Pinned); GCHandle gch3 = GCHandle.Alloc(gstTrackingId,GCHandleType.Pinned); int n = getContinuousGesture(kinect,gch.AddrOfPinnedObject(),gch2.AddrOfPinnedObject(),gch3.AddrOfPinnedObject()); gch.Free(); gch2.Free(); gch3.Free(); continuousGesture.Clear(); gestureProgress.Clear(); continuousGestureTrackingId.Clear(); for (int i=0; i<n; i++) { continuousGesture.Add(gstId[i]); gestureProgress.Add(gstFloat[i]); continuousGestureTrackingId.Add(gstTrackingId[i]); } return n; } // Video public void openVideo(string filename) { IntPtr str = Marshal.StringToHGlobalUni(filename); openVideo(kinect,str); Marshal.FreeHGlobal(str); } public void writeVideo() { writeVideo(kinect); } public void closeVideo() { closeVideo(kinect); } } public class RigBone { public GameObject gameObject; public HumanBodyBones bone; public bool isValid; public Transform transform { get { return animator.GetBoneTransform(bone); } } Animator animator; Quaternion savedLocalRotation; Quaternion savedRotation; public RigBone(GameObject g, HumanBodyBones b) { gameObject = g; bone = b; isValid = false; animator = gameObject.GetComponent<Animator>(); if (animator == null) { Debug.Log("no Animator Component"); return; } Avatar avatar = animator.avatar; if (avatar == null || !avatar.isHuman || !avatar.isValid) { Debug.Log("Avatar is not Humanoid or it is not valid"); return; } if (animator.GetBoneTransform(bone) == null) { Debug.Log("bone " + bone + " is note assigned in "+g); return; } isValid = true; savedLocalRotation = animator.GetBoneTransform(bone).localRotation; savedRotation = animator.GetBoneTransform(bone).rotation; } public void set(float a, float x, float y, float z) { set(Quaternion.AngleAxis(a, new Vector3(x,y,z))); } public void set(Quaternion q) { animator.GetBoneTransform(bone).localRotation = q; savedLocalRotation = q; } public void mul(float a, float x, float y, float z) { mul(Quaternion.AngleAxis(a, new Vector3(x,y,z))); } public void mul(Quaternion q) { Transform tr = animator.GetBoneTransform(bone); tr.localRotation = q * tr.localRotation; } public void offset(float a, float x, float y, float z) { offset(Quaternion.AngleAxis(a, new Vector3(x,y,z))); } public void offset(Quaternion q) { animator.GetBoneTransform(bone).localRotation = q * savedLocalRotation; } public void gset(float a, float x, float y, float z) { gset(Quaternion.AngleAxis(a, new Vector3(x,y,z))); } public void gset(Quaternion q) { animator.GetBoneTransform(bone).rotation = q; savedLocalRotation = q; } public void gmul(float a, float x, float y, float z) { gmul(Quaternion.AngleAxis(a, new Vector3(x,y,z))); } public void gmul(Quaternion q) { Transform tr = animator.GetBoneTransform(bone); tr.rotation = q * tr.rotation; } public void goffset(float a, float x, float y, float z) { goffset(Quaternion.AngleAxis(a, new Vector3(x,y,z))); } public void goffset(Quaternion q) { animator.GetBoneTransform(bone).rotation = q * savedRotation; } public void changeBone(HumanBodyBones b) { bone = b; savedLocalRotation = animator.GetBoneTransform(bone).localRotation; savedRotation = animator.GetBoneTransform(bone).rotation; } } class HumanoidSkeleton { protected static int[] jointSegment = new int[] { Kinect.JointType_SpineBase, Kinect.JointType_SpineMid, // Spine Kinect.JointType_Neck, Kinect.JointType_Head, // Neck // left Kinect.JointType_ShoulderLeft, Kinect.JointType_ElbowLeft, // LeftUpperArm Kinect.JointType_ElbowLeft, Kinect.JointType_WristLeft, // LeftLowerArm Kinect.JointType_WristLeft, Kinect.JointType_HandLeft, // LeftHand Kinect.JointType_HipLeft, Kinect.JointType_KneeLeft, // LeftUpperLeg Kinect.JointType_KneeLeft, Kinect.JointType_AnkleLeft, // LeftLowerLeg6 Kinect.JointType_AnkleLeft, Kinect.JointType_FootLeft, // LeftFoot // right Kinect.JointType_ShoulderRight, Kinect.JointType_ElbowRight, // RightUpperArm Kinect.JointType_ElbowRight, Kinect.JointType_WristRight, // RightLowerArm Kinect.JointType_WristRight, Kinect.JointType_HandRight, // RightHand Kinect.JointType_HipRight, Kinect.JointType_KneeRight, // RightUpperLeg Kinect.JointType_KneeRight, Kinect.JointType_AnkleRight, // RightLowerLeg Kinect.JointType_AnkleRight, Kinect.JointType_FootRight, // RightFoot }; public Vector3[] joint = new Vector3[Kinect.jointCount]; public int[] jointState = new int[Kinect.jointCount]; protected Dictionary<HumanBodyBones,Vector3> trackingSegment = null; protected Dictionary<HumanBodyBones, int> trackingState = null; protected static HumanBodyBones[] humanBone = new HumanBodyBones[] { HumanBodyBones.Hips, HumanBodyBones.Spine, HumanBodyBones.Chest, HumanBodyBones.Neck, HumanBodyBones.Head, HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, }; protected static HumanBodyBones[] targetBone = new HumanBodyBones[] { HumanBodyBones.Spine, HumanBodyBones.Neck, HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, }; public GameObject humanoid; protected Dictionary<HumanBodyBones, RigBone> rigBone = null; protected bool isSavedPosition = false; protected Vector3 savedPosition; protected Quaternion savedHumanoidRotation; public HumanoidSkeleton(GameObject h) { humanoid = h; rigBone = new Dictionary<HumanBodyBones, RigBone>(); foreach (HumanBodyBones bone in humanBone) { rigBone[bone] = new RigBone(humanoid,bone); } savedHumanoidRotation = humanoid.transform.rotation; trackingSegment = new Dictionary<HumanBodyBones,Vector3>(targetBone.Length); trackingState = new Dictionary<HumanBodyBones, int>(targetBone.Length); } protected void swapJoint(int a, int b) { Vector3 tmp = joint[a]; joint[a] = joint[b]; joint[b] = tmp; int t = jointState[a]; jointState[a] = jointState[b]; jointState[b] = t; } public void set(Kinect kinect, int n, bool mirrored = false, bool move=false, bool headMove=true) { Vector3 faceDir = kinect.getFaceDirectionByTrackingId(kinect.skeletonTrackingId[n]); if (isSavedPosition == false && kinect.skeletonState[n][Kinect.JointType_SpineBase] != Kinect.TrackingState_NotTracked) { isSavedPosition = true; savedPosition = kinect.skeleton[n][Kinect.JointType_SpineBase]; } for (int i=0; i<kinect.skeleton[n].Count; i++) { Vector3 jt = kinect.skeleton[n][i]; if (mirrored) { joint[i] = new Vector3(-jt.x, jt.y, -jt.z); } else { joint[i] = new Vector3(jt.x, jt.y, savedPosition.z*2 - jt.z); } jointState[i] = kinect.skeletonState[n][i]; } if (mirrored) { swapJoint(Kinect.JointType_ShoulderLeft, Kinect.JointType_ShoulderRight); swapJoint(Kinect.JointType_ElbowLeft, Kinect.JointType_ElbowRight); swapJoint(Kinect.JointType_WristLeft, Kinect.JointType_WristRight); swapJoint(Kinect.JointType_HandLeft, Kinect.JointType_HandRight); swapJoint(Kinect.JointType_HipLeft, Kinect.JointType_HipRight); swapJoint(Kinect.JointType_KneeLeft, Kinect.JointType_KneeRight); swapJoint(Kinect.JointType_AnkleLeft, Kinect.JointType_AnkleRight); swapJoint(Kinect.JointType_FootLeft, Kinect.JointType_FootRight); swapJoint(Kinect.JointType_HandTipLeft, Kinect.JointType_HandTipRight); swapJoint(Kinect.JointType_ThumbLeft, Kinect.JointType_ThumbRight); } for (int i=0; i<targetBone.Length; i++) { int s = jointSegment[2*i], e = jointSegment[2*i+1]; trackingSegment[targetBone[i]] = joint[e] - joint[s]; trackingState[targetBone[i]] = System.Math.Min(jointState[e],jointState[s]); } Vector3 waist = joint[Kinect.JointType_HipRight] - joint[Kinect.JointType_HipLeft]; waist = new Vector3(waist.x, 0, waist.z); Quaternion rot = Quaternion.FromToRotation(Vector3.right,waist); Quaternion rotInv = Quaternion.Inverse(rot); Vector3 shoulder = joint[Kinect.JointType_ShoulderRight] - joint[Kinect.JointType_ShoulderLeft]; shoulder = new Vector3(shoulder.x, 0, shoulder.z); //Quaternion srot = Quaternion.FromToRotation(Vector3.right,shoulder); //Quaternion srotInv = Quaternion.Inverse(srot); humanoid.transform.rotation = Quaternion.identity; //humanoid.transform.rotation = savedHumanoidRotation; foreach (HumanBodyBones bone in targetBone) { if (rigBone[bone].isValid && trackingState[bone] != Kinect.TrackingState_NotTracked) { rigBone[bone].transform.rotation = rotInv * Quaternion.FromToRotation(Vector3.up,trackingSegment[bone]); } } //rigBone[HumanBodyBones.Chest].offset(srot); if (headMove && faceDir.magnitude > 1e-6) { float pitch = faceDir.x, yaw = faceDir.y, roll = faceDir.z; if (mirrored) { pitch = -pitch; roll = -roll; } else { pitch = -pitch; yaw = -yaw; } rigBone[HumanBodyBones.Head].transform.rotation = Util.toQ(pitch, yaw, roll); } Quaternion bodyRot = rot; if (mirrored) { bodyRot = Quaternion.AngleAxis(180,Vector3.up) * bodyRot; } humanoid.transform.rotation = bodyRot; if (move == true) { Vector3 m = joint[Kinect.JointType_SpineBase]; if (mirrored) m = new Vector3(-m.x, m.y, -m.z); humanoid.transform.position = m; } } } class Util { public static Quaternion toQ (float pitch, float yaw, float roll) { yaw *= Mathf.Deg2Rad; pitch *= Mathf.Deg2Rad; roll *= Mathf.Deg2Rad; float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)System.Math.Sin ((double)rollOver2); float cosRollOver2 = (float)System.Math.Cos ((double)rollOver2); float pitchOver2 = pitch * 0.5f; float sinPitchOver2 = (float)System.Math.Sin ((double)pitchOver2); float cosPitchOver2 = (float)System.Math.Cos ((double)pitchOver2); float yawOver2 = yaw * 0.5f; float sinYawOver2 = (float)System.Math.Sin ((double)yawOver2); float cosYawOver2 = (float)System.Math.Cos ((double)yawOver2); Quaternion result; result.w = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2; result.x = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2; result.y = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2; result.z = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2; return result; } } class UnityChanSkeleton: HumanoidSkeleton { new protected static int[] jointSegment = new int[] { // left Kinect.JointType_ShoulderLeft, Kinect.JointType_ElbowLeft, // LeftUpperArm Kinect.JointType_ElbowLeft, Kinect.JointType_WristLeft, // LeftLowerArm Kinect.JointType_WristLeft, Kinect.JointType_HandLeft, // LeftHand Kinect.JointType_HipLeft, Kinect.JointType_KneeLeft, // LeftUpperLeg Kinect.JointType_KneeLeft, Kinect.JointType_AnkleLeft, // LeftLowerLeg6 Kinect.JointType_AnkleLeft, Kinect.JointType_FootLeft, // LeftFoot // right Kinect.JointType_ShoulderRight, Kinect.JointType_ElbowRight, // RightUpperArm Kinect.JointType_ElbowRight, Kinect.JointType_WristRight, // RightLowerArm Kinect.JointType_WristRight, Kinect.JointType_HandRight, // RightHand Kinect.JointType_HipRight, Kinect.JointType_KneeRight, // RightUpperLeg Kinect.JointType_KneeRight, Kinect.JointType_AnkleRight, // RightLowerLeg Kinect.JointType_AnkleRight, Kinect.JointType_FootRight, // RightFoot }; new protected static HumanBodyBones[] targetBone = new HumanBodyBones[] { HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand, HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand, HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot, }; public UnityChanSkeleton(GameObject h):base(h) {} new public void set(Kinect kinect, int n, bool mirrored=false, bool move=false, bool headMove=false) { Vector3 faceDir = kinect.getFaceDirectionByTrackingId(kinect.skeletonTrackingId[n]); if (isSavedPosition == false && kinect.skeletonState[n][Kinect.JointType_SpineBase] != Kinect.TrackingState_NotTracked) { isSavedPosition = true; savedPosition = kinect.skeleton[n][Kinect.JointType_SpineBase]; } for (int i=0; i<kinect.skeleton[n].Count; i++) { Vector3 jt = kinect.skeleton[n][i]; if (mirrored) { joint[i] = new Vector3(-jt.x, jt.y, -jt.z); } else { joint[i] = new Vector3(jt.x, jt.y, savedPosition.z*2 - jt.z); } jointState[i] = kinect.skeletonState[n][i]; } if (mirrored) { swapJoint(Kinect.JointType_ShoulderLeft, Kinect.JointType_ShoulderRight); swapJoint(Kinect.JointType_ElbowLeft, Kinect.JointType_ElbowRight); swapJoint(Kinect.JointType_WristLeft, Kinect.JointType_WristRight); swapJoint(Kinect.JointType_HandLeft, Kinect.JointType_HandRight); swapJoint(Kinect.JointType_HipLeft, Kinect.JointType_HipRight); swapJoint(Kinect.JointType_KneeLeft, Kinect.JointType_KneeRight); swapJoint(Kinect.JointType_AnkleLeft, Kinect.JointType_AnkleRight); swapJoint(Kinect.JointType_FootLeft, Kinect.JointType_FootRight); swapJoint(Kinect.JointType_HandTipLeft, Kinect.JointType_HandTipRight); swapJoint(Kinect.JointType_ThumbLeft, Kinect.JointType_ThumbRight); } for (int i=0; i<targetBone.Length; i++) { int s = jointSegment[2*i], e = jointSegment[2*i+1]; trackingSegment[targetBone[i]] = joint[e] - joint[s]; trackingState[targetBone[i]] = System.Math.Min(jointState[e],jointState[s]); } savedHumanoidRotation = humanoid.transform.rotation; humanoid.transform.rotation = Quaternion.identity; Vector3 waist = joint[Kinect.JointType_HipRight] - joint[Kinect.JointType_HipLeft]; waist = new Vector3(waist.x, 0, waist.z); Quaternion rot = Quaternion.FromToRotation(Vector3.right,waist); Quaternion rotInv = Quaternion.Inverse(rot); Vector3 shoulder = joint[Kinect.JointType_ShoulderRight] - joint[Kinect.JointType_ShoulderLeft]; shoulder = new Vector3(shoulder.x, 0, shoulder.z); Quaternion srot = Quaternion.FromToRotation(Vector3.right,shoulder); Quaternion defaultQ = Quaternion.AngleAxis(90, new Vector3(0,1,0) ) * Quaternion.AngleAxis( -90, new Vector3(0,0,1 ) ); foreach (HumanBodyBones b in targetBone) { if (rigBone[b].isValid && trackingState[b] != Kinect.TrackingState_NotTracked) { rigBone[b].transform.rotation = rotInv * Quaternion.FromToRotation(Vector3.up,trackingSegment[b]) * defaultQ; } } Quaternion q = Quaternion.AngleAxis(-90, new Vector3(0,1,0)) * Quaternion.AngleAxis(-90, new Vector3(0,0,1)); if (headMove && faceDir.magnitude > 1e-6) { float pitch = faceDir.x, yaw = faceDir.y, roll = faceDir.z; if (mirrored) { pitch = -pitch; roll = -roll; } else { pitch = -pitch; yaw = -yaw; } rigBone[HumanBodyBones.Head].transform.rotation = Util.toQ(pitch, yaw, roll) * q; } if (rigBone[HumanBodyBones.Chest].isValid) rigBone[HumanBodyBones.Chest].transform.rotation = srot * q; if (mirrored) { humanoid.transform.rotation = Quaternion.AngleAxis(180,Vector3.up) * rot; } else { humanoid.transform.rotation = rot; } if (move == true) { Vector3 m = joint[Kinect.JointType_SpineBase]; if (mirrored) m = new Vector3(-m.x, m.y, -m.z); humanoid.transform.position = m; } return; } } } |
上部のメニューから「Assets」-> 「Create」 -> 「C# Script」 -> ファイル名は Sample01
Sample01.cs |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Sample01 : MonoBehaviour { NtUnity.Kinect nt; void Start () { nt = new NtUnity.Kinect(); } void Update () { nt.setRGB(); nt.setSkeleton(); nt.setFace(); nt.imshowBlack(); Debug.Log("n = " + nt.skeleton.Count); } void OnApplicationQuit() { nt.stopKinect(); } } |
Files -> Save Scene as .. -> Sample01
実行中のキャプチャ画面はこちら。
上記のzipファイルには必ずしも最新の "NtKinectDLL.dll" と "NtUnity.cs" が含まれていない場合があるので、 こちらから最新版をダウンロードして 差し替えてお使い下さい。