「骨格を認識する」とはすなわち「ある人間の関節の位置情報を取得する」ということです。 関節を表す型は Joint で、Kinect for Windows SDK 2.0 では次のように定義されています。
「関節」に関するデータは Joint という型で表されます。 Joint 型は
| Kinect for Windows SDK 2.0 の Kinect.h(抜粋) |
|---|
enum _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,
JointType_Count= ( JointType_ThumbRight + 1 )
};
enum _TrackingState {
TrackingState_NotTracked= 0,
TrackingState_Inferred= 1,
TrackingState_Tracked= 2
};
typedef struct _Joint {
JointType JointType;
CameraSpacePoint Position;
TrackingState TrackingState;
} Joint;
|
| 返り値の型 | メソッド名 | 説明 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| void | setSkeleton() | 骨格認識を行い、次のメンバ変数に値を設定する。
|
| 型 | 変数名 | 説明 |
|---|---|---|
| vector<vector<Joint>> | skeleton | 骨格情報のベクタ。
一人の人間の関節の集合が vector<Joint> であり、これが骨格情報です。
複数の人間を扱うため骨格情報のベクタ、すなわち vector<vector<Joint>> となります。 関節の座標は CameraSpace 座標系における位置です。
|
| vector<int> | skeletonId | 骨格に対応するbodyIndexのベクタ。 skeleton[index ] の bodyIndex は skeletonId[index ] に保持されます。 |
| vector<UINT64> | skeletonTrackingId | 骨格に対応するtrackingIdのベクタ。 skeleton[index ] の trackingId は skeletonTrackingId[index ] に保持されます。 |
データの種類によって、それを計測するセンサーの位置や解像度が異なります。 そのため、実世界での同じ位置の状態が、センサーによってそれぞれの座標系で表現された値として得られます。 異なるセンサーから得られたデータを同時に利用する場合は、 座標系の変換を行なってどちらかの座標系に合わせる必要があります。
Kinect V2 では、ColorSpace, DepthSpace, CameraSpace という3つの座標系があって、 それぞれの座標を表すデータ型 ColorSpacePoint, DepthSpacePoint, CameraSpacePoint が存在します。
| Kinect for Windows SDK 2.0 の Kinect.h(抜粋) |
|---|
typedef struct _ColorSpacePoint {
float X;
float Y;
} ColorSpacePoint;
typedef struct _DepthSpacePoint {
float X;
float Y;
} DepthSpacePoint;
typedef struct _CameraSpacePoint {
float X;
float Y;
float Z;
} CameraSpacePoint;
|
RGB画像, Depth画像, 関節情報ではそれぞれ使っている座標系が異なります。 RGB画像の座標系は ColorSpace で、Depth画像の座標系は DepthSpace, 関節情報の座標系は CameraSpace です。
| 座標系 | 位置を表す型 | データの種類 |
|---|---|---|
| ColorSpace | ColorSpacePoint | RGB画像 |
| DepthSpace | DepthSpacePoint | depth画像, bodyIndex画像, 赤外線画像 |
| CameraSpace | CameraSpacePoint | skeleton情報 |

| 関節の位置を表すCameraSpace 座標系 |
|---|
|
CameraSpace 座標系は、
(2016/11/12 図を変更し、説明を追記しました)。 |
Kinect V2 の ICoordinateMapper クラス が保持する「座標系の変換用メソッド」は次の通りです。
| 返り値の型 | メソッド名 | 説明 |
|---|---|---|
| HRESULT | MapCameraPointToColorSpace( CameraSpacePoint sp , ColorSpacePoint *cp ) |
CameraSpace 座標系での座標 sp を ColorSpace 座標系での座標に変換してcp にセットする。 返り値はS_OKかエラーコード。 |
| HRESULT | MapCameraPointToDepthSpace( CameraSpacePoint sp , DelpthSpacePoint *dp ) |
CameraSpace 座標系での座標 sp を DepthSpace 座標系での座標に変換してdp にセットする。 返り値はS_OKかエラーコード。 |
| HRESULT | MapDepthPointToColorSpace( DepthSpacePoint dp , UINT16 depth , ColorSpacePoint *cp ) |
DepthSpace 座標系での座標 dp と距離depth から ColorSpace 座標系での座標に変換してcp にセットする。 返り値はS_OKかエラーコード。 |
| HRESULT | MapDepthPointToCameraSpace( DepthSpacePoint dp , UINT16 depth , CameraSpacePoint *sp ) |
DepthSpace 座標系での座標 dp と距離depth から CameraSpace 座標系での座標に変換してsp にセットする。 返り値はS_OKかエラーコード。 |
Kinect V2 で座標系の変換に使う ICoordinateMapper クラス のインスタンスは、 NtKinect のメンバ変数 coordinateMapper に保持されています。
| 型 | 変数名 | 説明 |
|---|---|---|
| CComPtr<ICoordinateMapper> | coordinateMapper | 座標変換を行う ICoordinateMapperのインスタンス。 |
kinect.setSkeleton()メソッドを呼び出して骨格情報を kinect.skeleton に取得します。 関節の位置は CameraSpace 座標系で表現されているので、 ColorSpace 座標系の座標に変換してから RGB画像上に四角形を描画しています(緑字部分)。
Joint型のデータが意味を持つのは、その TrackingState メンバ変数の値が TrackingState_Tracked か TrackingState_Inferred である場合だけなので、 プログラム中では TrackingState_NotTracked である場合はその関節の表示処理をスキップしています。
| main.cpp |
#include <iostream> #include <sstream> #include "NtKinect.h" using namespace std; void doJob() { NtKinect kinect; while (1) { kinect.setRGB(); kinect.setSkeleton(); for (auto person : kinect.skeleton) { for (auto joint : person) { if (joint.TrackingState == TrackingState_NotTracked) continue; ColorSpacePoint cp; kinect.coordinateMapper->MapCameraPointToColorSpace(joint.Position,&cp); cv::rectangle(kinect.rgbImage, cv::Rect((int)cp.X-5, (int)cp.Y-5,10,10), cv::Scalar(0,0,255),2); } } cv::imshow("rgb", kinect.rgbImage); auto key = cv::waitKey(1); if (key == 'q') break; } cv::destroyAllWindows(); } int main(int argc, char** argv) { try { doJob(); } catch (exception &ex) { cout << ex.what() << endl; string s; cin >> s; } return 0; } |
RGB画像の上に、認識された関節が赤い四角形で示されます。OpenCVでは色をBGRの順番で表現するのが 普通なので cv::Scalar(0,0,255)は (青, 緑, 赤)=(0,0,255)、すなわち赤を表していることに注意しましょう。

上記のzipファイルには必ずしも最新の NtKinect.h が含まれていない場合があるので、 こちらから最新版をダウンロードして 差し替えてお使い下さい。