2017-02-21 627 views
0

伙计们,RealSense的OpenCV深度图像太暗

我有一个realsense SR300,但是当我在OpenCV的窗口中显示我的深度图像,它看起来太黑了。我怎样才能解决这个问题?当我运行真实的例子时,图像看起来不错,但这些例子使用OpenGL。但我的项目需要OpenCV。这里是我的代码:

int main(int argc, char ** argv) 
{ 
    // realsense camera setup 
    rs::log_to_console(rs::log_severity::warn); 
    // Create a context object. This object owns the handles to all connected realsense devices 
    rs::context ctx; 
    if (ctx.get_device_count() == 0) 
    { 
    throw std::runtime_error("No device detected. Is it plugged in?"); 
    } 
    // Access the first available RealSense device 
    rs::device * dev = ctx.get_device(0); 
    // Configure depth to run at VGA resolution at 30 frames per second 
    dev->enable_stream(rs::stream::depth, 640, 480, rs::format::z16, 30); 
    rs::intrinsics depth_intrin; 
    rs::format depth_format; 
    depth_intrin = dev->get_stream_intrinsics(rs::stream::depth); 
    depth_format = dev->get_stream_format(rs::stream::depth); 
    cv::namedWindow("Send Display Image", CV_WINDOW_AUTOSIZE); 

    /* Set callbacks prior to calling start(). */ 
    auto depth_callback = [depth_intrin, depth_format](rs::frame f) 
    { 
    cv::Mat image(cv::Size(640, 480), CV_16UC1, 
     (void*)f.get_data(), cv::Mat::AUTO_STEP); 
    cv::imshow("Send Display Image", image); 
    cv::waitKey(1000/80); 
    }; 
    /* callback to grab depth fream and publish it. */ 
    dev->set_frame_callback(rs::stream::depth, depth_callback); 
    // Start streaming 
    dev->start(); 
    While(1) 
    { 

    } 
    return 0; 
} 

我不知道为什么我的图像是如此黑暗。我希望它看起来像Kinect的或Xtion当我从ROS运行openni_launch

回答

2

编辑:

下面的归一化功能产生一些闪烁:

  • 我怀疑这是由于最大深度值闪烁。
  • 最小深度值始终为0,因为当深度无效并因此深度范围变为假时使用此值。

相反,你应该这样做:

void make_depth_histogram(const Mat &depth, Mat &normalized_depth) { 
    normalized_depth = Mat(depth.size(), CV_8U); 
    int width = depth.cols, height = depth.rows; 

    static uint32_t histogram[0x10000]; 
    memset(histogram, 0, sizeof(histogram)); 

    for(int i = 0; i < height; ++i) { 
    for (int j = 0; j < width; ++j) { 
     ++histogram[depth.at<ushort>(i,j)]; 
    } 
    } 

    for(int i = 2; i < 0x10000; ++i) histogram[i] += histogram[i-1]; // Build a cumulative histogram for the indices in [1,0xFFFF] 

    for(int i = 0; i < height; ++i) { 
    for (int j = 0; j < width; ++j) { 
     if (uint16_t d = depth.at<ushort>(i,j)) { 
     int f = histogram[d] * 255/histogram[0xFFFF]; // 0-255 based on histogram location 
     normalized_depth.at<uchar>(i,j) = static_cast<uchar>(f); 
     } else { 
     normalized_depth.at<uchar>(i,j) = 0; 
     } 
    } 
    } 
} 

你看到什么就是因为深度流是在16位(rs::stream::z16),而当只有8位将被用于显示的编码。

可以归你的深度图:

double min, max; 
minMaxLoc(depth, &min, &max); 
Mat depth_normalized; 
double alpha = 255.0/(max-min); 
depth.convertTo(depth_normalized, CV_8U, alpha, -min*alpha); 

或者用一种颜色表的显示深度:make_depth_histogram()

完整的示例代码:

