Skip to content

Commit 6a0545e

Browse files
committed
Improving DisparityWLSFilter interface and adding a tutorial
Now the filter natively supports StereoBM and StereoSGBM with no parameter tuning required. Also, now user won't need to set the ROI and the right matcher parameters manually, it is all done in the respective convenience factory method based on the left matcher instance. Tutorial was added to clarify the provided example of use.
1 parent 7c421ba commit 6a0545e

File tree

10 files changed

+289
-75
lines changed

10 files changed

+289
-75
lines changed

modules/ximgproc/include/opencv2/ximgproc/disparity_filter.hpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#ifdef __cplusplus
4040

4141
#include <opencv2/core.hpp>
42+
#include <opencv2/calib3d.hpp>
4243

4344
namespace cv {
4445
namespace ximgproc {
@@ -63,15 +64,15 @@ class CV_EXPORTS_W DisparityFilter : public Algorithm
6364
6465
@param filtered_disparity_map output disparity map.
6566
66-
@param ROI region of the disparity map to filter.
67-
6867
@param disparity_map_right optional argument, some implementations might also use the disparity map
6968
of the right view to compute confidence maps, for instance.
7069
70+
@param ROI region of the disparity map to filter. Optional, usually it should be set automatically.
71+
7172
@param right_view optional argument, some implementations might also use the right view of the original
7273
stereo-pair.
7374
*/
74-
CV_WRAP virtual void filter(InputArray disparity_map_left, InputArray left_view, OutputArray filtered_disparity_map, Rect ROI, InputArray disparity_map_right = Mat(), InputArray right_view = Mat()) = 0;
75+
CV_WRAP virtual void filter(InputArray disparity_map_left, InputArray left_view, OutputArray filtered_disparity_map, InputArray disparity_map_right = Mat(), Rect ROI = Rect(), InputArray right_view = Mat()) = 0;
7576
};
7677

7778
/** @brief Disparity map filter based on Weighted Least Squares filter (in form of Fast Global Smoother that
@@ -106,8 +107,7 @@ class CV_EXPORTS_W DisparityWLSFilter : public DisparityFilter
106107
/** @see getLRCthresh */
107108
CV_WRAP virtual void setLRCthresh(int _LRC_thresh) = 0;
108109
/** @brief DepthDiscontinuityRadius is a parameter used in confidence computation. It defines the size of
109-
low-confidence regions around depth discontinuities. For typical window sizes used in stereo matching the
110-
optimal value is around 5.
110+
low-confidence regions around depth discontinuities.
111111
*/
112112
CV_WRAP virtual int getDepthDiscontinuityRadius() = 0;
113113
/** @see getDepthDiscontinuityRadius */
@@ -117,16 +117,36 @@ class CV_EXPORTS_W DisparityWLSFilter : public DisparityFilter
117117
correct disparity values with a high degree of confidence).
118118
*/
119119
CV_WRAP virtual Mat getConfidenceMap() = 0;
120-
120+
/** @brief Get the ROI used in the last filter call
121+
*/
122+
CV_WRAP virtual Rect getROI() = 0;
121123
};
122124

123-
/** @brief Factory method, create instance of DisparityWLSFilter and execute the initialization routines.
125+
/** @brief Convenience factory method that creates an instance of DisparityWLSFilter and sets up all the relevant
126+
filter parameters automatically based on the matcher instance. Currently supports only StereoBM and StereoSGBM.
127+
128+
@param matcher_left stereo matcher instance that will be used with the filter
129+
*/
130+
CV_EXPORTS_W
131+
Ptr<DisparityWLSFilter> createDisparityWLSFilter(Ptr<StereoMatcher> matcher_left);
132+
133+
/** @brief Convenience method to set up the matcher for computing the right-view disparity map
134+
that is required in case of filtering with confidence.
135+
136+
@param matcher_left main stereo matcher instance that will be used with the filter
137+
*/
138+
CV_EXPORTS_W
139+
Ptr<StereoMatcher> createRightMatcher(Ptr<StereoMatcher> matcher_left);
140+
141+
/** @brief More generic factory method, create instance of DisparityWLSFilter and execute basic
142+
initialization routines. When using this method you will need to set-up the ROI, matchers and
143+
other parameters by yourself.
124144
125145
@param use_confidence filtering with confidence requires two disparity maps (for the left and right views) and is
126146
approximately two times slower. However, quality is typically significantly better.
127147
*/
128148
CV_EXPORTS_W
129-
Ptr<DisparityWLSFilter> createDisparityWLSFilter(bool use_confidence);
149+
Ptr<DisparityWLSFilter> createDisparityWLSFilterGeneric(bool use_confidence);
130150

