Skip to content

Commit 3f0eaf6

Browse files
ytyytyytalalek
authored andcommitted
Merge pull request #1877 from ytyytyyt:master
* fbs disparity filtering fix * fbs fix vol II * fbs doc update * fix unused variables warnings in disparity_filtering.cpp * trailing whitespaces removed
1 parent 6389627 commit 3f0eaf6

File tree

4 files changed

+123
-76
lines changed

4 files changed

+123
-76
lines changed

modules/ximgproc/doc/ximgproc.bib

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,11 @@ @misc{M_RF
311311
url = {http://reference.wolfram.com/language/ref/RidgeFilter.html}
312312
}
313313

314-
@article{BarronPoole2016,
315-
author = {Jonathan T Barron and Ben Poole},
316-
title = {The Fast Bilateral Solver},
317-
journal = {ECCV},
318-
year = {2016},
314+
@inproceedings{BarronPoole2016,
315+
author = {Jonathan T Barron and Ben Poole},
316+
title={The Fast Bilateral Solver},
317+
booktitle={European Conference on Computer Vision (ECCV)},
318+
year={2016},
319+
publisher={Springer International Publishing},
320+
pages={617--632},
319321
}

modules/ximgproc/include/opencv2/ximgproc/edge_filter.hpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,9 @@ class CV_EXPORTS_W FastBilateralSolverFilter : public Algorithm
384384
public:
385385
/** @brief Apply smoothing operation to the source image.
386386
387-
@param src source image for filtering with unsigned 8-bit or signed 16-bit or floating-point 32-bit depth and up to 4 channels.
387+
@param src source image for filtering with unsigned 8-bit or signed 16-bit or floating-point 32-bit depth and up to 3 channels.
388388
389-
@param confidence confidence image with unsigned 8-bit or signed 16-bit or floating-point 32-bit confidence and 1 channel.
389+
@param confidence confidence image with unsigned 8-bit or floating-point 32-bit confidence and 1 channel.
390390
391391
@param dst destination image.
392392
*/
@@ -405,9 +405,10 @@ class CV_EXPORTS_W FastBilateralSolverFilter : public Algorithm
405405
406406
@param num_iter number of iterations used for solving, 25 is usually enough.
407407
408-
@param max_tol solving tolerance used for solving, 25 is usually enough.
408+
@param max_tol solving tolerance used for solving.
409409
410410
For more details about the Fast Bilateral Solver parameters, see the original paper @cite BarronPoole2016.
411+
411412
*/
412413
CV_EXPORTS_W Ptr<FastBilateralSolverFilter> createFastBilateralSolverFilter(InputArray guide, double sigma_spatial, double sigma_luma, double sigma_chroma, int num_iter = 25, double max_tol = 1e-5);
413414

@@ -419,7 +420,7 @@ guide then use FastBilateralSolverFilter interface to avoid extra computations.
419420
420421
@param src source image for filtering with unsigned 8-bit or signed 16-bit or floating-point 32-bit depth and up to 4 channels.
421422
422-
@param confidence confidence image with unsigned 8-bit or signed 16-bit or floating-point 32-bit confidence and 1 channel.
423+
@param confidence confidence image with unsigned 8-bit or floating-point 32-bit confidence and 1 channel.
423424
424425
@param dst destination image.
425426
@@ -431,7 +432,9 @@ guide then use FastBilateralSolverFilter interface to avoid extra computations.
431432
432433
@param num_iter number of iterations used for solving, 25 is usually enough.
433434
434-
@param max_tol solving tolerance used for solving, 25 is usually enough.
435+
@param max_tol solving tolerance used for solving.
436+
437+
@note Confidence images with CV_8U depth are expected to in [0, 255] and CV_32F in [0, 1] range.
435438
*/
436439
CV_EXPORTS_W void fastBilateralSolverFilter(InputArray guide, InputArray src, InputArray confidence, OutputArray dst, double sigma_spatial = 8, double sigma_luma = 8, double sigma_chroma = 8, int num_iter = 25, double max_tol = 1e-5);
437440
//////////////////////////////////////////////////////////////////////////

modules/ximgproc/samples/disparity_filtering.cpp

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@ const String keys =
2121
"{dst_path |None | optional path to save the resulting filtered disparity map }"
2222
"{dst_raw_path |None | optional path to save raw disparity map before filtering }"
2323
"{algorithm |bm | stereo matching method (bm or sgbm) }"
24-
"{filter |wls_conf | used post-filtering (wls_conf or wls_no_conf or fbs_conf) }"
24+
"{filter |wls_conf | used post-filtering (wls_conf or wls_no_conf or fbs_conf) }"
2525
"{no-display | | don't display results }"
2626
"{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 }"
3030
"{window_size |-1 | parameter of stereo matching }"
31-
"{wls_lambda |8000.0 | parameter of post-filtering }"
32-
"{wls_sigma |1.5 | parameter of post-filtering }"
31+
"{wls_lambda |8000.0 | parameter of wls post-filtering }"
32+
"{wls_sigma |1.5 | parameter of wls post-filtering }"
33+
"{fbs_spatial |16.0 | parameter of fbs post-filtering }"
34+
"{fbs_luma |8.0 | parameter of fbs post-filtering }"
35+
"{fbs_chroma |8.0 | parameter of fbs post-filtering }"
3336
;
3437

3538
int main(int argc, char** argv)
@@ -56,6 +59,9 @@ int main(int argc, char** argv)
5659
int max_disp = parser.get<int>("max_disparity");
5760
double lambda = parser.get<double>("wls_lambda");
5861
double sigma = parser.get<double>("wls_sigma");
62+
double fbs_spatial = parser.get<double>("fbs_spatial");
63+
double fbs_luma = parser.get<double>("fbs_luma");
64+
double fbs_chroma = parser.get<double>("fbs_chroma");
5965
double vis_mult = parser.get<double>("vis_mult");
6066

6167
int wsize;
@@ -107,9 +113,9 @@ int main(int argc, char** argv)
107113
}
108114
}
109115

