前提・実現したいこと
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の中のそれぞれの関節に対応するものにあてはめたりしたのですが成功しませんでした。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/12/06 02:16
2018/12/06 04:30