2017-02-21 3 views
0

Leuten,RealSense OpenCV Tiefes Bild zu dunkel

Ich habe ein realsense SR300, aber wenn ich in einem opencv Fenster meiner Tiefenbild anzuzeigen, sieht es zu dunkel. Wie kann ich das beheben? Wenn ich die richtigen Beispiele benutze, sehen die Bilder gut aus, aber die Beispiele verwenden OpenGL. Aber ich brauche OpenCV für meine Projekte. Hier ist mein Code:

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

Ich bin mir nicht sicher, warum mein Bild so dunkel ist. Ich möchte es so etwas wie die kinect oder Xtion suchen, wenn ich openni_launch von ROS laufen

Antwort

2

Edit:

  • vermute ich, dass zurückzuführen ist auf

    Die normalisierte Funktion unten einige Flimmern erzeugt der maximale Tiefenwert flackert.

  • Der minimale Tiefenwert ist immer 0, da dieser Wert verwendet wird, wenn die Tiefe ungültig ist und somit der Tiefenbereich falsch wird.

Stattdessen sollten Sie diese verwenden:

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

Was Sie beachten ist, da die Tiefenstrom auf 16 Bit codiert (rs::stream::z16), während, wenn sie angezeigt werden nur 8 Bit verwendet werden.

Sie können Ihre Tiefenkarte normalisiert:

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); 

Oder eine Art colormap verwenden, um die Tiefe anzuzeigen: make_depth_histogram().

Full-Demo-Code:

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

Wenn ich die „normalisiert Tiefe“ Schritt tun, mein neues 8-Bit-Bild zu pulsieren scheint, das heißt, alle Pixel im Bild wirklich hell bekommen, dann richtig dunkel (alle Pixel um den gleichen Betrag). Es ist irgendwie komisch. Es dauert ungefähr eine Sekunde, um wirklich hell zu werden, und dann noch eine Sekunde, um wirklich dunkel zu werden, und wiederhole es. Weißt du, was das sein könnte? Vielleicht ein Problem mit der automatischen Belichtung oder etwas mit der Kamera? – Pototo

+0

Wenn ich Max und Min auf Konstanten setze, verschwindet das Flackern. Wenn ich ein statisches Objekt betrachte, flackert es nicht. Wenn sich Dinge bewegen, geschieht Flackern. Es macht Sinn, da zumindest Alpha sich immer ändert. – Pototo

+0

Sie sollten 'make_depth_histogram()' verwenden, um die Tiefenkarte zu visualisieren. Es ist ein wenig zeitaufwendiger, aber die Visualisierung sollte sowieso nur für Debugzwecke verwendet werden. – Catree

1

Die einzige Lösung, die ich für dieses Problem gefunden, die zufriedenstellende Ergebnisse gibt, ist die folgende:

  • Speichern Sie das Bild als PNG-Datei. (PNG unterstützt das Speichern von 16-Bit-Bildern)
  • Verwenden Sie matplotlib, um es in einer farbigen Karte anzuzeigen.

    #!/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() 
    

Die button_press_event ist der genauen Pixelwert auf dem Pixel geklickt zu drucken.

RGB Image RGB Bild Corresponding Depth Image entsprechendes Tiefenbild