110-
Mat left_for_matcher, right_for_matcher, guide;
116+
Mat left_for_matcher, right_for_matcher;
111117
Mat left_disp,right_disp;
112-
Mat filtered_disp,solved_disp;
118+
Mat filtered_disp,solved_disp,solved_filtered_disp;
113119
Mat conf_map = Mat(left.rows,left.cols,CV_8U);
114120
conf_map = Scalar(255);
115121
Rect ROI;
@@ -203,7 +209,7 @@ int main(int argc, char** argv)
203209
ROI = Rect(ROI.x*2,ROI.y*2,ROI.width*2,ROI.height*2);
204210
}
205211
}
206-
else if(filter=="fbs_conf") // filtering with confidence (significantly better quality than wls_no_conf)
212+
else if(filter=="fbs_conf") // filtering with fbs and confidence using also wls pre-processing
207213
{
208214
if(!no_downscale)
209215
{
@@ -222,7 +228,6 @@ int main(int argc, char** argv)
222228
left_for_matcher = left.clone();
223229
right_for_matcher = right.clone();
224230
}
225-
guide = left_for_matcher.clone();
226231

227232
if(algo=="bm")
228233
{
@@ -281,20 +286,26 @@ int main(int argc, char** argv)
281286
// upscale raw disparity and ROI back for a proper comparison:
282287
resize(left_disp,left_disp,Size(),2.0,2.0);
283288
left_disp = left_disp*2.0;
289+
left_disp_resized = left_disp_resized*2.0;
284290
ROI = Rect(ROI.x*2,ROI.y*2,ROI.width*2,ROI.height*2);
285291
}
286292

287293
#ifdef HAVE_EIGEN
288294
//! [filtering_fbs]
289295
solving_time = (double)getTickCount();
290-
// wls_filter->filter(left_disp,left,filtered_disp,right_disp);
291-
// fastBilateralSolverFilter(left, filtered_disp, conf_map, solved_disp, 16.0, 16.0, 16.0);
292-
fastBilateralSolverFilter(left, left_disp_resized, conf_map, solved_disp, 16.0, 16.0, 16.0);
296+
fastBilateralSolverFilter(left, left_disp_resized, conf_map/255.0f, solved_disp, fbs_spatial, fbs_luma, fbs_chroma);
293297
solving_time = ((double)getTickCount() - solving_time)/getTickFrequency();
294-
solved_disp.convertTo(solved_disp, CV_8UC1);
295-
cv::equalizeHist(solved_disp, solved_disp);
296298
//! [filtering_fbs]
299+
300+
//! [filtering_wls2fbs]
301+
fastBilateralSolverFilter(left, filtered_disp, conf_map/255.0f, solved_filtered_disp, fbs_spatial, fbs_luma, fbs_chroma);
302+
//! [filtering_wls2fbs]
303+
#else
304+
(void)fbs_spatial;
305+
(void)fbs_luma;
306+
(void)fbs_chroma;
297307
#endif
308+
298309
}
299310
else if(filter=="wls_no_conf")
300311
{
@@ -358,7 +369,7 @@ int main(int argc, char** argv)
358369
cout.precision(2);
359370
cout<<"Matching time: "<<matching_time<<"s"<<endl;
360371
cout<<"Filtering time: "<<filtering_time<<"s"<<endl;
361-
cout<<"solving time: "<<solving_time<<"s"<<endl;
372+
cout<<"Solving time: "<<solving_time<<"s"<<endl;
362373
cout<<endl;
363374

364375
double MSE_before,percent_bad_before,MSE_after,percent_bad_after;
@@ -422,31 +433,23 @@ int main(int argc, char** argv)
422433

423434
if(!solved_disp.empty())
424435
{
436+
Mat solved_disp_vis;
437+
getDisparityVis(solved_disp,solved_disp_vis,vis_mult);
425438
namedWindow("solved disparity", WINDOW_AUTOSIZE);
426-
imshow("solved disparity", solved_disp);
427-
428-
#define ENABLE_DOMAIN_TRANSFORM_FILTER
429-
#ifdef ENABLE_DOMAIN_TRANSFORM_FILTER
430-
const float property_dt_sigmaSpatial = 40.0f;
431-
const float property_dt_sigmaColor = 220.0f;
432-
const int property_dt_numIters = 3;
433-
cv::Mat final_disparty_dtfiltered_image;
434-
cv::ximgproc::dtFilter(left,
435-
solved_disp, final_disparty_dtfiltered_image,
436-
property_dt_sigmaSpatial, property_dt_sigmaColor,
437-
cv::ximgproc::DTF_RF,
438-
property_dt_numIters);
439-
440-
// display disparity image
441-
cv::Mat adjmap_dt;
442-
final_disparty_dtfiltered_image.convertTo(adjmap_dt, CV_8UC1);
443-
// 255.0f / 255.0f, 0.0f);
444-
cv::imshow("disparity image + domain transform", adjmap_dt);
445-
#endif
439+
imshow("solved disparity", solved_disp_vis);
446440

441+
Mat solved_filtered_disp_vis;
442+
getDisparityVis(solved_filtered_disp,solved_filtered_disp_vis,vis_mult);
443+
namedWindow("solved wls disparity", WINDOW_AUTOSIZE);
444+
imshow("solved wls disparity", solved_filtered_disp_vis);
447445
}
448446

449-
waitKey();
447+
while(1)
448+
{
449+
char key = (char)waitKey();
450+
if( key == 27 || key == 'q' || key == 'Q') // 'ESC'
451+
break;
452+
}
450453
//! [visualization]
451454
}
452455

