2016-10-20 4 views
0

Ich versuche, den Beispielcode von here zu verwenden.OpenKinect erfassen Rohtiefe Bild

Ich habe einige Änderungen vorgenommen, um die Bilder auf dem Computer zu speichern. Wenn ich die Daten in MATLAB lese, scheinen Werte, die 0 sein sollten, auf 2047 eingestellt zu sein, und insgesamt scheint es nicht korrekt zu sein, wenn ich die 3D-Punkte unter Verwendung der standardmäßigen intrinsischen Kameraparameter rekonstruiere.

Was ich will, erreichen, ist die Bilder zu speichern, damit ich img = single (imread (depth.png ')) verwenden können/1000 und die Tiefenwerte in Metern, und Pixel ohne Messungen sollten Null.

Es ist übrigens die Kinect V1.

Hier ist der Code mit Kommentaren, wo ich versucht habe zu ändern.

#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; 
} 

Vielen Dank im Voraus!

Erik

Antwort

0

Ich habe keine Erfahrung mit OpenKinect im Besonderen; aber sollte dein Tiefenpuffer uint16 sein?

std::vector<uint8_t> m_buffer_depth; 

Auch; für Matlab, überprüfen Sie, ob das Bild, das Sie lesen, ein Uint16 oder Uint8 ist. Wenn es das letztere ist dann wandeln Sie es in Uint16

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

Sorry konnte nicht mehr helfen. Hoffe das hilft.

0
  1. Die Werte, die Sie haben, sind die rohen Tiefenwerte. Sie müssen diese in MM umwandeln, damit die Zahlen sinnvoll sind. Kinect 1 kann bis zu 10 Meter sehen. Also würde ich mit row_values ​​/ 2407 * 10000 gehen.

  2. Wenn die Werte bei 2047 gesättigt sind, verwenden Sie wahrscheinlich das Tiefenformat FREENECT_DEPTH_11BIT_PACKED.

  3. Für die Arbeit in Matlab ist es immer einfacher, FREENECT_DEPTH_MM oder FREENECT_DEPTH_REGISTERED zu verwenden.

Genießen.

Verwandte Themen