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

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

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

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Kinect

Kinect(キネクト)はマイクロソフトから発売されたジェスチャー・音声認識によって 操作ができるデバイスです。

Q&A

1回答

2548閲覧

Kinectでの関節の座標取得

kinect-jongen

総合スコア13

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Kinect

Kinect(キネクト)はマイクロソフトから発売されたジェスチャー・音声認識によって 操作ができるデバイスです。

0グッド

0クリップ

投稿2018/12/05 01:29

前提・実現したいこと

C++でKinectの開発を行っています。
主に、秀和システムの「KINECT for Windows SDKプログラミング」という本を参考にして開発をしています。

私はKinectを用いて、人の手や足のピンポイントの座標を取得してその座標を配列に格納したいと思っています。

発生している問題・エラーメッセージ

身体の各関節の座標を個別で取得する方法が分からなくて困っています。
本やインターネットで調べても詳しい方法が出てこないです。

ほかにこのような開発を行ったことがある方など助けていただけたら嬉しいです。

該当のソースコード

C++

1#include <iostream> 2#include <sstream> 3 4#include <Kinect.h> 5#include <opencv2\opencv.hpp> 6 7#include <atlbase.h> 8 9#define ERROR_CHECK( ret ) \ 10 if ( (ret) != S_OK ) { \ 11 std::stringstream ss; \ 12 ss << "failed " #ret " " << std::hex << ret << std::endl; \ 13 throw std::runtime_error( ss.str().c_str() ); \ 14 } 15 16//Kinect動作用 17 18class KinectApp{ 19 20private: 21 22 CComPtr<IKinectSensor> kinect = nullptr; 23 24 //カラー画像用 25 CComPtr<IColorFrameReader> colorFrameReader = nullptr; 26 27 int colorWidth; 28 int colorHeight; 29 unsigned int colorBytesPerPixel; 30 31 ColorImageFormat colorFormat = ColorImageFormat::ColorImageFormat_Bgra; 32 33 std::vector<BYTE> colorBuffer; 34 35 36 37 //body用 38 CComPtr<IBodyFrameReader> bodyFrameReader = nullptr; 39 IBody* bodies[6]; 40 41public: 42 43 ~KinectApp(){ 44 // Kinectの動作を終了する 45 if ( kinect != nullptr ){ 46 kinect->Close(); 47 } 48 } 49 50 // 初期化 51 void initialize(){ 52 // デフォルトのKinectを取得する 53 ERROR_CHECK( ::GetDefaultKinectSensor( &kinect ) ); 54 ERROR_CHECK( kinect->Open() ); 55 56 //カラーリーダーを取得する 57 CComPtr<IColorFrameSource> colorFrameSource; 58 ERROR_CHECK(kinect->get_ColorFrameSource(&colorFrameSource)); 59 ERROR_CHECK(colorFrameSource->OpenReader(&colorFrameReader)); 60 61 // デフォルトのカラー画像のサイズを取得する 62 CComPtr<IFrameDescription> defaultColorFrameDescription; 63 ERROR_CHECK(colorFrameSource->get_FrameDescription(&defaultColorFrameDescription)); 64 ERROR_CHECK(defaultColorFrameDescription->get_Width(&colorWidth)); 65 ERROR_CHECK(defaultColorFrameDescription->get_Height(&colorHeight)); 66 ERROR_CHECK(defaultColorFrameDescription->get_BytesPerPixel(&colorBytesPerPixel)); 67 std::cout << "default : " << colorWidth << ", " << colorHeight << ", " << colorBytesPerPixel << std::endl; 68 69 // カラー画像のサイズを取得する 70 CComPtr<IFrameDescription> colorFrameDescription; 71 ERROR_CHECK(colorFrameSource->CreateFrameDescription(colorFormat, &colorFrameDescription)); 72 ERROR_CHECK(colorFrameDescription->get_Width(&colorWidth)); 73 ERROR_CHECK(colorFrameDescription->get_Height(&colorHeight)); 74 ERROR_CHECK(colorFrameDescription->get_BytesPerPixel(&colorBytesPerPixel)); 75 std::cout << "create : " << colorWidth << ", " << colorHeight << ", " << colorBytesPerPixel << std::endl; 76 77 // バッファーを作成する 78 colorBuffer.resize(colorWidth * colorHeight * colorBytesPerPixel); 79 80 // ボディリーダーを取得する 81 CComPtr<IBodyFrameSource> bodyFrameSource; 82 ERROR_CHECK( kinect->get_BodyFrameSource( &bodyFrameSource ) ); 83 ERROR_CHECK( bodyFrameSource->OpenReader( &bodyFrameReader ) ); 84 85 for ( auto& body : bodies ){ 86 body = nullptr; 87 } 88 } 89 90 void run(){ 91 while ( 1 ) { 92 update(); 93 draw(); 94 95 auto key = cv::waitKey( 10 ); 96 if ( key == 'q' ){ 97 break; 98 } 99 } 100 } 101 102private: 103 104 // データの更新処理 105 void update(){ 106 updateBodyFrame(); 107 updateColorFrame(); 108 } 109 110 // ボディフレームの更新 111 void updateBodyFrame(){ 112 // フレームを取得する 113 CComPtr<IBodyFrame> bodyFrame; 114 auto ret = bodyFrameReader->AcquireLatestFrame( &bodyFrame ); 115 if ( FAILED( ret ) ){ 116 return; 117 } 118 119 // 前回のBodyを解放する 120 for ( auto& body : bodies ){ 121 if ( body != nullptr ){ 122 body->Release(); 123 body = nullptr; 124 } 125 } 126 127 // データを取得する 128 ERROR_CHECK( bodyFrame->GetAndRefreshBodyData( 6, &bodies[0] ) ); 129 } 130 131 void draw(){ 132 drawBodyFrame(); 133 drawColorFrame(); 134 } 135 136 void drawBodyFrame(){ 137 // 関節の座標をDepth座標系で表示する 138 cv::Mat bodyImage = cv::Mat::zeros( 424, 512, CV_8UC4 ); 139 140 for ( auto body : bodies ){ 141 if ( body == nullptr ){ 142 continue; 143 } 144 145 BOOLEAN isTracked = false; 146 ERROR_CHECK( body->get_IsTracked( &isTracked ) ); 147 if ( !isTracked ) { 148 continue; 149 } 150 151 // 関節の位置を表示する 152 Joint joints[JointType::JointType_Count]; 153 body->GetJoints( JointType::JointType_Count, joints ); 154 for ( auto joint : joints ) { 155 // 手の位置が追跡状態 156 if ( joint.TrackingState == TrackingState::TrackingState_Tracked ) { 157 drawEllipse( bodyImage, joint, 10, cv::Scalar( 255, 0, 0 ) ); 158 } 159 // 手の位置が推測状態 160 else if ( joint.TrackingState == TrackingState::TrackingState_Inferred ) { 161 drawEllipse( bodyImage, joint, 10, cv::Scalar( 255, 255, 0 ) ); 162 } 163 } 164 } 165 166 cv::imshow( "Body Image", bodyImage ); 167 } 168 169 void drawEllipse( cv::Mat& bodyImage, const Joint& joint, int r, const cv::Scalar& color ){ 170 // カメラ座標系をDepth座標系に変換する 171 CComPtr<ICoordinateMapper> mapper; 172 ERROR_CHECK( kinect->get_CoordinateMapper( &mapper ) ); 173 174 DepthSpacePoint point; 175 mapper->MapCameraPointToDepthSpace( joint.Position, &point ); 176 177 cv::circle( bodyImage, cv::Point( point.X, point.Y ), r, color, -1 ); 178 } 179 180 // カラーフレームの更新 181 void updateColorFrame(){ 182 // フレームを取得する 183 CComPtr<IColorFrame> colorFrame; 184 auto ret = colorFrameReader->AcquireLatestFrame(&colorFrame); 185 if (FAILED(ret)) { 186 return; 187 } 188 189 // 指定の形式でデータを取得する 190 ERROR_CHECK(colorFrame->CopyConvertedFrameDataToArray(colorBuffer.size(), &colorBuffer[0], colorFormat)); 191 } 192 193 // カラーデータの表示処理 194 void drawColorFrame(){ 195 196#if 0 197 // カラーデータを表示する 198 cv::Mat colorImage(colorHeight, colorWidth, CV_8UC4, &colorBuffer[0]); 199 cv::imshow("Color Image", colorImage); 200 201#else 202 cv::Mat colorImage(colorHeight, colorWidth, CV_8UC4, &colorBuffer[0]); 203 cv::Mat harfImage; 204 cv::resize(colorImage, harfImage, cv::Size(), 0.5, 0.5); 205 cv::imshow("Harf Image", harfImage); 206 207#endif 208 209 } 210}; 211 212void main(){ 213 try { 214 KinectApp app; 215 app.initialize(); 216 app.run(); 217 } 218 catch ( std::exception& ex ){ 219 std::cout << ex.what() << std::endl; 220 } 221} 222

