2016-10-20 18 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; 
} 

Заранее благодарен!

Эрик

ответ

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.

Наслаждайтесь.