inline void make_depth_histogram(const Mat &depth, Mat &color_depth) { 
    color_depth = Mat(depth.size(), CV_8UC3); 
    int width = depth.cols, height = depth.rows; 

    static uint32_t histogram[0x10000]; 
    memset(histogram, 0, sizeof(histogram)); 

    for(int i = 0; i < height; ++i) { 
    for (int j = 0; j < width; ++j) { 
     ++histogram[depth.at<ushort>(i,j)]; 
    } 
    } 

    for(int i = 2; i < 0x10000; ++i) histogram[i] += histogram[i-1]; // Build a cumulative histogram for the indices in [1,0xFFFF] 

    for(int i = 0; i < height; ++i) { 
    for (int j = 0; j < width; ++j) { 
     if (uint16_t d = depth.at<ushort>(i,j)) { 
     int f = histogram[d] * 255/histogram[0xFFFF]; // 0-255 based on histogram location 
     color_depth.at<Vec3b>(i,j) = Vec3b(f, 0, 255 - f); 
     } else { 
     color_depth.at<Vec3b>(i,j) = Vec3b(0, 5, 20); 
     } 
    } 
    } 
} 

int main(int argc, char *argv[]) { 
    // Create a context object. This object owns the handles to all connected realsense devices 
    rs::context ctx; 

    // Access the first available RealSense device 
    rs::device * dev = ctx.get_device(0); 

    // Configure Infrared stream to run at VGA resolution at 30 frames per second 
    dev->enable_stream(rs::stream::depth, 640, 480, rs::format::z16, 30); 

    // Start streaming 
    dev->start(); 

    // Camera warmup - Dropped several first frames to let auto-exposure stabilize 
    for(int i = 0; i < 30; i++) 
     dev->wait_for_frames(); 

    // Creating OpenCV Matrix from a color image 
    Mat depth(Size(640, 480), CV_16U, (void*)dev->get_frame_data(rs::stream::depth), Mat::AUTO_STEP); 

    // Create a color depth 
    Mat color_depth; 
    make_depth_histogram(depth, color_depth); 

    // Create a normalized depth 
    double min, max; 
    minMaxLoc(depth, &min, &max); 
    Mat depth_normalized; 
    double alpha = 255.0/(max-min); 
    depth.convertTo(depth_normalized, CV_8U, alpha, -min*alpha); 

    // Display in a GUI 
    imshow("Display normalized depth", depth_normalized); 
    imshow("Display color depth", color_depth); 

    waitKey(0); 

    return 0; 
    } 
+0

当我做了“归一化深度”的步骤,我的新的8位图像看起来跳动,这意味着,图像中的所有像素变得很亮,那么很黑(所有像素的数量相同)。这有点奇怪。大约需要一秒钟才能变得非常光明,然后再过一秒钟才能变得非常黑暗,然后重复。你知道那可能是什么吗?也许一些自动曝光问题或相机的东西? – Pototo

+0

当我将最大值和最小值设置为常量时,闪烁消失。当我看着一个静态物体时没有闪烁。当事情四处移动时,会发生闪烁。这是有道理的,因为至少alpha总是在变化。 – Pototo

+0

您应该使用'make_depth_histogram()'来显示深度图。它有点花费时间,但可视化只能用于调试目的。 – Catree

1

,我发现这个问题,这得到满意的结果,唯一的解决方案是:

  • 将图像保存为PNG文件。 (PNG支持保存16位图像)
  • 使用matplotlib在彩色地图中查看它。

    #!/usr/bin/python3 
    import numpy as np 
    import cv2 
    import sys 
    from matplotlib import pyplot as plt 
    
    def printCoordinates(event): 
        x,y = event.xdata,event.ydata 
        if x != None: 
         print("X : ",x," Y: ",y," Value = ",img[np.int(y),np.int(x)]) 
    
    img = cv2.imread(sys.argv[1],cv2.CV_16UC1) 
    #img = img/65535 
    
    fig = plt.figure() 
    plt.imshow(img,cmap='nipy_spectral') 
    cid = fig.canvas.mpl_connect('button_press_event',printCoordinates) 
    plt.colorbar() 
    plt.show() 
    

的button_press_event是打印上点击的像素的确切像素值。

RGB Image RGB图像 Corresponding Depth Image 深度影像