131151
//////////////////////////////////////////////////////////////////////////
132152
//////////////////////////////////////////////////////////////////////////

modules/ximgproc/perf/perf_disparity_wls_filter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ PERF_TEST_P( DisparityWLSFilterPerfTest, perf, Combine(GuideTypes::all(), SrcTyp
8585
cv::setNumThreads(cv::getNumberOfCPUs());
8686
TEST_CYCLE_N(10)
8787
{
88-
Ptr<DisparityWLSFilter> wls_filter = createDisparityWLSFilter(use_conf);
89-
wls_filter->filter(disp_left,guide,dst,ROI,disp_right);
88+
Ptr<DisparityWLSFilter> wls_filter = createDisparityWLSFilterGeneric(use_conf);
89+
wls_filter->filter(disp_left,guide,dst,disp_right,ROI);
9090
}
9191

9292
SANITY_CHECK(dst);

modules/ximgproc/samples/disparity_filtering.cpp

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ const String keys =
2323
"{algorithm |bm | stereo matching method (bm or sgbm) }"
2424
"{filter |wls_conf | used post-filtering (wls_conf or wls_no_conf) }"
2525
"{no-display | | don't display results }"
26-
"{no-downscale | | prevent stereo matching on downscaled views }"
26+
"{no-downscale | | force stereo matching on full-sized views to improve quality }"
2727
"{dst_conf_path |None | optional path to save the confidence map used in filtering }"
2828
"{vis_mult |1.0 | coefficient used to scale disparity map visualizations }"
2929
"{max_disparity |160 | parameter of stereo matching }"
30-
"{window_size |19 | parameter of stereo matching }"
30+
"{window_size |-1 | parameter of stereo matching }"
3131
"{wls_lambda |8000.0 | parameter of post-filtering }"
32-
"{wls_sigma |1.0 | parameter of post-filtering }"
32+
"{wls_sigma |1.5 | parameter of post-filtering }"
3333
;
3434

3535
int main(int argc, char** argv)
@@ -54,17 +54,30 @@ int main(int argc, char** argv)
5454
bool no_display = parser.has("no-display");
5555
bool no_downscale = parser.has("no-downscale");
5656
int max_disp = parser.get<int>("max_disparity");
57-
int wsize = parser.get<int>("window_size");
5857
double lambda = parser.get<double>("wls_lambda");
5958
double sigma = parser.get<double>("wls_sigma");
6059
double vis_mult = parser.get<double>("vis_mult");
6160

61+
int wsize;
62+
if(parser.get<int>("window_size")>=0) //user provided window_size value
63+
wsize = parser.get<int>("window_size");
64+
else
65+
{
66+
if(algo=="sgbm")
67+
wsize = 3; //default window size for SGBM
68+
else if(!no_downscale && algo=="bm" && filter=="wls_conf")
69+
wsize = 7; //default window size for BM on downscaled views (downscaling is performed only for wls_conf)
70+
else
71+
wsize = 15; //default window size for BM on full-sized views
72+
}
73+
6274
if (!parser.check())
6375
{
6476
parser.printErrors();
6577
return -1;
6678
}
6779

80+
//! [load_views]
6881
Mat left = imread(left_im ,IMREAD_COLOR);
6982
if ( left.empty() )
7083
{
@@ -78,6 +91,7 @@ int main(int argc, char** argv)
7891
cout<<"Cannot read image file: "<<right_im;
7992
return -1;
8093
}
94+
//! [load_views]
8195

8296
bool noGT;
8397
Mat GT_disp;
@@ -99,6 +113,7 @@ int main(int argc, char** argv)
99113
Mat conf_map = Mat(left.rows,left.cols,CV_8U);
100114
conf_map = Scalar(255);
101115
Rect ROI;
116+
Ptr<DisparityWLSFilter> wls_filter;
102117
double matching_time, filtering_time;
103118
if(max_disp<=0 || max_disp%16!=0)
104119
{
@@ -110,56 +125,51 @@ int main(int argc, char** argv)
110125
cout<<"Incorrect window_size value: it should be positive and odd";
111126
return -1;
112127
}
113-
if(filter=="wls_conf")
128+
if(filter=="wls_conf") // filtering with confidence (significantly better quality than wls_no_conf)
114129
{
115130
if(!no_downscale)
116131
{
117-
wsize = wsize/2;
118-
if(wsize%2==0) wsize++;
132+
// downscale the views to speed-up the matching stage, as we will need to compute both left
133+
// and right disparity maps for confidence map computation
134+
//! [downscale]
119135
max_disp/=2;
120136
if(max_disp%16!=0)
121137
max_disp += 16-(max_disp%16);
122138
resize(left ,left_for_matcher ,Size(),0.5,0.5);
123139
resize(right,right_for_matcher,Size(),0.5,0.5);
140+
//! [downscale]
124141
}
125142
else
126143
{
127144
left_for_matcher = left.clone();
128145
right_for_matcher = right.clone();
129146
}
130147

131-
132148
if(algo=="bm")
133149
{
134-
Ptr<StereoBM> left_matcher = StereoBM::create(max_disp,wsize);
135-
left_matcher->setMinDisparity(0);
136-
Ptr<StereoBM> right_matcher = StereoBM::create(max_disp,wsize);
137-
right_matcher->setMinDisparity(-max_disp+1);
138-
left_matcher->setTextureThreshold(0);
139-
left_matcher->setUniquenessRatio(0);
140-
right_matcher->setTextureThreshold(0);
141-
right_matcher->setUniquenessRatio(0);
142-
cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
150+
//! [matching]
151+
Ptr<StereoBM> left_matcher = StereoBM::create(max_disp,wsize);
152+
wls_filter = createDisparityWLSFilter(left_matcher);
153+
Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
154+
155+
cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
143156
cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY);
144-
ROI = computeROI(left_for_matcher.size(),left_matcher);
145157

146158
matching_time = (double)getTickCount();
147159
left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp);
148160
right_matcher->compute(right_for_matcher,left_for_matcher, right_disp);
149161
matching_time = ((double)getTickCount() - matching_time)/getTickFrequency();
162+
//! [matching]
150163
}
151164
else if(algo=="sgbm")
152165
{
153166
Ptr<StereoSGBM> left_matcher = StereoSGBM::create(0,max_disp,wsize);
154-
left_matcher->setMinDisparity(0);
155-
Ptr<StereoSGBM> right_matcher = StereoSGBM::create(-max_disp+1,max_disp,wsize);
156-
left_matcher->setUniquenessRatio(0);
157-
left_matcher->setDisp12MaxDiff(1000000);
158-
left_matcher->setSpeckleWindowSize(0);
159-
right_matcher->setUniquenessRatio(0);
160-
right_matcher->setDisp12MaxDiff(1000000);
161-
right_matcher->setSpeckleWindowSize(0);
162-
ROI = computeROI(left_for_matcher.size(),left_matcher);
167+
left_matcher->setP1(24*wsize*wsize);
168+
left_matcher->setP2(96*wsize*wsize);
169+
left_matcher->setPreFilterCap(63);
170+
left_matcher->setMode(StereoSGBM::MODE_SGBM_3WAY);
171+
wls_filter = createDisparityWLSFilter(left_matcher);
172+
Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
163173

164174
matching_time = (double)getTickCount();
165175
left_matcher-> compute(left_for_matcher, right_for_matcher,left_disp);
@@ -172,14 +182,17 @@ int main(int argc, char** argv)
172182
return -1;
173183
}
174184

175-
Ptr<DisparityWLSFilter> wls_filter = createDisparityWLSFilter(true);
185+
//! [filtering]
176186
wls_filter->setLambda(lambda);
177187
wls_filter->setSigmaColor(sigma);
178188
filtering_time = (double)getTickCount();
179-
wls_filter->filter(left_disp,left,filtered_disp,ROI,right_disp);
189+
wls_filter->filter(left_disp,left,filtered_disp,right_disp);
180190
filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency();
191+
//! [filtering]
181192
conf_map = wls_filter->getConfidenceMap();
182193

194+
// Get the ROI that was used in the last filter call:
195+
ROI = wls_filter->getROI();
183196
if(!no_downscale)
184197
{
185198
// upscale raw disparity and ROI back for a proper comparison:
@@ -190,6 +203,9 @@ int main(int argc, char** argv)
190203
}
191204
else if(filter=="wls_no_conf")
192205
{
206+
/* There is no convenience function for the case of filtering with no confidence, so we
207+
will need to set the ROI and matcher parameters manually */
208+
193209
left_for_matcher = left.clone();
194210
right_for_matcher = right.clone();
195211

@@ -201,6 +217,8 @@ int main(int argc, char** argv)
201217
cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
202218
cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY);
203219
ROI = computeROI(left_for_matcher.size(),matcher);
220+
wls_filter = createDisparityWLSFilterGeneric(false);
221+
wls_filter->setDepthDiscontinuityRadius((int)ceil(0.33*wsize));
204222

205223
matching_time = (double)getTickCount();
206224
matcher->compute(left_for_matcher,right_for_matcher,left_disp);
@@ -212,7 +230,12 @@ int main(int argc, char** argv)
212230
matcher->setUniquenessRatio(0);
213231
matcher->setDisp12MaxDiff(1000000);
214232
matcher->setSpeckleWindowSize(0);
233+
matcher->setP1(24*wsize*wsize);
234+
matcher->setP2(96*wsize*wsize);
235+
matcher->setMode(StereoSGBM::MODE_SGBM_3WAY);
215236
ROI = computeROI(left_for_matcher.size(),matcher);
237+
wls_filter = createDisparityWLSFilterGeneric(false);
238+
wls_filter->setDepthDiscontinuityRadius((int)ceil(0.5*wsize));
216239

217240
matching_time = (double)getTickCount();
218241
matcher->compute(left_for_matcher,right_for_matcher,left_disp);
@@ -224,11 +247,10 @@ int main(int argc, char** argv)
224247
return -1;
225248
}
226249

227-
Ptr<DisparityWLSFilter> wls_filter = createDisparityWLSFilter(false);
228250
wls_filter->setLambda(lambda);
229251
wls_filter->setSigmaColor(sigma);
230252
filtering_time = (double)getTickCount();
231-
wls_filter->filter(left_disp,left,filtered_disp,ROI);
253+
wls_filter->filter(left_disp,left,filtered_disp,Mat(),ROI);
232254
filtering_time = ((double)getTickCount() - filtering_time)/getTickFrequency();
233255
}
234256
else
@@ -292,6 +314,7 @@ int main(int argc, char** argv)
292314
imshow("ground-truth disparity", GT_disp_vis);
293315
}
294316

317+
//! [visualization]
295318
Mat raw_disp_vis;
296319
getDisparityVis(left_disp,raw_disp_vis,vis_mult);
297320
namedWindow("raw disparity", WINDOW_AUTOSIZE);
@@ -301,6 +324,7 @@ int main(int argc, char** argv)
301324
namedWindow("filtered disparity", WINDOW_AUTOSIZE);
302325
imshow("filtered disparity", filtered_disp_vis);
303326
waitKey();
327+
//! [visualization]
304328
}
305329

306330
return 0;

0 commit comments

Comments
 (0)