2016-10-20 15 views
0

hereのサンプルコードを使用しようとしています。OpenKinectは生の奥行き画像を取得します

イメージをコンピュータに保存するためにいくつか変更を加えました。私がMATLABでデータを読むと、0にすべき値が2047に設定されているように見え、デフォルトの組み込みカメラパラメータを使用して3Dポイントを再構成すると全体的に正しいとは思われません。

私は何を達成したいことは、私は IMG =シングル(関数imread(depth.pngを '))を使用することができるように画像を保存することです/ 1000 やメートルで深さの値を持つ、ノー測定とピクセルがなければなりませんゼロ。

途中でKinect V1です。

ここでは、私が変更しようとしたコメントのコードです。

#include "libfreenect.hpp" 
#include <iostream> 
#include <vector> 
#include <cmath> 
#include <pthread.h> 
#include <cv.h> 
#include <cxcore.h> 
#include <highgui.h> 


using namespace cv; 
using namespace std; 


class myMutex { 
    public: 
     myMutex() { 
      pthread_mutex_init(&m_mutex, NULL); 
     } 
     void lock() { 
      pthread_mutex_lock(&m_mutex); 
     } 
     void unlock() { 
      pthread_mutex_unlock(&m_mutex); 
     } 
    private: 
     pthread_mutex_t m_mutex; 
}; 

// Should one use FREENECT_DEPTH_REGISTERED instead of FREENECT_DEPTH_11BIT? 
class MyFreenectDevice : public Freenect::FreenectDevice { 
    public: 
     MyFreenectDevice(freenect_context *_ctx, int _index) 
      : Freenect::FreenectDevice(_ctx, _index), m_buffer_depth(FREENECT_DEPTH_11BIT), 
      m_buffer_rgb(FREENECT_VIDEO_RGB), m_gamma(2048), m_new_rgb_frame(false), 
      m_new_depth_frame(false), depthMat(Size(640,480),CV_16UC1), 
      rgbMat(Size(640,480), CV_8UC3, Scalar(0)), 
      ownMat(Size(640,480),CV_8UC3,Scalar(0)) { 

      for(unsigned int i = 0 ; i < 2048 ; i++) { 
       float v = i/2048.0; 
       v = std::pow(v, 3)* 6; 
       m_gamma[i] = v*6*256; 
      } 
     } 

     // Do not call directly even in child 
     void VideoCallback(void* _rgb, uint32_t timestamp) { 
      std::cout << "RGB callback" << std::endl; 
      m_rgb_mutex.lock(); 
      uint8_t* rgb = static_cast<uint8_t*>(_rgb); 
      rgbMat.data = rgb; 
      m_new_rgb_frame = true; 
      m_rgb_mutex.unlock(); 
     }; 

     // Do not call directly even in child 
     void DepthCallback(void* _depth, uint32_t timestamp) { 
      std::cout << "Depth callback" << std::endl; 
      m_depth_mutex.lock(); 
      uint16_t* depth = static_cast<uint16_t*>(_depth); 
      // Here I use memcpy instead so I can use uint16 
      // memcpy(depthMat.data,depth,depthMat.rows*depthMat.cols*sizeof(uint16_t)); 

      depthMat.data = (uchar*) depth; 
      m_new_depth_frame = true; 
      m_depth_mutex.unlock(); 
     } 

     bool getVideo(Mat& output) { 
      m_rgb_mutex.lock(); 
      if(m_new_rgb_frame) { 
       cv::cvtColor(rgbMat, output, CV_RGB2BGR); 
       m_new_rgb_frame = false; 
       m_rgb_mutex.unlock(); 
       return true; 
      } else { 
       m_rgb_mutex.unlock(); 
       return false; 
      } 
     } 

     bool getDepth(Mat& output) { 
       m_depth_mutex.lock(); 
       if(m_new_depth_frame) { 
        depthMat.copyTo(output); 
        m_new_depth_frame = false; 
        m_depth_mutex.unlock(); 
        return true; 
       } else { 
        m_depth_mutex.unlock(); 
        return false; 
       } 
      } 
    private: 

     // Should it be uint16_t instead or even higher? 
     std::vector<uint8_t> m_buffer_depth; 
     std::vector<uint8_t> m_buffer_rgb; 
     std::vector<uint16_t> m_gamma; 
     Mat depthMat; 
     Mat rgbMat; 
     Mat ownMat; 
     myMutex m_rgb_mutex; 
     myMutex m_depth_mutex; 
     bool m_new_rgb_frame; 
     bool m_new_depth_frame; 
}; 


int main(int argc, char **argv) { 
    bool die(false); 
    string filename("snapshot"); 
    string suffix(".png"); 
    int i_snap(0),iter(0); 

    Mat depthMat(Size(640,480),CV_16UC1); 
    Mat depthf (Size(640,480),CV_8UC1); 
    Mat rgbMat(Size(640,480),CV_8UC3,Scalar(0)); 
    Mat ownMat(Size(640,480),CV_8UC3,Scalar(0)); 

    // The next two lines must be changed as Freenect::Freenect 
    // isn't a template but the method createDevice: 
    // Freenect::Freenect<MyFreenectDevice> freenect; 
    // MyFreenectDevice& device = freenect.createDevice(0); 
    // by these two lines: 

    Freenect::Freenect freenect; 
    MyFreenectDevice& device = freenect.createDevice<MyFreenectDevice>(0); 

    namedWindow("rgb",CV_WINDOW_AUTOSIZE); 
    namedWindow("depth",CV_WINDOW_AUTOSIZE); 
    device.startVideo(); 
    device.startDepth(); 
    while (!die) { 
     device.getVideo(rgbMat); 
     device.getDepth(depthMat); 
     // Here I save the depth images 
     std::ostringstream file; 
     file << filename << i_snap << suffix; 
     cv::imwrite(file.str(),depthMat); 

     cv::imshow("rgb", rgbMat); 
     depthMat.convertTo(depthf, CV_8UC1, 255.0/2048.0); 
     cv::imshow("depth",depthf); 

     if(iter >= 1000) break; 
     iter++; 
    } 

    device.stopVideo(); 
    device.stopDepth(); 
    return 0; 
} 

ありがとうございます!

Erik

答えて

0

特にOpenKinectでの経験はありません。あなたの奥行きバッファはuint16でなければなりませんか?

std::vector<uint8_t> m_buffer_depth; 

また、 Matlabの場合は、読み込んでいる画像がuint16かuint8かどうかを確認してください。その後者がuint16に変換する場合

uint16(imread('depth.png')); 

申し訳ありません。お役に立てれば。

0
  1. あなたが持っている値は生の奥行値です。番号を理解するためには、それらをMMに再マップする必要があります。 Kinect 1は最大10メートルまで見ることができます。ですから、私はraw_values/2407 * 10000に行きます。

  2. 値が2047で飽和している場合、おそらくFREENECT_DEPTH_11BIT_PACKEDの深さの形式が使用されています。

  3. Matlabでの作業は、FREENECT_DEPTH_MMまたはFREENECT_DEPTH_REGISTEREDを使用する方が簡単です。

お楽しみください。

関連する問題