試したこと

void drawEllipse中のjointをJointTypeの中のそれぞれの関節に対応するものにあてはめたりしたのですが成功しませんでした。

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

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

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

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

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

guest

回答1

0

以下の部分を改造すると良いです。

C++

// 関節の位置を表示する
Joint joints[JointType::JointType_Count];
body->GetJoints( JointType::JointType_Count, joints );
for ( auto joint : joints ) {
...
}

リファレンスを見ると、Joint構造体のメンバを知ることができます。

未検証ですが、次のようにループを書いていけば良いでしょう。

C++

1for(const auto& joint: joints) { // 無駄なコピーはしない方が良いです 2 switch(joint.JointType) { 3 case JointType.HandLeft: 4 座標を記録する 5 break; 6 ... 7 } 8}

座標値の取得方法・解釈の仕方については、次の記事が参考になりそうです。
Kinect開発備忘録(1) | Kinect | アプリ関連ニュース | ギガスジャパン

座標の記録については、std::arrayを使うのが安直で簡単だと思います。

投稿2018/12/05 05:06

LouiS0616

総合スコア35658

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

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

kinect-jongen

2018/12/06 02:16

回答ありがとうございます! 参考にさせていただきます。 回答の中のswitch文の中に case JointType_HandRight: mapper->MapCameraPointToDepthSpace(joint.Position, &HandRightPoint); HandRightRecord[j] = HandRightPoint; j++; break; } という文を書いてみましたが、HandRightPointのところに「"DepthSpacePoint"から"double"への適切な変換関数が存在しません」と表示されてしまいます。 HandRightRecordは std::array<double, 50000> HandRightRecord; と宣言しました。 エラーの文の1つ上の文でやっているつもりですがどのようにこのエラーを消せばよろしいでしょうか。 このエラーを消したところで値の保存はできているでしょうか。 初心者でもうしわけございません
LouiS0616

2018/12/06 04:30

とりあえずエラーを消すだけなら、HandRightRecordの型をstd::array<DepthSpacePoint, 50000>にしてみるとか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問