diff --git a/lib/libstereo/CMakeLists.txt b/lib/libstereo/CMakeLists.txt index a5fe73958e3a2910d1aea58ef813a2b3bab0623f..fba64234b8c6a726eaac775aaeb3c6ae5c17852d 100644 --- a/lib/libstereo/CMakeLists.txt +++ b/lib/libstereo/CMakeLists.txt @@ -43,6 +43,7 @@ if (LIBSTEREO_SHARED) src/algorithms/tcensussgm.cu src/algorithms/hcensussgm.cu src/algorithms/brefcensussgm.cu + src/algorithms/meancensussgm.cu #src/stereo_hier_census.cu src/stereo_wcensussgm.cu src/stereo_census_adaptive.cu @@ -75,6 +76,7 @@ else() src/algorithms/tcensussgm.cu src/algorithms/hcensussgm.cu src/algorithms/brefcensussgm.cu + src/algorithms/meancensussgm.cu #src/stereo_hier_census.cu src/stereo_wcensussgm.cu src/stereo_census_adaptive.cu diff --git a/lib/libstereo/include/stereo.hpp b/lib/libstereo/include/stereo.hpp index ea40a6386b7d8f85276718a9ffd2ce9b689bfcff..4c802da27d7e98228436bde624e1724501fe5492 100644 --- a/lib/libstereo/include/stereo.hpp +++ b/lib/libstereo/include/stereo.hpp @@ -86,7 +86,43 @@ private: }; /** - * Bilateral filtering for reference pixel. Doesn't make things better + * Mean reference pixel. Doesn't work since detail is lost form reference + * + * @see "A robust local census-based stereo matching insensitive to illumination changes" (2012) + * @see "A stereo matching algorithm based on four-moded census and relative confidence plane fitting" (2015) + * @see "Stereo matching based on improved census transform" (2018) + */ +class StereoMeanCensusSgm { +public: + StereoMeanCensusSgm(); + ~StereoMeanCensusSgm(); + + void compute(cv::InputArray l, cv::InputArray r, cv::OutputArray disparity); + void setPrior(cv::InputArray disp) {}; + + struct Parameters { + int d_min = 0; + int d_max = 0; + unsigned short P1 = 5; + unsigned short P2 = 25; + float uniqueness = std::numeric_limits<unsigned short>::max(); + int subpixel = 1; // subpixel interpolation method + bool lr_consistency = true; + int paths = AggregationDirections::HORIZONTAL | + AggregationDirections::VERTICAL | + AggregationDirections::DIAGONAL; + bool debug = false; + }; + Parameters params; + +private: + struct Impl; + Impl *impl_; +}; + +/** + * Bilateral filtering for reference pixel. Doesn't make things better, but + * still better than mean value for reference. */ class StereoBRefCensusSgm { public: diff --git a/lib/libstereo/middlebury/main.cpp b/lib/libstereo/middlebury/main.cpp index 0c627989d7088fdbbfd17f5befaeb87e2a1c048f..ec40c620eda82d7bff143da3a7fa82f2c96a9e75 100644 --- a/lib/libstereo/middlebury/main.cpp +++ b/lib/libstereo/middlebury/main.cpp @@ -27,6 +27,19 @@ static void run_censussgm(MiddleburyData &data, cv::Mat &disparity) { stereo.compute(data.imL, data.imR, disparity); } +static void run_meancensussgm(MiddleburyData &data, cv::Mat &disparity) { + auto stereo = StereoMeanCensusSgm(); + stereo.params.P1 = 12; + stereo.params.P2 = 32; + + stereo.params.d_min = data.calib.vmin; + stereo.params.d_max = data.calib.vmax; + stereo.params.subpixel = 1; + stereo.params.lr_consistency = true; + stereo.params.debug = false; + stereo.compute(data.imL, data.imR, disparity); +} + static void run_brefcensussgm(MiddleburyData &data, cv::Mat &disparity) { auto stereo = StereoBRefCensusSgm(); stereo.params.P1 = 12; @@ -193,6 +206,7 @@ static const std::map<std::string, std::function<void(MiddleburyData&, cv::Mat&) { "hcensussgm", run_hcensussgm }, { "wcensussgm", run_wcensussgm }, { "brefcensus", run_brefcensussgm }, + { "mcensussgm", run_meancensussgm }, //{ "misgm", run_misgm }, { "varcensus", run_varcensus }, { "stablesgm", run_stablesgm }, diff --git a/lib/libstereo/src/algorithms/meancensussgm.cu b/lib/libstereo/src/algorithms/meancensussgm.cu new file mode 100644 index 0000000000000000000000000000000000000000..e0c1d49d7bb4569faa9086d39a5e16deaa9cd5a5 --- /dev/null +++ b/lib/libstereo/src/algorithms/meancensussgm.cu @@ -0,0 +1,48 @@ +#include "stereo.hpp" +#include "stereosgm.hpp" +#include "../costs/census.hpp" +#include <opencv2/cudafilters.hpp> + +struct StereoMeanCensusSgm::Impl : public StereoSgm<CensusMatchingCost, StereoMeanCensusSgm::Parameters> { + Array2D<uchar> l; + Array2D<uchar> r; + Array2D<uchar> ml; + Array2D<uchar> mr; + + Impl(StereoMeanCensusSgm::Parameters ¶ms, int width, int height, int dmin, int dmax) : + StereoSgm(params, width, height, dmin, dmax), l(width, height), r(width, height), + ml(width, height), mr(width, height) {} +}; + +StereoMeanCensusSgm::StereoMeanCensusSgm() : impl_(nullptr) { + impl_ = new Impl(params, 0, 0, 0, 0); +} + +void StereoMeanCensusSgm::compute(cv::InputArray l, cv::InputArray r, cv::OutputArray disparity) { + + cudaSetDevice(0); + + if (l.rows() != impl_->cost.height() || r.cols() != impl_->cost.width()) { + delete impl_; impl_ = nullptr; + impl_ = new Impl(params, l.cols(), l.rows(), params.d_min, params.d_max); + } + + mat2gray(l, impl_->l); + mat2gray(r, impl_->r); + + auto filter = cv::cuda::createBoxFilter(CV_8UC1, CV_8UC1, cv::Size(5,5)); + filter->apply(impl_->l.toGpuMat(), impl_->ml.toGpuMat()); // E[X] + filter->apply(impl_->r.toGpuMat(), impl_->mr.toGpuMat()); // E[X] + + impl_->cost.set(impl_->ml, impl_->mr); + + cudaSafeCall(cudaDeviceSynchronize()); + impl_->compute(disparity); +} + +StereoMeanCensusSgm::~StereoMeanCensusSgm() { + if (impl_) { + delete impl_; + impl_ = nullptr; + } +}