2017-02-21 632 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 深度影像