modules/ximgproc/src/fbs_filter.cpp

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
typedef std::unordered_map<long long /* hash */, int /* vert id */> mapId;
6767
#endif
6868

69+
#define EPS 1e-43f
70+
6971
namespace cv
7072
{
7173
namespace ximgproc
@@ -88,7 +90,7 @@ namespace ximgproc
8890
{
8991

9092
CV_Assert(!src.empty() && (src.depth() == CV_8U || src.depth() == CV_16S || src.depth() == CV_32F) && src.channels()<=4);
91-
CV_Assert(!confidence.empty() && (confidence.depth() == CV_8U || confidence.depth() == CV_16S || confidence.depth() == CV_32F) && confidence.channels()==1);
93+
CV_Assert(!confidence.empty() && (confidence.depth() == CV_8U || confidence.depth() == CV_32F) && confidence.channels()==1);
9294
if (src.rows() != rows || src.cols() != cols)
9395
{
9496
CV_Error(Error::StsBadSize, "Size of the filtered image must be equal to the size of the guide image");
@@ -108,14 +110,10 @@ namespace ximgproc
108110
split(src,src_channels);
109111

110112
Mat conf = confidence.getMat();
111-
if(conf.depth() != CV_8UC1)
112-
conf.convertTo(conf, CV_8UC1);
113113

114114
for(int i=0;i<src.channels();i++)
115115
{
116116
Mat cur_res = src_channels[i].clone();
117-
if(src.depth() != CV_8UC1)
118-
cur_res.convertTo(cur_res, CV_8UC1);
119117

120118
solve(cur_res,conf,cur_res);
121119
cur_res.convertTo(cur_res, src.type());
@@ -167,7 +165,6 @@ namespace ximgproc
167165
Eigen::SparseMatrix<float, Eigen::ColMajor> S;
168166
Eigen::SparseMatrix<float, Eigen::ColMajor> Dn;
169167
Eigen::SparseMatrix<float, Eigen::ColMajor> Dm;
170-
cv::Mat guide;
171168

172169
struct grid_params
173170
{
@@ -206,7 +203,6 @@ namespace ximgproc
206203

207204
void FastBilateralSolverFilterImpl::init(cv::Mat& reference, double sigma_spatial, double sigma_luma, double sigma_chroma, int num_iter, double max_tol)
208205
{
209-
guide = reference.clone();
210206

211207
bs_param.cg_maxiter = num_iter;
212208
bs_param.cg_tol = max_tol;
@@ -479,45 +475,69 @@ namespace ximgproc
479475
Eigen::VectorXf y1(nvertices);
480476
Eigen::VectorXf w_splat(nvertices);
481477

482-
cv::Mat x;
483-
cv::Mat w;
484-
cv::Mat xw;
485-
cv::Mat filtered_xw;
486-
cv::Mat filtered_w;
487-
cv::Mat filtered_disp;
488-
float fgs_colorSigma = 1.5;
489-
float fgs_spatialSigma = 2000;
490-
target.convertTo(x, CV_32FC1, 1.0f/255.0f);
491-
confidence.convertTo(w, CV_32FC1);
492-
xw = x.mul(w);
493-
cv::ximgproc::fastGlobalSmootherFilter(guide, xw, filtered_xw, fgs_spatialSigma, fgs_colorSigma);
494-
cv::ximgproc::fastGlobalSmootherFilter(guide, w, filtered_w, fgs_spatialSigma, fgs_colorSigma);
495-
cv::divide(filtered_xw, filtered_w, filtered_disp, 1.0f, CV_32FC1);
478+
Eigen::VectorXf x(npixels);
479+
Eigen::VectorXf w(npixels);
496480

481+
if(target.depth() == CV_16S)
482+
{
483+
const int16_t *pft = reinterpret_cast<const int16_t*>(target.data);
484+
for (int i = 0; i < npixels; i++)
485+
{
486+
x(i) = (cv::saturate_cast<float>(pft[i])+32768.0f)/65535.0f;
487+
}
488+
}
489+
else if(target.depth() == CV_8U)
490+
{
491+
const uchar *pft = reinterpret_cast<const uchar*>(target.data);
492+
for (int i = 0; i < npixels; i++)
493+
{
494+
x(i) = cv::saturate_cast<float>(pft[i])/255.0f;
495+
}
496+
}
497+
else if(confidence.depth() == CV_32F)
498+
{
499+
const float *pft = reinterpret_cast<const float*>(target.data);
500+
for (int i = 0; i < npixels; i++)
501+
{
502+
x(i) = pft[i];
503+
}
504+
}
497505

498-
//construct A
499-
w_splat.setZero();
500-
const float *pfw = reinterpret_cast<const float*>(w.data);
501-
for (int i = 0; i < int(splat_idx.size()); i++)
506+
if(confidence.depth() == CV_8U)
502507
{
503-
w_splat(splat_idx[i]) += pfw[i]/255.0f;
508+
const uchar *pfc = reinterpret_cast<const uchar*>(confidence.data);
509+
for (int i = 0; i < npixels; i++)
510+
{
511+
w(i) = cv::saturate_cast<float>(pfc[i])/255.0f;
512+
}
504513
}
514+
else if(confidence.depth() == CV_32F)
515+
{
516+
const float *pfc = reinterpret_cast<const float*>(confidence.data);
517+
for (int i = 0; i < npixels; i++)
518+
{
519+
w(i) = pfc[i];
520+
}
521+
}
522+
523+
//construct A
524+
Splat(w,w_splat);
525+
505526
diagonal(w_splat,A_data);
506527
A = bs_param.lam * (Dm - Dn * (blurs*Dn)) + A_data ;
507528

508529
//construct b
509530
b.setZero();
510-
const float *pfx = reinterpret_cast<const float*>(filtered_disp.data);
511531
for (int i = 0; i < int(splat_idx.size()); i++)
512532
{
513-
b(splat_idx[i]) += pfx[i]*pfw[i]/255.0f;
533+
b(splat_idx[i]) += x(i) * w(i);
514534
}
515535

516536
//construct guess for y
517537
y0.setZero();
518538
for (int i = 0; i < int(splat_idx.size()); i++)
519539
{
520-
y0(splat_idx[i]) += pfx[i];
540+
y0(splat_idx[i]) += x(i);
521541
}
522542
y1.setZero();
523543
for (int i = 0; i < int(splat_idx.size()); i++)
@@ -541,10 +561,29 @@ namespace ximgproc
541561
std::cout << "estimated error: " << cg.error() << std::endl;
542562

543563
//slice
544-
uchar *pftar = (uchar*)(output.data);
545-
for (int i = 0; i < int(splat_idx.size()); i++)
564+
if(target.depth() == CV_16S)
565+
{
566+
int16_t *pftar = (int16_t*) output.data;
567+
for (int i = 0; i < int(splat_idx.size()); i++)
568+
{
569+
pftar[i] = cv::saturate_cast<ushort>(y(splat_idx[i]) * 65535.0f - 32768.0f);
570+
}
571+
}
572+
else if (target.depth() == CV_8U)
546573
{
547-
pftar[i] = uchar(y(splat_idx[i]) * 255.0f);
574+
uchar *pftar = (uchar*) output.data;
575+
for (int i = 0; i < int(splat_idx.size()); i++)
576+
{
577+
pftar[i] = cv::saturate_cast<uchar>(y(splat_idx[i]) * 255.0f);
578+
}
579+
}
580+
else
581+
{
582+
float *pftar = (float*)(output.data);
583+
for (int i = 0; i < int(splat_idx.size()); i++)
584+
{
585+
pftar[i] = y(splat_idx[i]);
586+
}
548587
}
549588

550589

0 commit comments

Comments
 (0)