Skip to content

Commit b1e9dd5

Browse files
dimitrisPsalalek
authored andcommitted
Merge pull request #1941 from surgical-vision:quasi-dense-stereo
Implementation of Quasi Dense Stereo algorithm. (#1941) * initial commit. * Remove license header. * Fix python wrap flags * Change std::string to cv::String, in function declarations, to resolve compilation issues. * Add python wrapper extending header * Fix python wrapper conflicts * Fix implicit type conversions * Change C API types and enums to C++. * Remove redundant included headers and move wanted headers to src/precomp.hpp * Remove saturate header * Remove unnecessary python wrapping flags * Removed defaults parameter header * Split declaration and implementation of the class using Pimpl. * Fix to comply with new public API. * Remove unnecessary modules * Fix maybe-uninitialized warnings on linux * Migration to stereo module * Remove CV_PROP_RW flag. * Remove CV_EXPORTS flags from class members. * Fix: Removed misplaced flag * Remove empty lines. * Move queue to private headers. * Fix default arguments of public methods. * Add authors information and switch to the compact version of license header. * Reorganize and fix markdown files. Create a table of content and move tutorials in new directories. Modify samples and tutorials to use snippet and include Doxygen commands. * Change argument name dMatch->denseMatch, to avoid confusion with cv::DMatch build-in type. * Remove duplicate snippet. * Fix: change vector resize to reserve. * Fix: replace extensive license header with the compact version.
1 parent 2522124 commit b1e9dd5

12 files changed

+1087
-2
lines changed

modules/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ $ cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -D BUILD_opencv_<r
5454

5555
- **sfm**: Structure from Motion -- This module contains algorithms to perform 3d reconstruction from 2d images. The core of the module is a light version of Libmv.
5656

57-
- **stereo**: Stereo Correspondence -- Stereo matching done with different descriptors: Census / CS-Census / MCT / BRIEF / MV.
57+
- **stereo**: Stereo Correspondence -- Stereo matching done with different descriptors: Census / CS-Census / MCT / BRIEF / MV and dense stereo correspondence using Quasi Dense Stereo method.
5858

5959
- **structured_light**: Structured Light Use -- How to generate and project gray code patterns and use them to find dense depth in a scene.
6060

modules/stereo/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
set(the_description "Stereo Correspondence")
2-
ocv_define_module(stereo opencv_imgproc opencv_features2d opencv_core opencv_calib3d)
2+
ocv_define_module(stereo opencv_imgproc opencv_features2d opencv_core opencv_calib3d opencv_tracking opencv_video)

modules/stereo/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,10 @@ Stereo Correspondence with different descriptors
22
================================================
33

44
Stereo matching done with different descriptors: Census / CS-Census / MCT / BRIEF / MV.
5+
6+
Quasi Dense Stereo
7+
======================
8+
9+
Quasi Dense Stereo is method for performing dense stereo matching.
10+
The code uses pyramidal Lucas-Kanade with Shi-Tomasi features to get the initial seed correspondences.
11+
Then these seeds are propagated by using mentioned growing scheme.

modules/stereo/doc/stereo.bib

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
@InProceedings{Stoyanov2010,
2+
author="Stoyanov, Danail
3+
and Scarzanella, Marco Visentini
4+
and Pratt, Philip
5+
and Yang, Guang-Zhong",
6+
editor="Jiang, Tianzi
7+
and Navab, Nassir
8+
and Pluim, Josien P. W.
9+
and Viergever, Max A.",
10+
title="Real-Time Stereo Reconstruction in Robotically Assisted Minimally Invasive Surgery",
11+
booktitle="Medical Image Computing and Computer-Assisted Intervention (MICCAI 2010)",
12+
year="2010",
13+
publisher="Springer Berlin Heidelberg",
14+
address="Berlin, Heidelberg",
15+
pages="275--282",
16+
abstract="The recovery of 3D tissue structure and morphology during robotic assisted surgery is an important step towards accurate deployment of surgical guidance and control techniques in minimally invasive therapies. In this article, we present a novel stereo reconstruction algorithm that propagates disparity information around a set of candidate feature matches. This has the advantage of avoiding problems with specular highlights, occlusions from instruments and view dependent illumination bias. Furthermore, the algorithm can be used with any feature matching strategy allowing the propagation of depth in very disparate views. Validation is provided for a phantom model with known geometry and this data is available online in order to establish a structured validation scheme in the field. The practical value of the proposed method is further demonstrated by reconstructions on various in vivo images of robotic assisted procedures, which are also available to the community.",
17+
isbn="978-3-642-15705-9"
18+
}
19+
20+
@article{Lhuillier2000,
21+
abstract = {A new robust dense matching algorithm is introduced. The algorithm$\backslash$nstarts from matching the most textured points, then a match propagation$\backslash$nalgorithm is developed with the best first strategy to dense matching.$\backslash$nNext, the matching map is regularised by using the local geometric$\backslash$nconstraints encoded by planar affine applications and by using the$\backslash$nglobal geometric constraint encoded by the fundamental matrix. Two most$\backslash$ndistinctive features are a match propagation strategy developed by$\backslash$nanalogy to region growing and a successive regularisation by local and$\backslash$nglobal geometric constraints. The algorithm is efficient, robust and can$\backslash$ncope with wide disparity. The algorithm is demonstrated on many real$\backslash$nimage pairs, and applications on image interpolation and a creation of$\backslash$nnovel views are also presented},
22+
author = {Lhuillier, Maxime and Quan, Long},
23+
doi = {10.1109/ICPR.2000.905620},
24+
file = {:home/dimitrisps/Desktop/ucl/papers/quasiDenseMatching.pdf:pdf},
25+
isbn = {0-7695-0750-6},
26+
issn = {10514651},
27+
journal = {Proceedings-International Conference on Pattern Recognition},
28+
number = {1},
29+
pages = {968--972},
30+
title = {{Robust dense matching using local and global geometric constraints}},
31+
volume = {15},
32+
year = {2000}
33+
}

modules/stereo/include/opencv2/stereo.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "opencv2/core/affine.hpp"
5050
#include "opencv2/stereo/descriptor.hpp"
5151
#include "opencv2/stereo/matching.hpp"
52+
#include <opencv2/stereo/quasi_dense_stereo.hpp>
5253

5354
/**
5455
@defgroup stereo Stereo Correspondance Algorithms
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
5+
//authors: Danail Stoyanov, Evangelos Mazomenos, Dimitrios Psychogyios
6+
7+
8+
//__OPENCV_QUASI_DENSE_STEREO_H__
9+
#ifndef __OPENCV_QUASI_DENSE_STEREO_H__
10+
#define __OPENCV_QUASI_DENSE_STEREO_H__
11+
12+
13+
14+
#include <opencv2/core.hpp>
15+
16+
17+
namespace cv
18+
{
19+
namespace stereo
20+
{
21+
/** \addtogroup stereo
22+
* @{
23+
*/
24+
25+
26+
// A basic match structure
27+
struct CV_EXPORTS Match
28+
{
29+
cv::Point2i p0;
30+
cv::Point2i p1;
31+
float corr;
32+
33+
bool operator < (const Match & rhs) const//fixme may be used uninitialized in this function
34+
{
35+
return this->corr < rhs.corr;
36+
}
37+
};
38+
struct CV_EXPORTS PropagationParameters
39+
{
40+
int corrWinSizeX; // similarity window
41+
int corrWinSizeY;
42+
43+
int borderX; // border to ignore
44+
int borderY;
45+
46+
//matching
47+
float correlationThreshold; // correlation threshold
48+
float textrureThreshold; // texture threshold
49+
50+
int neighborhoodSize; // neighborhood size
51+
int disparityGradient; // disparity gradient threshold
52+
53+
// Parameters for LK flow algorithm
54+
int lkTemplateSize;
55+
int lkPyrLvl;
56+
int lkTermParam1;
57+
float lkTermParam2;
58+
59+
// Parameters for GFT algorithm.
60+
float gftQualityThres;
61+
int gftMinSeperationDist;
62+
int gftMaxNumFeatures;
63+
64+
};
65+
66+
67+
/**
68+
* @brief Class containing the methods needed for Quasi Dense Stereo computation.
69+
*
70+
* This module contains the code to perform quasi dense stereo matching.
71+
* The method initially starts with a sparse 3D reconstruction based on feature matching across a
72+
* stereo image pair and subsequently propagates the structure into neighboring image regions.
73+
* To obtain initial seed correspondences, the algorithm locates Shi and Tomashi features in the
74+
* left image of the stereo pair and then tracks them using pyramidal Lucas-Kanade in the right image.
75+
* To densify the sparse correspondences, the algorithm computes the zero-mean normalized
76+
* cross-correlation (ZNCC) in small patches around every seed pair and uses it as a quality metric
77+
* for each match. In this code, we introduce a custom structure to store the location and ZNCC value
78+
* of correspondences called "Match". Seed Matches are stored in a priority queue sorted according to
79+
* their ZNCC value, allowing for the best quality Match to be readily available. The algorithm pops
80+
* Matches and uses them to extract new matches around them. This is done by considering a small
81+
* neighboring area around each Seed and retrieving correspondences above a certain texture threshold
82+
* that are not previously computed. New matches are stored in the seed priority queue and used as seeds.
83+
* The propagation process ends when no additional matches can be retrieved.
84+
*
85+
*
86+
* @sa This code represents the work presented in @cite Stoyanov2010.
87+
* If this code is useful for your work please cite @cite Stoyanov2010.
88+
*
89+
* Also the original growing scheme idea is described in @cite Lhuillier2000
90+
*
91+
*/
92+
93+
class CV_EXPORTS QuasiDenseStereo
94+
{
95+
public:
96+
/**
97+
* @brief destructor
98+
* Method to free all the memory allocated by matrices and vectors in this class.
99+
*/
100+
virtual ~QuasiDenseStereo() = 0;
101+
102+
103+
/**
104+
* @brief Load a file containing the configuration parameters of the class.
105+
* @param[in] filepath The location of the .YAML file containing the configuration parameters.
106+
* @note default value is an empty string in which case the default parameters will be loaded.
107+
* @retval 1: If the path is not empty and the program loaded the parameters successfully.
108+
* @retval 0: If the path is empty and the program loaded default parameters.
109+
* @retval -1: If the file location is not valid or the program could not open the file and
110+
* loaded default parameters from defaults.hpp.
111+
* @note The method is automatically called in the constructor and configures the class.
112+
* @note Loading different parameters will have an effect on the output. This is useful for tuning
113+
* in case of video processing.
114+
* @sa loadParameters
115+
*/
116+
virtual int loadParameters(cv::String filepath) = 0;
117+
118+
119+
/**
120+
* @brief Save a file containing all the configuration parameters the class is currently set to.
121+
* @param[in] filepath The location to store the parameters file.
122+
* @note Calling this method with no arguments will result in storing class parameters to a file
123+
* names "qds_parameters.yaml" in the root project folder.
124+
* @note This method can be used to generate a template file for tuning the class.
125+
* @sa loadParameters
126+
*/
127+
virtual int saveParameters(cv::String filepath) = 0;
128+
129+
130+
/**
131+
* @brief Get The sparse corresponding points.
132+
* @param[out] sMatches A vector containing all sparse correspondences.
133+
* @note The method clears the sMatches vector.
134+
* @note The returned Match elements inside the sMatches vector, do not use corr member.
135+
*/
136+
virtual void getSparseMatches(std::vector<stereo::Match> &sMatches) = 0;
137+
138+
139+
/**
140+
* @brief Get The dense corresponding points.
141+
* @param[out] denseMatches A vector containing all dense matches.
142+
* @note The method clears the denseMatches vector.
143+
* @note The returned Match elements inside the sMatches vector, do not use corr member.
144+
*/
145+
virtual void getDenseMatches(std::vector<stereo::Match> &denseMatches) = 0;
146+
147+
148+
149+
/**
150+
* @brief Main process of the algorithm. This method computes the sparse seeds and then densifies them.
151+
*
152+
* Initially input images are converted to gray-scale and then the sparseMatching method
153+
* is called to obtain the sparse stereo. Finally quasiDenseMatching is called to densify the corresponding
154+
* points.
155+
* @param[in] imgLeft The left Channel of a stereo image pair.
156+
* @param[in] imgRight The right Channel of a stereo image pair.
157+
* @note If input images are in color, the method assumes that are BGR and converts them to grayscale.
158+
* @sa sparseMatching
159+
* @sa quasiDenseMatching
160+
*/
161+
virtual void process(const cv::Mat &imgLeft ,const cv::Mat &imgRight) = 0;
162+
163+
164+
/**
165+
* @brief Specify pixel coordinates in the left image and get its corresponding location in the right image.
166+
* @param[in] x The x pixel coordinate in the left image channel.
167+
* @param[in] y The y pixel coordinate in the left image channel.
168+
* @retval cv::Point(x, y) The location of the corresponding pixel in the right image.
169+
* @retval cv::Point(0, 0) (NO_MATCH) if no match is found in the right image for the specified pixel location in the left image.
170+
* @note This method should be always called after process, otherwise the matches will not be correct.
171+
*/
172+
virtual cv::Point2f getMatch(const int x, const int y) = 0;
173+
174+
175+
/**
176+
* @brief Compute and return the disparity map based on the correspondences found in the "process" method.
177+
* @param[in] disparityLvls The level of detail in output disparity image.
178+
* @note Default level is 50
179+
* @return cv::Mat containing a the disparity image in grayscale.
180+
* @sa computeDisparity
181+
* @sa quantizeDisparity
182+
*/
183+
virtual cv::Mat getDisparity(uint8_t disparityLvls=50) = 0;
184+
185+
186+
static cv::Ptr<QuasiDenseStereo> create(cv::Size monoImgSize, cv::String paramFilepath = cv::String());
187+
188+
189+
PropagationParameters Param;
190+
};
191+
192+
} //namespace cv
193+
} //namespace stereo
194+
195+
/** @}*/
196+
197+
#endif // __OPENCV_QUASI_DENSE_STEREO_H__
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include <opencv2/core.hpp>
2+
#include <opencv2/highgui.hpp>
3+
#include <fstream>
4+
#include <opencv2/stereo.hpp>
5+
6+
7+
8+
9+
using namespace cv;
10+
using namespace std;
11+
12+
13+
int main()
14+
{
15+
//! [load]
16+
cv::Mat rightImg, leftImg;
17+
leftImg = imread("./imgLeft.png", IMREAD_COLOR);
18+
rightImg = imread("./imgRight.png", IMREAD_COLOR);
19+
//! [load]
20+
21+
22+
//! [create]
23+
cv::Size frameSize = leftImg.size();
24+
Ptr<stereo::QuasiDenseStereo> stereo = stereo::QuasiDenseStereo::create(frameSize);
25+
//! [create]
26+
27+
28+
//! [process]
29+
stereo->process(leftImg, rightImg);
30+
//! [process]
31+
32+
33+
//! [disp]
34+
uint8_t displvl = 80;
35+
cv::Mat disp;
36+
disp = stereo->getDisparity(displvl);
37+
cv::namedWindow("disparity map");
38+
cv::imshow("disparity map", disp);
39+
//! [disp]
40+
41+
42+
cv::namedWindow("right channel");
43+
cv::namedWindow("left channel");
44+
cv::imshow("left channel", leftImg);
45+
cv::imshow("right channel", rightImg);
46+
47+
48+
//! [export]
49+
vector<stereo::Match> matches;
50+
stereo->getDenseMatches(matches);
51+
std::ofstream dense("./dense.txt", std::ios::out);
52+
for (uint i=0; i< matches.size(); i++)
53+
{
54+
dense << matches[i].p0 << matches[i].p1 << endl;
55+
}
56+
dense.close();
57+
//! [export]
58+
59+
60+
61+
cv::waitKey(0);
62+
63+
return 0;
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <opencv2/core.hpp>
2+
#include <opencv2/stereo.hpp>
3+
4+
using namespace cv;
5+
using namespace std;
6+
7+
int main(int argc, char* argv[])
8+
{
9+
//! [create]
10+
Ptr<stereo::QuasiDenseStereo> stereo = stereo::QuasiDenseStereo::create(cv::Size(5,5));
11+
//! [create]
12+
13+
14+
//! [write]
15+
std::string parameterFileLocation = "./parameters.yaml";
16+
if (argc > 1)
17+
parameterFileLocation = argv[1];
18+
stereo->saveParameters(parameterFileLocation);
19+
//! [write]
20+
21+
return 0;
22+
}

0 commit comments

Comments
 (0)