Commit 3a02e599 authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

refactored DisparityBilateralFilter

parent be9bb8f1
...@@ -134,44 +134,48 @@ public: ...@@ -134,44 +134,48 @@ public:
CV_EXPORTS Ptr<gpu::StereoConstantSpaceBP> CV_EXPORTS Ptr<gpu::StereoConstantSpaceBP>
createStereoConstantSpaceBP(int ndisp = 128, int iters = 8, int levels = 4, int nr_plane = 4, int msg_type = CV_32F); createStereoConstantSpaceBP(int ndisp = 128, int iters = 8, int levels = 4, int nr_plane = 4, int msg_type = CV_32F);
/////////////////////////////////////////
// DisparityBilateralFilter
//! Disparity map refinement using joint bilateral filtering given a single color image.
//! Qingxiong Yang, Liang Wang, Narendra Ahuja
// Disparity map refinement using joint bilateral filtering given a single color image. //! http://vision.ai.uiuc.edu/~qyang6/
// Qingxiong Yang, Liang Wang, Narendra Ahuja class CV_EXPORTS DisparityBilateralFilter : public cv::Algorithm
// http://vision.ai.uiuc.edu/~qyang6/
class CV_EXPORTS DisparityBilateralFilter
{ {
public: public:
enum { DEFAULT_NDISP = 64 }; //! the disparity map refinement operator. Refine disparity map using joint bilateral filtering given a single color image.
enum { DEFAULT_RADIUS = 3 }; //! disparity must have CV_8U or CV_16S type, image must have CV_8UC1 or CV_8UC3 type.
enum { DEFAULT_ITERS = 1 }; virtual void apply(InputArray disparity, InputArray image, OutputArray dst, Stream& stream = Stream::Null()) = 0;
//! the default constructor virtual int getNumDisparities() const = 0;
explicit DisparityBilateralFilter(int ndisp = DEFAULT_NDISP, int radius = DEFAULT_RADIUS, int iters = DEFAULT_ITERS); virtual void setNumDisparities(int numDisparities) = 0;
//! the full constructor taking the number of disparities, filter radius, virtual int getRadius() const = 0;
//! number of iterations, truncation of data continuity, truncation of disparity continuity virtual void setRadius(int radius) = 0;
//! and filter range sigma
DisparityBilateralFilter(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold, float sigma_range);
//! the disparity map refinement operator. Refine disparity map using joint bilateral filtering given a single color image. virtual int getNumIters() const = 0;
//! disparity must have CV_8U or CV_16S type, image must have CV_8UC1 or CV_8UC3 type. virtual void setNumIters(int iters) = 0;
void operator()(const GpuMat& disparity, const GpuMat& image, GpuMat& dst, Stream& stream = Stream::Null());
private: //! truncation of data continuity
int ndisp; virtual double getEdgeThreshold() const = 0;
int radius; virtual void setEdgeThreshold(double edge_threshold) = 0;
int iters;
float edge_threshold; //! truncation of disparity continuity
float max_disc_threshold; virtual double getMaxDiscThreshold() const = 0;
float sigma_range; virtual void setMaxDiscThreshold(double max_disc_threshold) = 0;
GpuMat table_color; //! filter range sigma
GpuMat table_space; virtual double getSigmaRange() const = 0;
virtual void setSigmaRange(double sigma_range) = 0;
}; };
CV_EXPORTS Ptr<gpu::DisparityBilateralFilter>
createDisparityBilateralFilter(int ndisp = 64, int radius = 3, int iters = 1);
//! Reprojects disparity image to 3D space. //! Reprojects disparity image to 3D space.
//! Supports CV_8U and CV_16S types of input disparity. //! Supports CV_8U and CV_16S types of input disparity.
//! The output is a 3- or 4-channel floating-point matrix. //! The output is a 3- or 4-channel floating-point matrix.
......
...@@ -173,13 +173,13 @@ PERF_TEST_P(ImagePair, DisparityBilateralFilter, ...@@ -173,13 +173,13 @@ PERF_TEST_P(ImagePair, DisparityBilateralFilter,
if (PERF_RUN_GPU()) if (PERF_RUN_GPU())
{ {
cv::gpu::DisparityBilateralFilter d_filter(ndisp); cv::Ptr<cv::gpu::DisparityBilateralFilter> d_filter = cv::gpu::createDisparityBilateralFilter(ndisp);
const cv::gpu::GpuMat d_img(img); const cv::gpu::GpuMat d_img(img);
const cv::gpu::GpuMat d_disp(disp); const cv::gpu::GpuMat d_disp(disp);
cv::gpu::GpuMat dst; cv::gpu::GpuMat dst;
TEST_CYCLE() d_filter(d_disp, d_img, dst); TEST_CYCLE() d_filter->apply(d_disp, d_img, dst);
GPU_SANITY_CHECK(dst); GPU_SANITY_CHECK(dst);
} }
......
...@@ -47,10 +47,7 @@ using namespace cv::gpu; ...@@ -47,10 +47,7 @@ using namespace cv::gpu;
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int, int, int) { throw_no_cuda(); } Ptr<gpu::DisparityBilateralFilter> cv::gpu::createDisparityBilateralFilter(int, int, int) { throw_no_cuda(); return Ptr<gpu::DisparityBilateralFilter>(); }
cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int, int, int, float, float, float) { throw_no_cuda(); }
void cv::gpu::DisparityBilateralFilter::operator()(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); }
#else /* !defined (HAVE_CUDA) */ #else /* !defined (HAVE_CUDA) */
...@@ -65,15 +62,46 @@ namespace cv { namespace gpu { namespace cudev ...@@ -65,15 +62,46 @@ namespace cv { namespace gpu { namespace cudev
} }
}}} }}}
using namespace ::cv::gpu::cudev::disp_bilateral_filter;
namespace namespace
{ {
const float DEFAULT_EDGE_THRESHOLD = 0.1f; class DispBilateralFilterImpl : public gpu::DisparityBilateralFilter
const float DEFAULT_MAX_DISC_THRESHOLD = 0.2f; {
const float DEFAULT_SIGMA_RANGE = 10.0f; public:
DispBilateralFilterImpl(int ndisp, int radius, int iters);
void apply(InputArray disparity, InputArray image, OutputArray dst, Stream& stream);
int getNumDisparities() const { return ndisp_; }
void setNumDisparities(int numDisparities) { ndisp_ = numDisparities; }
int getRadius() const { return radius_; }
void setRadius(int radius);
int getNumIters() const { return iters_; }
void setNumIters(int iters) { iters_ = iters; }
inline void calc_color_weighted_table(GpuMat& table_color, float sigma_range, int len) double getEdgeThreshold() const { return edge_threshold_; }
void setEdgeThreshold(double edge_threshold) { edge_threshold_ = (float) edge_threshold; }
double getMaxDiscThreshold() const { return max_disc_threshold_; }
void setMaxDiscThreshold(double max_disc_threshold) { max_disc_threshold_ = (float) max_disc_threshold; }
double getSigmaRange() const { return sigma_range_; }
void setSigmaRange(double sigma_range);
private:
int ndisp_;
int radius_;
int iters_;
float edge_threshold_;
float max_disc_threshold_;
float sigma_range_;
GpuMat table_color_;
GpuMat table_space_;
};
void calc_color_weighted_table(GpuMat& table_color, float sigma_range, int len)
{ {
Mat cpu_table_color(1, len, CV_32F); Mat cpu_table_color(1, len, CV_32F);
...@@ -85,7 +113,7 @@ namespace ...@@ -85,7 +113,7 @@ namespace
table_color.upload(cpu_table_color); table_color.upload(cpu_table_color);
} }
inline void calc_space_weighted_filter(GpuMat& table_space, int win_size, float dist_space) void calc_space_weighted_filter(GpuMat& table_space, int win_size, float dist_space)
{ {
int half = (win_size >> 1); int half = (win_size >> 1);
...@@ -101,54 +129,78 @@ namespace ...@@ -101,54 +129,78 @@ namespace
table_space.upload(cpu_table_space); table_space.upload(cpu_table_space);
} }
const float DEFAULT_EDGE_THRESHOLD = 0.1f;
const float DEFAULT_MAX_DISC_THRESHOLD = 0.2f;
const float DEFAULT_SIGMA_RANGE = 10.0f;
DispBilateralFilterImpl::DispBilateralFilterImpl(int ndisp, int radius, int iters) :
ndisp_(ndisp), radius_(radius), iters_(iters),
edge_threshold_(DEFAULT_EDGE_THRESHOLD), max_disc_threshold_(DEFAULT_MAX_DISC_THRESHOLD),
sigma_range_(DEFAULT_SIGMA_RANGE)
{
calc_color_weighted_table(table_color_, sigma_range_, 255);
calc_space_weighted_filter(table_space_, radius_ * 2 + 1, radius_ + 1.0f);
}
void DispBilateralFilterImpl::setRadius(int radius)
{
radius_ = radius;
calc_space_weighted_filter(table_space_, radius_ * 2 + 1, radius_ + 1.0f);
}
void DispBilateralFilterImpl::setSigmaRange(double sigma_range)
{
sigma_range_ = (float) sigma_range;
calc_color_weighted_table(table_color_, sigma_range_, 255);
}
template <typename T> template <typename T>
void disp_bilateral_filter_operator(int ndisp, int radius, int iters, float edge_threshold,float max_disc_threshold, void disp_bilateral_filter_operator(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold,
GpuMat& table_color, GpuMat& table_space, GpuMat& table_color, GpuMat& table_space,
const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream) const GpuMat& disp, const GpuMat& img,
OutputArray _dst, Stream& stream)
{ {
short edge_disc = std::max<short>(short(1), short(ndisp * edge_threshold + 0.5)); using namespace cv::gpu::cudev::disp_bilateral_filter;
short max_disc = short(ndisp * max_disc_threshold + 0.5);
const short edge_disc = std::max<short>(short(1), short(ndisp * edge_threshold + 0.5));
const short max_disc = short(ndisp * max_disc_threshold + 0.5);
disp_load_constants(table_color.ptr<float>(), table_space, ndisp, radius, edge_disc, max_disc); disp_load_constants(table_color.ptr<float>(), table_space, ndisp, radius, edge_disc, max_disc);
if (&dst != &disp) _dst.create(disp.size(), disp.type());
{ GpuMat dst = _dst.getGpuMat();
if (dst.data != disp.data)
disp.copyTo(dst, stream); disp.copyTo(dst, stream);
}
disp_bilateral_filter<T>(dst, img, img.channels(), iters, StreamAccessor::getStream(stream)); disp_bilateral_filter<T>(dst, img, img.channels(), iters, StreamAccessor::getStream(stream));
} }
typedef void (*bilateral_filter_operator_t)(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold, void DispBilateralFilterImpl::apply(InputArray _disp, InputArray _image, OutputArray dst, Stream& stream)
GpuMat& table_color, GpuMat& table_space, {
const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream); typedef void (*bilateral_filter_operator_t)(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold,
GpuMat& table_color, GpuMat& table_space,
const GpuMat& disp, const GpuMat& img, OutputArray dst, Stream& stream);
const bilateral_filter_operator_t operators[] =
{disp_bilateral_filter_operator<unsigned char>, 0, 0, disp_bilateral_filter_operator<short>, 0, 0, 0, 0};
const bilateral_filter_operator_t operators[] = CV_Assert( 0 < ndisp_ && 0 < radius_ && 0 < iters_ );
{disp_bilateral_filter_operator<unsigned char>, 0, 0, disp_bilateral_filter_operator<short>, 0, 0, 0, 0};
}
cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int ndisp_, int radius_, int iters_) GpuMat disp = _disp.getGpuMat();
: ndisp(ndisp_), radius(radius_), iters(iters_), edge_threshold(DEFAULT_EDGE_THRESHOLD), max_disc_threshold(DEFAULT_MAX_DISC_THRESHOLD), GpuMat img = _image.getGpuMat();
sigma_range(DEFAULT_SIGMA_RANGE)
{
calc_color_weighted_table(table_color, sigma_range, 255);
calc_space_weighted_filter(table_space, radius * 2 + 1, radius + 1.0f);
}
cv::gpu::DisparityBilateralFilter::DisparityBilateralFilter(int ndisp_, int radius_, int iters_, float edge_threshold_, CV_Assert( disp.type() == CV_8U || disp.type() == CV_16S );
float max_disc_threshold_, float sigma_range_) CV_Assert( img.type() == CV_8UC1 || img.type() == CV_8UC3 );
: ndisp(ndisp_), radius(radius_), iters(iters_), edge_threshold(edge_threshold_), max_disc_threshold(max_disc_threshold_), CV_Assert( disp.size() == img.size() );
sigma_range(sigma_range_)
{ operators[disp.type()](ndisp_, radius_, iters_, edge_threshold_, max_disc_threshold_,
calc_color_weighted_table(table_color, sigma_range, 255); table_color_, table_space_, disp, img, dst, stream);
calc_space_weighted_filter(table_space, radius * 2 + 1, radius + 1.0f); }
} }
void cv::gpu::DisparityBilateralFilter::operator()(const GpuMat& disp, const GpuMat& img, GpuMat& dst, Stream& stream) Ptr<gpu::DisparityBilateralFilter> cv::gpu::createDisparityBilateralFilter(int ndisp, int radius, int iters)
{ {
CV_DbgAssert(0 < ndisp && 0 < radius && 0 < iters); return new DispBilateralFilterImpl(ndisp, radius, iters);
CV_Assert(disp.rows == img.rows && disp.cols == img.cols && (disp.type() == CV_8U || disp.type() == CV_16S) && (img.type() == CV_8UC1 || img.type() == CV_8UC3));
operators[disp.type()](ndisp, radius, iters, edge_threshold, max_disc_threshold, table_color, table_space, disp, img, dst, stream);
} }
#endif /* !defined (HAVE_CUDA) */ #endif /* !defined (HAVE_CUDA) */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment