ZED Open Capture  v0.6.0
Low level camera driver for the ZED stereo camera family
zed_oc_tune_stereo_sgbm.cpp

Example of how to use the VideoCapture class and OpenCV GUI controls to tune the depth extraction process.

//
// Copyright (c) 2021, STEREOLABS.
//
// All rights reserved.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ----> Includes
#include <iostream>
#include <sstream>
#include <string>
#include <mutex>
#include "videocapture.hpp"
// OpenCV includes
#include <opencv2/opencv.hpp>
// Sample includes
#include "calibration.hpp"
#include "stopwatch.hpp"
#include "stereo.hpp"
#include "ocv_display.hpp"
// <---- Includes
// ----> MACROS
#define USE_HALF_SIZE_DISPARITY
// <---- MACROS
// ----> Global variables
std::string preFiltDispWinName = "Pre-filtered disparity";
cv::Ptr<cv::StereoSGBM> left_matcher;
int maxMaxDisp=0;
bool params_initialized=false;
// <---- Global variables
// ----> Global functions
void on_trackbar_block_size( int newBlockSize, void* );
void on_trackbar_min_disparities( int newMinDisparities, void* );
void on_trackbar_num_disparities( int newNumDisparities, void* );
void on_trackbar_mode( int newMode, void* );
void on_trackbar_disp12MaxDiff(int newDisp12MaxDiff, void* );
void on_trackbar_preFilterCap(int newPreFilterCap, void* );
void on_trackbar_uniquenessRatio(int newUniquenessRatio, void* );
void on_trackbar_speckleWindowSize(int newSpeckleWindowSize, void* );
void on_trackbar_speckleRange(int newSpeckleRange, void* );
// <---- Global functions
int main(int argc, char *argv[])
{
// ----> Silence unused warning
(void)argc;
(void)argv;
// <---- Silence unused warning
// ----> Set Video parameters
#ifdef EMBEDDED_ARM
#else
#endif
params.verbose = verbose;
// <---- Set Video parameters
// ----> Create Video Capture
if( !cap.initializeVideo(-1) )
{
std::cerr << "Cannot open camera video capture" << std::endl;
std::cerr << "See verbosity level for more details." << std::endl;
return EXIT_FAILURE;
}
int sn = cap.getSerialNumber();
std::cout << "Connected to camera sn: " << sn << std::endl;
// <---- Create Video Capture
// ----> Retrieve calibration file from Stereolabs server
std::string calibration_file;
// ZED Calibration
unsigned int serial_number = sn;
// Download camera calibration file
if( !sl_oc::tools::downloadCalibrationFile(serial_number, calibration_file) )
{
std::cerr << "Could not load calibration file from Stereolabs servers" << std::endl;
return EXIT_FAILURE;
}
std::cout << "Calibration file found. Loading..." << std::endl;
// ----> Frame size
int w,h;
cap.getFrameSize(w,h);
// <---- Frame size
// ----> Initialize calibration
cv::Mat map_left_x, map_left_y;
cv::Mat map_right_x, map_right_y;
cv::Mat cameraMatrix_left, cameraMatrix_right;
sl_oc::tools::initCalibration(calibration_file, cv::Size(w/2,h), map_left_x, map_left_y, map_right_x, map_right_y,
cameraMatrix_left, cameraMatrix_right);
std::cout << " Camera Matrix L: \n" << cameraMatrix_left << std::endl << std::endl;
std::cout << " Camera Matrix R: \n" << cameraMatrix_right << std::endl << std::endl;
// <---- Initialize calibration
// Grab first valid frame couple
while (1)
{
// Get a new frame from camera
const sl_oc::video::Frame frame = cap.getLastFrame();
// ----> If the frame is valid we can convert, rectify and display it
if(frame.data!=nullptr)
{
// ----> Conversion from YUV 4:2:2 to BGR for visualization
frameYUV = cv::Mat( frame.height, frame.width, CV_8UC2, frame.data );
cv::cvtColor(frameYUV,frameBGR,cv::COLOR_YUV2BGR_YUYV);
// <---- Conversion from YUV 4:2:2 to BGR for visualization
// ----> Extract left and right images from side-by-side
left_raw = frameBGR(cv::Rect(0, 0, frameBGR.cols / 2, frameBGR.rows));
right_raw = frameBGR(cv::Rect(frameBGR.cols / 2, 0, frameBGR.cols / 2, frameBGR.rows));
// <---- Extract left and right images from side-by-side
// ----> Apply rectification
cv::remap(left_raw, left_rect, map_left_x, map_left_y, cv::INTER_LINEAR );
cv::remap(right_raw, right_rect, map_right_x, map_right_y, cv::INTER_LINEAR );
// <---- Apply rectification
break;
}
cv::waitKey(10);
}
// ----> Create tune GUI
#ifdef USE_HALF_SIZE_DISPARITY
#endif
cv::namedWindow(preFiltDispWinName, cv::WINDOW_AUTOSIZE); // Create Window
cv::createTrackbar( "blockSize", preFiltDispWinName, nullptr, 255, on_trackbar_block_size );
cv::setTrackbarMin( "blockSize", preFiltDispWinName, 1 );
cv::createTrackbar( "numDisparities", preFiltDispWinName, nullptr, maxMaxDisp, on_trackbar_num_disparities );
cv::setTrackbarMin( "numDisparities", preFiltDispWinName, 16 );
cv::createTrackbar( "minDisparity", preFiltDispWinName, nullptr, maxMaxDisp-16, on_trackbar_min_disparities );
cv::setTrackbarMin( "minDisparity", preFiltDispWinName, -maxMaxDisp );
cv::createTrackbar( "mode", preFiltDispWinName, nullptr, 3, on_trackbar_mode);
cv::setTrackbarMin( "mode", preFiltDispWinName, 0 );
cv::createTrackbar( "disp12MaxDiff", preFiltDispWinName, nullptr, maxMaxDisp, on_trackbar_disp12MaxDiff);
cv::setTrackbarMin( "disp12MaxDiff", preFiltDispWinName, -1 );
cv::createTrackbar( "preFilterCap", preFiltDispWinName, nullptr, 1024, on_trackbar_preFilterCap);
cv::setTrackbarMin( "preFilterCap", preFiltDispWinName, 0 );
cv::createTrackbar( "uniquenessRatio", preFiltDispWinName, nullptr, 99, on_trackbar_uniquenessRatio);
cv::setTrackbarMin( "uniquenessRatio", preFiltDispWinName, 0 );
cv::createTrackbar( "speckleWindowSize", preFiltDispWinName, nullptr, 255, on_trackbar_speckleWindowSize);
cv::setTrackbarMin( "speckleWindowSize", preFiltDispWinName, 0 );
cv::createTrackbar( "speckleRange", preFiltDispWinName, nullptr, 16, on_trackbar_speckleRange);
cv::setTrackbarMin( "speckleRange", preFiltDispWinName, 1 );
// <---- Create tune GUI
// ----> Stereo matcher initialization
left_matcher->setMinDisparity(stereoPar.minDisparity);
left_matcher->setNumDisparities(stereoPar.numDisparities);
left_matcher->setDisp12MaxDiff(stereoPar.disp12MaxDiff);
left_matcher->setPreFilterCap(stereoPar.preFilterCap);
left_matcher->setUniquenessRatio(stereoPar.uniquenessRatio);
left_matcher->setSpeckleWindowSize(stereoPar.speckleWindowSize);
left_matcher->setSpeckleRange(stereoPar.speckleRange);
// <---- Stereo matcher initialization
// ----> Update GUI value
cv::setTrackbarPos( "blockSize", preFiltDispWinName, stereoPar.blockSize );
cv::setTrackbarPos( "numDisparities", preFiltDispWinName, stereoPar.numDisparities );
cv::setTrackbarPos( "minDisparity", preFiltDispWinName, stereoPar.minDisparity );
cv::setTrackbarPos( "mode", preFiltDispWinName, stereoPar.mode );
cv::setTrackbarPos( "disp12MaxDiff", preFiltDispWinName, stereoPar.disp12MaxDiff );
cv::setTrackbarPos( "preFilterCap", preFiltDispWinName, stereoPar.preFilterCap );
cv::setTrackbarPos( "uniquenessRatio", preFiltDispWinName, stereoPar.uniquenessRatio );
cv::setTrackbarPos( "speckleWindowSize", preFiltDispWinName, stereoPar.speckleWindowSize );
cv::setTrackbarPos( "speckleRange", preFiltDispWinName, stereoPar.speckleRange );
// <---- Update GUI value
while(1)
{
// ----> Keyboard handling
int key = cv::waitKey( 5 );
if(key=='q' || key==27) // Quit
{
std::cout << "Save current stereo parameters? [Y/N]" << std::endl;
key = cv::waitKey(-1);
if(key=='Y' || key=='y')
{
}
break;
}
if(key=='l' || key=='L') // load parameters)
{
{
left_matcher->setMinDisparity(stereoPar.minDisparity);
left_matcher->setNumDisparities(stereoPar.numDisparities);
left_matcher->setDisp12MaxDiff(-(stereoPar.disp12MaxDiff-1));
left_matcher->setPreFilterCap(stereoPar.preFilterCap);
left_matcher->setUniquenessRatio(stereoPar.uniquenessRatio);
left_matcher->setSpeckleWindowSize(stereoPar.speckleWindowSize);
left_matcher->setSpeckleRange(stereoPar.speckleRange);
// ----> Update GUI value
cv::setTrackbarPos( "blockSize", preFiltDispWinName, stereoPar.blockSize );
cv::setTrackbarPos( "numDisparities", preFiltDispWinName, stereoPar.numDisparities );
cv::setTrackbarPos( "minDisparity", preFiltDispWinName, stereoPar.minDisparity );
cv::setTrackbarPos( "mode", preFiltDispWinName, stereoPar.mode );
cv::setTrackbarPos( "disp12MaxDiff", preFiltDispWinName, stereoPar.disp12MaxDiff );
cv::setTrackbarPos( "preFilterCap", preFiltDispWinName, stereoPar.preFilterCap );
cv::setTrackbarPos( "uniquenessRatio", preFiltDispWinName, stereoPar.uniquenessRatio );
cv::setTrackbarPos( "speckleWindowSize", preFiltDispWinName, stereoPar.speckleWindowSize );
cv::setTrackbarPos( "speckleRange", preFiltDispWinName, stereoPar.speckleRange );
// <---- Update GUI value
}
}
if(key=='s' || key=='S') // load parameters
{
}
if(key=='r' || key=='R') // reset default parameters
{
// ----> Update GUI value
cv::setTrackbarPos( "blockSize", preFiltDispWinName, stereoPar.blockSize );
cv::setTrackbarPos( "numDisparities", preFiltDispWinName, stereoPar.numDisparities );
cv::setTrackbarPos( "minDisparity", preFiltDispWinName, stereoPar.minDisparity );
cv::setTrackbarPos( "mode", preFiltDispWinName, stereoPar.mode );
cv::setTrackbarPos( "disp12MaxDiff", preFiltDispWinName, stereoPar.disp12MaxDiff );
cv::setTrackbarPos( "preFilterCap", preFiltDispWinName, stereoPar.preFilterCap );
cv::setTrackbarPos( "uniquenessRatio", preFiltDispWinName, stereoPar.uniquenessRatio );
cv::setTrackbarPos( "speckleWindowSize", preFiltDispWinName, stereoPar.speckleWindowSize );
cv::setTrackbarPos( "speckleRange", preFiltDispWinName, stereoPar.speckleRange );
// <---- Update GUI value
}
// <---- Keyboard handling
}
return EXIT_SUCCESS;
}
{
return;
// ----> Stereo matching
#ifdef USE_HALF_SIZE_DISPARITY
cv::resize(left_rect, left_for_matcher, cv::Size(), 0.5, 0.5, cv::INTER_AREA);
cv::resize(right_rect, right_for_matcher, cv::Size(), 0.5, 0.5, cv::INTER_AREA);
#else
#endif
left_matcher->setMinDisparity(stereoPar.minDisparity);
left_matcher->setNumDisparities(stereoPar.numDisparities);
left_matcher->setDisp12MaxDiff(stereoPar.disp12MaxDiff);
left_matcher->setPreFilterCap(stereoPar.preFilterCap);
left_matcher->setUniquenessRatio(stereoPar.uniquenessRatio);
left_matcher->setSpeckleWindowSize(stereoPar.speckleWindowSize);
left_matcher->setSpeckleRange(stereoPar.speckleRange);
#ifdef USE_HALF_SIZE_DISPARITY
#endif
std::cout << "Start stereo matching..." << std::endl;
std::cout << "... finished stereo matching" << std::endl;
double elapsed = stereo_clock.toc();
std::cout << "Stereo processing: " << elapsed << " sec - Freq: " << 1./elapsed << std::endl;
// <---- Stereo matching
// ----> Show disparity
//cv::ximgproc::getDisparityVis(left_disp,left_disp_vis,3.0);
cv::normalize(left_disp, left_disp_vis, 0, 255, cv::NORM_MINMAX, CV_8UC1);
#ifdef USE_HALF_SIZE_DISPARITY
cv::resize(left_disp_vis, left_disp_vis, cv::Size(), 2.0, 2.0, cv::INTER_AREA);
#endif
// <---- Show disparity
}
void on_trackbar_block_size( int newBlockSize, void* )
{
bool fixed = false;
if(newBlockSize==stereoPar.blockSize)
return;
if(newBlockSize%2!=1)
{
if(newBlockSize>stereoPar.blockSize)
++newBlockSize;
else
--newBlockSize;
fixed=true;
}
if(newBlockSize<1)
{
newBlockSize=1;
fixed=true;
}
if(newBlockSize>255)
{
newBlockSize=255;
fixed=true;
}
stereoPar.blockSize = newBlockSize;
if(fixed)
{
cv::setTrackbarPos("blockSize", preFiltDispWinName, newBlockSize);
}
std::cout << "New 'blockSize' value: " << stereoPar.blockSize << std::endl;
}
void on_trackbar_min_disparities( int newMinDisparities, void* )
{
if(newMinDisparities==stereoPar.minDisparity)
return;
stereoPar.minDisparity = newMinDisparities;
{
cv::setTrackbarPos("numDisparities", preFiltDispWinName, newNumDisparities);
std::cout << "New 'numDisparities' value: " << stereoPar.numDisparities << std::endl;
}
std::cout << "New 'minDisparity' value: " << stereoPar.minDisparity << std::endl;
}
void on_trackbar_num_disparities( int newNumDisparities, void* )
{
bool fixed = false;
if(newNumDisparities==stereoPar.numDisparities)
return;
if(newNumDisparities%16!=0)
{
if(newNumDisparities<stereoPar.numDisparities)
newNumDisparities = newNumDisparities/16;
else
newNumDisparities = newNumDisparities/16 + 1;
newNumDisparities*=16;
fixed=true;
}
stereoPar.numDisparities = newNumDisparities;
if(fixed)
{
cv::setTrackbarPos("numDisparities", preFiltDispWinName, newNumDisparities);
}
{
cv::setTrackbarPos("minDisparity", preFiltDispWinName, newMinDisparity);
std::cout << "New 'minDisparity' value: " << stereoPar.minDisparity << std::endl;
}
std::cout << "New 'numDisparities' value: " << stereoPar.numDisparities << std::endl;
}
void on_trackbar_mode( int newMode, void* )
{
if(newMode==stereoPar.mode)
return;
stereoPar.mode = newMode;
std::cout << "New 'mode' value: " << stereoPar.mode << std::endl;
}
void on_trackbar_disp12MaxDiff (int newDisp12MaxDiff, void* )
{
if(newDisp12MaxDiff==stereoPar.disp12MaxDiff)
return;
stereoPar.disp12MaxDiff = newDisp12MaxDiff;
std::cout << "New 'disp12MaxDiff' value: " << stereoPar.disp12MaxDiff << std::endl;
}
void on_trackbar_preFilterCap(int newPreFilterCap, void* )
{
if(newPreFilterCap==stereoPar.preFilterCap)
return;
stereoPar.preFilterCap = newPreFilterCap;
std::cout << "New 'preFilterCap' value: " << stereoPar.preFilterCap << std::endl;
}
void on_trackbar_uniquenessRatio(int newUniquenessRatio, void* )
{
if(newUniquenessRatio==stereoPar.uniquenessRatio)
return;
stereoPar.uniquenessRatio = newUniquenessRatio;
std::cout << "New 'uniquenessRatio' value: " << stereoPar.uniquenessRatio << std::endl;
}
void on_trackbar_speckleWindowSize(int newSpeckleWindowSize, void* )
{
if(newSpeckleWindowSize==stereoPar.speckleWindowSize)
return;
stereoPar.speckleWindowSize = newSpeckleWindowSize;
std::cout << "New 'speckleWindowSize' value: " << stereoPar.speckleWindowSize << std::endl;
}
void on_trackbar_speckleRange(int newSpeckleRange, void* )
{
if(newSpeckleRange==stereoPar.speckleRange)
return;
stereoPar.speckleRange = newSpeckleRange;
std::cout << "New 'speckleRange' value: " << stereoPar.speckleRange << std::endl;
}
The StereoSgbmPar class is used to store/retrieve the stereo matching parameters.
Definition: stereo.hpp:20
int P1
[default: 24*blockSize*blockSize] The first parameter controlling the disparity smoothness....
Definition: stereo.hpp:57
int disp12MaxDiff
[default: 96] Maximum allowed difference (in integer pixel units) in the left-right disparity check....
Definition: stereo.hpp:59
int speckleWindowSize
[default: 255] Maximum size of smooth disparity regions to consider their noise speckles and invalida...
Definition: stereo.hpp:62
int uniquenessRatio
[default: 5] Margin in percentage by which the best (minimum) computed cost function value should "wi...
Definition: stereo.hpp:61
int minDisparity
[default: 0] Minimum possible disparity value. Normally, it is zero but sometimes rectification algor...
Definition: stereo.hpp:54
void setDefaultValues()
set default stereo matching parameters
Definition: stereo.hpp:69
bool save()
save stereo matching parameters
Definition: stereo.hpp:120
bool load()
load stereo matching parameters
Definition: stereo.hpp:87
int numDisparities
[default: 96] Maximum disparity minus minimum disparity. The value is always greater than zero....
Definition: stereo.hpp:55
int mode
Set it to StereoSGBM::MODE_HH to run the full-scale two-pass dynamic programming algorithm....
Definition: stereo.hpp:56
int speckleRange
[default: 1] Maximum disparity variation within each connected component. If you do speckle filtering...
Definition: stereo.hpp:63
int blockSize
[default: 3] Matched block size. It must be an odd number >=1 . Normally, it should be somewhere in t...
Definition: stereo.hpp:53
void print()
print the current stereo matching parameters on standard output
Definition: stereo.hpp:150
int preFilterCap
[default: 63] Truncation value for the prefiltered image pixels. The algorithm first computes x-deriv...
Definition: stereo.hpp:60
int P2
[default: 4*PI]The second parameter controlling the disparity smoothness. The larger the values are,...
Definition: stereo.hpp:58
Stop Timer used to measure time intervals.
Definition: stopwatch.hpp:34
double toc()
Calculates the seconds elapsed from the last tic.
Definition: stopwatch.hpp:55
The VideoCapture class provides image grabbing functions and settings control for all the Stereolabs ...
bool initCalibration(std::string calibration_file, cv::Size2i image_size, cv::Mat &map_left_x, cv::Mat &map_left_y, cv::Mat &map_right_x, cv::Mat &map_right_y, cv::Mat &cameraMatrix_left, cv::Mat &cameraMatrix_right, double *baseline=nullptr)
void showImage(std::string name, cv::UMat &img, sl_oc::video::RESOLUTION res, bool change_name=true, std::string info="")
Rescale the OpenCV T-API images [cv::UMat] according to the selected resolution to better display the...
Definition: ocv_display.hpp:27
bool downloadCalibrationFile(unsigned int serial_number, std::string &calibration_file)
@ FPS_30
30 Frames per second. Not available for RESOLUTION::HD2K.
VERBOSITY
Definition: defines.hpp:85
@ INFO
Definition: defines.hpp:89
The Frame struct containing the acquired video frames.
uint16_t height
Frame height.
uint16_t width
Frame width.
uint8_t * data
Frame data in YUV 4:2:2 format.
The camera configuration parameters.
RESOLUTION res
Camera resolution.
FPS fps
Frames per second.
cv::Mat left_raw
int main(int argc, char *argv[])
sl_oc::tools::StereoSgbmPar stereoPar
std::string preFiltDispWinName
void on_trackbar_mode(int newMode, void *)
cv::Mat frameBGR
cv::Mat left_for_matcher
void on_trackbar_speckleRange(int newSpeckleRange, void *)
void on_trackbar_num_disparities(int newNumDisparities, void *)
sl_oc::video::VideoParams params
cv::Mat right_raw
void applyStereoMatching()
bool params_initialized
cv::Mat right_for_matcher
void on_trackbar_min_disparities(int newMinDisparities, void *)
void on_trackbar_preFilterCap(int newPreFilterCap, void *)
void on_trackbar_disp12MaxDiff(int newDisp12MaxDiff, void *)
cv::Mat left_disp_vis
cv::Mat frameYUV
void on_trackbar_block_size(int newBlockSize, void *)
cv::Mat left_rect
void on_trackbar_uniquenessRatio(int newUniquenessRatio, void *)
void on_trackbar_speckleWindowSize(int newSpeckleWindowSize, void *)
cv::Mat left_disp
cv::Mat right_rect
cv::Ptr< cv::StereoSGBM > left_matcher