Commit be9bb8f1 authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

refactored StereoConstantSpaceBP

parent d0e89337
...@@ -112,63 +112,30 @@ public: ...@@ -112,63 +112,30 @@ public:
CV_EXPORTS Ptr<gpu::StereoBeliefPropagation> CV_EXPORTS Ptr<gpu::StereoBeliefPropagation>
createStereoBeliefPropagation(int ndisp = 64, int iters = 5, int levels = 5, int msg_type = CV_32F); createStereoBeliefPropagation(int ndisp = 64, int iters = 5, int levels = 5, int msg_type = CV_32F);
/////////////////////////////////////////
// StereoConstantSpaceBP
//! "A Constant-Space Belief Propagation Algorithm for Stereo Matching"
// "A Constant-Space Belief Propagation Algorithm for Stereo Matching" //! Qingxiong Yang, Liang Wang, Narendra Ahuja
// Qingxiong Yang, Liang Wang, Narendra Ahuja //! http://vision.ai.uiuc.edu/~qyang6/
// http://vision.ai.uiuc.edu/~qyang6/ class CV_EXPORTS StereoConstantSpaceBP : public gpu::StereoBeliefPropagation
class CV_EXPORTS StereoConstantSpaceBP
{ {
public: public:
enum { DEFAULT_NDISP = 128 }; //! number of active disparity on the first level
enum { DEFAULT_ITERS = 8 }; virtual int getNrPlane() const = 0;
enum { DEFAULT_LEVELS = 4 }; virtual void setNrPlane(int nr_plane) = 0;
enum { DEFAULT_NR_PLANE = 4 };
static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane);
//! the default constructor
explicit StereoConstantSpaceBP(int ndisp = DEFAULT_NDISP,
int iters = DEFAULT_ITERS,
int levels = DEFAULT_LEVELS,
int nr_plane = DEFAULT_NR_PLANE,
int msg_type = CV_32F);
//! the full constructor taking the number of disparities, number of BP iterations on each level,
//! number of levels, number of active disparity on the first level, truncation of data cost, data weight,
//! truncation of discontinuity cost, discontinuity single jump and minimum disparity threshold
StereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane,
float max_data_term, float data_weight, float max_disc_term, float disc_single_jump,
int min_disp_th = 0,
int msg_type = CV_32F);
//! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair,
//! if disparity is empty output type will be CV_16S else output type will be disparity.type().
void operator()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null());
int ndisp; virtual bool getUseLocalInitDataCost() const = 0;
virtual void setUseLocalInitDataCost(bool use_local_init_data_cost) = 0;
int iters;
int levels;
int nr_plane;
float max_data_term; static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane);
float data_weight; };
float max_disc_term;
float disc_single_jump;
int min_disp_th; CV_EXPORTS Ptr<gpu::StereoConstantSpaceBP>
createStereoConstantSpaceBP(int ndisp = 128, int iters = 8, int levels = 4, int nr_plane = 4, int msg_type = CV_32F);
int msg_type;
bool use_local_init_data_cost;
private:
GpuMat messages_buffers;
GpuMat temp;
GpuMat out;
};
// Disparity map refinement using joint bilateral filtering given a single color image. // Disparity map refinement using joint bilateral filtering given a single color image.
// Qingxiong Yang, Liang Wang, Narendra Ahuja // Qingxiong Yang, Liang Wang, Narendra Ahuja
......
...@@ -141,13 +141,13 @@ PERF_TEST_P(ImagePair, StereoConstantSpaceBP, ...@@ -141,13 +141,13 @@ PERF_TEST_P(ImagePair, StereoConstantSpaceBP,
if (PERF_RUN_GPU()) if (PERF_RUN_GPU())
{ {
cv::gpu::StereoConstantSpaceBP d_csbp(ndisp); cv::Ptr<cv::gpu::StereoConstantSpaceBP> d_csbp = cv::gpu::createStereoConstantSpaceBP(ndisp);
const cv::gpu::GpuMat d_imgLeft(imgLeft); const cv::gpu::GpuMat d_imgLeft(imgLeft);
const cv::gpu::GpuMat d_imgRight(imgRight); const cv::gpu::GpuMat d_imgRight(imgRight);
cv::gpu::GpuMat dst; cv::gpu::GpuMat dst;
TEST_CYCLE() d_csbp(d_imgLeft, d_imgRight, dst); TEST_CYCLE() d_csbp->compute(d_imgLeft, d_imgRight, dst);
GPU_SANITY_CHECK(dst); GPU_SANITY_CHECK(dst);
} }
......
...@@ -48,5 +48,6 @@ ...@@ -48,5 +48,6 @@
#include "opencv2/gpustereo.hpp" #include "opencv2/gpustereo.hpp"
#include "opencv2/core/private.gpu.hpp" #include "opencv2/core/private.gpu.hpp"
#include "opencv2/core/utility.hpp"
#endif /* __OPENCV_PRECOMP_H__ */ #endif /* __OPENCV_PRECOMP_H__ */
...@@ -49,13 +49,9 @@ using namespace cv::gpu; ...@@ -49,13 +49,9 @@ using namespace cv::gpu;
void cv::gpu::StereoConstantSpaceBP::estimateRecommendedParams(int, int, int&, int&, int&, int&) { throw_no_cuda(); } void cv::gpu::StereoConstantSpaceBP::estimateRecommendedParams(int, int, int&, int&, int&, int&) { throw_no_cuda(); }
cv::gpu::StereoConstantSpaceBP::StereoConstantSpaceBP(int, int, int, int, int) { throw_no_cuda(); } Ptr<gpu::StereoConstantSpaceBP> cv::gpu::createStereoConstantSpaceBP(int, int, int, int, int) { throw_no_cuda(); return Ptr<gpu::StereoConstantSpaceBP>(); }
cv::gpu::StereoConstantSpaceBP::StereoConstantSpaceBP(int, int, int, int, float, float, float, float, int, int) { throw_no_cuda(); }
void cv::gpu::StereoConstantSpaceBP::operator()(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); }
#else /* !defined (HAVE_CUDA) */ #else /* !defined (HAVE_CUDA) */
#include "opencv2/core/utility.hpp"
namespace cv { namespace gpu { namespace cudev namespace cv { namespace gpu { namespace cudev
{ {
...@@ -89,199 +85,303 @@ namespace cv { namespace gpu { namespace cudev ...@@ -89,199 +85,303 @@ namespace cv { namespace gpu { namespace cudev
} }
}}} }}}
using namespace ::cv::gpu::cudev::stereocsbp;
namespace namespace
{ {
const float DEFAULT_MAX_DATA_TERM = 30.0f; class StereoCSBPImpl : public gpu::StereoConstantSpaceBP
const float DEFAULT_DATA_WEIGHT = 1.0f; {
const float DEFAULT_MAX_DISC_TERM = 160.0f; public:
const float DEFAULT_DISC_SINGLE_JUMP = 10.0f; StereoCSBPImpl(int ndisp, int iters, int levels, int nr_plane, int msg_type);
}
void cv::gpu::StereoConstantSpaceBP::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane) void compute(InputArray left, InputArray right, OutputArray disparity);
{ void compute(InputArray left, InputArray right, OutputArray disparity, Stream& stream);
ndisp = (int) ((float) width / 3.14f); void compute(InputArray data, OutputArray disparity, Stream& stream);
if ((ndisp & 1) != 0)
ndisp++;
int mm = std::max(width, height); int getMinDisparity() const { return min_disp_th_; }
iters = mm / 100 + ((mm > 1200)? - 4 : 4); void setMinDisparity(int minDisparity) { min_disp_th_ = minDisparity; }
levels = (int)::log(static_cast<double>(mm)) * 2 / 3; int getNumDisparities() const { return ndisp_; }
if (levels == 0) levels++; void setNumDisparities(int numDisparities) { ndisp_ = numDisparities; }
nr_plane = (int) ((float) ndisp / std::pow(2.0, levels + 1)); int getBlockSize() const { return 0; }
} void setBlockSize(int /*blockSize*/) {}
cv::gpu::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp_, int iters_, int levels_, int nr_plane_, int getSpeckleWindowSize() const { return 0; }
int msg_type_) void setSpeckleWindowSize(int /*speckleWindowSize*/) {}
: ndisp(ndisp_), iters(iters_), levels(levels_), nr_plane(nr_plane_), int getSpeckleRange() const { return 0; }
max_data_term(DEFAULT_MAX_DATA_TERM), data_weight(DEFAULT_DATA_WEIGHT), void setSpeckleRange(int /*speckleRange*/) {}
max_disc_term(DEFAULT_MAX_DISC_TERM), disc_single_jump(DEFAULT_DISC_SINGLE_JUMP), min_disp_th(0),
msg_type(msg_type_), use_local_init_data_cost(true)
{
CV_Assert(msg_type_ == CV_32F || msg_type_ == CV_16S);
}
cv::gpu::StereoConstantSpaceBP::StereoConstantSpaceBP(int ndisp_, int iters_, int levels_, int nr_plane_, int getDisp12MaxDiff() const { return 0; }
float max_data_term_, float data_weight_, float max_disc_term_, float disc_single_jump_, void setDisp12MaxDiff(int /*disp12MaxDiff*/) {}
int min_disp_th_, int msg_type_)
: ndisp(ndisp_), iters(iters_), levels(levels_), nr_plane(nr_plane_),
max_data_term(max_data_term_), data_weight(data_weight_),
max_disc_term(max_disc_term_), disc_single_jump(disc_single_jump_), min_disp_th(min_disp_th_),
msg_type(msg_type_), use_local_init_data_cost(true)
{
CV_Assert(msg_type_ == CV_32F || msg_type_ == CV_16S);
}
template<class T> int getNumIters() const { return iters_; }
static void csbp_operator(StereoConstantSpaceBP& rthis, GpuMat& mbuf, GpuMat& temp, GpuMat& out, const GpuMat& left, const GpuMat& right, GpuMat& disp, Stream& stream) void setNumIters(int iters) { iters_ = iters; }
{
CV_DbgAssert(0 < rthis.ndisp && 0 < rthis.iters && 0 < rthis.levels && 0 < rthis.nr_plane int getNumLevels() const { return levels_; }
&& left.rows == right.rows && left.cols == right.cols && left.type() == right.type()); void setNumLevels(int levels) { levels_ = levels; }
double getMaxDataTerm() const { return max_data_term_; }
void setMaxDataTerm(double max_data_term) { max_data_term_ = (float) max_data_term; }
double getDataWeight() const { return data_weight_; }
void setDataWeight(double data_weight) { data_weight_ = (float) data_weight; }
double getMaxDiscTerm() const { return max_disc_term_; }
void setMaxDiscTerm(double max_disc_term) { max_disc_term_ = (float) max_disc_term; }
CV_Assert(rthis.levels <= 8 && (left.type() == CV_8UC1 || left.type() == CV_8UC3 || left.type() == CV_8UC4)); double getDiscSingleJump() const { return disc_single_jump_; }
void setDiscSingleJump(double disc_single_jump) { disc_single_jump_ = (float) disc_single_jump; }
const Scalar zero = Scalar::all(0); int getMsgType() const { return msg_type_; }
void setMsgType(int msg_type) { msg_type_ = msg_type; }
cudaStream_t cudaStream = StreamAccessor::getStream(stream); int getNrPlane() const { return nr_plane_; }
void setNrPlane(int nr_plane) { nr_plane_ = nr_plane; }
//////////////////////////////////////////////////////////////////////////////////////////// bool getUseLocalInitDataCost() const { return use_local_init_data_cost_; }
// Init void setUseLocalInitDataCost(bool use_local_init_data_cost) { use_local_init_data_cost_ = use_local_init_data_cost; }
int rows = left.rows; private:
int cols = left.cols; int min_disp_th_;
int ndisp_;
int iters_;
int levels_;
float max_data_term_;
float data_weight_;
float max_disc_term_;
float disc_single_jump_;
int msg_type_;
int nr_plane_;
bool use_local_init_data_cost_;
rthis.levels = std::min(rthis.levels, int(log((double)rthis.ndisp) / log(2.0))); GpuMat mbuf_;
int levels = rthis.levels; GpuMat temp_;
GpuMat outBuf_;
};
// compute sizes const float DEFAULT_MAX_DATA_TERM = 30.0f;
AutoBuffer<int> buf(levels * 3); const float DEFAULT_DATA_WEIGHT = 1.0f;
int* cols_pyr = buf; const float DEFAULT_MAX_DISC_TERM = 160.0f;
int* rows_pyr = cols_pyr + levels; const float DEFAULT_DISC_SINGLE_JUMP = 10.0f;
int* nr_plane_pyr = rows_pyr + levels;
cols_pyr[0] = cols; StereoCSBPImpl::StereoCSBPImpl(int ndisp, int iters, int levels, int nr_plane, int msg_type) :
rows_pyr[0] = rows; min_disp_th_(0), ndisp_(ndisp), iters_(iters), levels_(levels),
nr_plane_pyr[0] = rthis.nr_plane; max_data_term_(DEFAULT_MAX_DATA_TERM), data_weight_(DEFAULT_DATA_WEIGHT),
max_disc_term_(DEFAULT_MAX_DISC_TERM), disc_single_jump_(DEFAULT_DISC_SINGLE_JUMP),
msg_type_(msg_type), nr_plane_(nr_plane), use_local_init_data_cost_(true)
{
}
for (int i = 1; i < levels; i++) void StereoCSBPImpl::compute(InputArray left, InputArray right, OutputArray disparity)
{ {
cols_pyr[i] = cols_pyr[i-1] / 2; compute(left, right, disparity, Stream::Null());
rows_pyr[i] = rows_pyr[i-1] / 2;
nr_plane_pyr[i] = nr_plane_pyr[i-1] * 2;
} }
void StereoCSBPImpl::compute(InputArray _left, InputArray _right, OutputArray disp, Stream& _stream)
{
using namespace cv::gpu::cudev::stereocsbp;
GpuMat u[2], d[2], l[2], r[2], disp_selected_pyr[2], data_cost, data_cost_selected; CV_Assert( msg_type_ == CV_32F || msg_type_ == CV_16S );
CV_Assert( 0 < ndisp_ && 0 < iters_ && 0 < levels_ && 0 < nr_plane_ && levels_ <= 8 );
GpuMat left = _left.getGpuMat();
GpuMat right = _right.getGpuMat();
//allocate buffers CV_Assert( left.type() == CV_8UC1 || left.type() == CV_8UC3 || left.type() == CV_8UC4 );
int buffers_count = 10; // (up + down + left + right + disp_selected_pyr) * 2 CV_Assert( left.size() == right.size() && left.type() == right.type() );
buffers_count += 2; // data_cost has twice more rows than other buffers, what's why +2, not +1;
buffers_count += 1; // data_cost_selected
mbuf.create(rows * rthis.nr_plane * buffers_count, cols, DataType<T>::type);
data_cost = mbuf.rowRange(0, rows * rthis.nr_plane * 2); cudaStream_t stream = StreamAccessor::getStream(_stream);
data_cost_selected = mbuf.rowRange(data_cost.rows, data_cost.rows + rows * rthis.nr_plane);
for(int k = 0; k < 2; ++k) // in/out ////////////////////////////////////////////////////////////////////////////////////////////
{ // Init
GpuMat sub1 = mbuf.rowRange(data_cost.rows + data_cost_selected.rows, mbuf.rows);
GpuMat sub2 = sub1.rowRange((k+0)*sub1.rows/2, (k+1)*sub1.rows/2);
GpuMat *buf_ptrs[] = { &u[k], &d[k], &l[k], &r[k], &disp_selected_pyr[k] }; int rows = left.rows;
for(int _r = 0; _r < 5; ++_r) int cols = left.cols;
levels_ = std::min(levels_, int(log((double)ndisp_) / log(2.0)));
// compute sizes
AutoBuffer<int> buf(levels_ * 3);
int* cols_pyr = buf;
int* rows_pyr = cols_pyr + levels_;
int* nr_plane_pyr = rows_pyr + levels_;
cols_pyr[0] = cols;
rows_pyr[0] = rows;
nr_plane_pyr[0] = nr_plane_;
for (int i = 1; i < levels_; i++)
{ {
*buf_ptrs[_r] = sub2.rowRange(_r * sub2.rows/5, (_r+1) * sub2.rows/5); cols_pyr[i] = cols_pyr[i-1] / 2;
CV_DbgAssert(buf_ptrs[_r]->cols == cols && buf_ptrs[_r]->rows == rows * rthis.nr_plane); rows_pyr[i] = rows_pyr[i-1] / 2;
nr_plane_pyr[i] = nr_plane_pyr[i-1] * 2;
} }
};
size_t elem_step = mbuf.step / sizeof(T); GpuMat u[2], d[2], l[2], r[2], disp_selected_pyr[2], data_cost, data_cost_selected;
Size temp_size = data_cost.size(); //allocate buffers
if ((size_t)temp_size.area() < elem_step * rows_pyr[levels - 1] * rthis.ndisp) int buffers_count = 10; // (up + down + left + right + disp_selected_pyr) * 2
temp_size = Size(static_cast<int>(elem_step), rows_pyr[levels - 1] * rthis.ndisp); buffers_count += 2; // data_cost has twice more rows than other buffers, what's why +2, not +1;
buffers_count += 1; // data_cost_selected
mbuf_.create(rows * nr_plane_ * buffers_count, cols, msg_type_);
temp.create(temp_size, DataType<T>::type); data_cost = mbuf_.rowRange(0, rows * nr_plane_ * 2);
data_cost_selected = mbuf_.rowRange(data_cost.rows, data_cost.rows + rows * nr_plane_);
//////////////////////////////////////////////////////////////////////////// for(int k = 0; k < 2; ++k) // in/out
// Compute {
GpuMat sub1 = mbuf_.rowRange(data_cost.rows + data_cost_selected.rows, mbuf_.rows);
GpuMat sub2 = sub1.rowRange((k+0)*sub1.rows/2, (k+1)*sub1.rows/2);
load_constants(rthis.ndisp, rthis.max_data_term, rthis.data_weight, rthis.max_disc_term, rthis.disc_single_jump, rthis.min_disp_th, left, right, temp); GpuMat *buf_ptrs[] = { &u[k], &d[k], &l[k], &r[k], &disp_selected_pyr[k] };
for(int _r = 0; _r < 5; ++_r)
{
*buf_ptrs[_r] = sub2.rowRange(_r * sub2.rows/5, (_r+1) * sub2.rows/5);
CV_DbgAssert( buf_ptrs[_r]->cols == cols && buf_ptrs[_r]->rows == rows * nr_plane_ );
}
};
l[0].setTo(zero, stream); size_t elem_step = mbuf_.step / mbuf_.elemSize();
d[0].setTo(zero, stream);
r[0].setTo(zero, stream);
u[0].setTo(zero, stream);
l[1].setTo(zero, stream); Size temp_size = data_cost.size();
d[1].setTo(zero, stream); if ((size_t)temp_size.area() < elem_step * rows_pyr[levels_ - 1] * ndisp_)
r[1].setTo(zero, stream); temp_size = Size(static_cast<int>(elem_step), rows_pyr[levels_ - 1] * ndisp_);
u[1].setTo(zero, stream);
data_cost.setTo(zero, stream); temp_.create(temp_size, msg_type_);
data_cost_selected.setTo(zero, stream);
int cur_idx = 0; ////////////////////////////////////////////////////////////////////////////
// Compute
for (int i = levels - 1; i >= 0; i--) load_constants(ndisp_, max_data_term_, data_weight_, max_disc_term_, disc_single_jump_, min_disp_th_, left, right, temp_);
{
if (i == levels - 1) l[0].setTo(0, _stream);
d[0].setTo(0, _stream);
r[0].setTo(0, _stream);
u[0].setTo(0, _stream);
l[1].setTo(0, _stream);
d[1].setTo(0, _stream);
r[1].setTo(0, _stream);
u[1].setTo(0, _stream);
data_cost.setTo(0, _stream);
data_cost_selected.setTo(0, _stream);
int cur_idx = 0;
if (msg_type_ == CV_32F)
{ {
init_data_cost(left.rows, left.cols, disp_selected_pyr[cur_idx].ptr<T>(), data_cost_selected.ptr<T>(), for (int i = levels_ - 1; i >= 0; i--)
elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], rthis.ndisp, left.channels(), rthis.use_local_init_data_cost, cudaStream); {
if (i == levels_ - 1)
{
init_data_cost(left.rows, left.cols, disp_selected_pyr[cur_idx].ptr<float>(), data_cost_selected.ptr<float>(),
elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream);
}
else
{
compute_data_cost(disp_selected_pyr[cur_idx].ptr<float>(), data_cost.ptr<float>(), elem_step,
left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream);
int new_idx = (cur_idx + 1) & 1;
init_message(u[new_idx].ptr<float>(), d[new_idx].ptr<float>(), l[new_idx].ptr<float>(), r[new_idx].ptr<float>(),
u[cur_idx].ptr<float>(), d[cur_idx].ptr<float>(), l[cur_idx].ptr<float>(), r[cur_idx].ptr<float>(),
disp_selected_pyr[new_idx].ptr<float>(), disp_selected_pyr[cur_idx].ptr<float>(),
data_cost_selected.ptr<float>(), data_cost.ptr<float>(), elem_step, rows_pyr[i],
cols_pyr[i], nr_plane_pyr[i], rows_pyr[i+1], cols_pyr[i+1], nr_plane_pyr[i+1], stream);
cur_idx = new_idx;
}
calc_all_iterations(u[cur_idx].ptr<float>(), d[cur_idx].ptr<float>(), l[cur_idx].ptr<float>(), r[cur_idx].ptr<float>(),
data_cost_selected.ptr<float>(), disp_selected_pyr[cur_idx].ptr<float>(), elem_step,
rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, stream);
}
} }
else else
{ {
compute_data_cost(disp_selected_pyr[cur_idx].ptr<T>(), data_cost.ptr<T>(), elem_step, for (int i = levels_ - 1; i >= 0; i--)
left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), cudaStream); {
if (i == levels_ - 1)
{
init_data_cost(left.rows, left.cols, disp_selected_pyr[cur_idx].ptr<short>(), data_cost_selected.ptr<short>(),
elem_step, rows_pyr[i], cols_pyr[i], i, nr_plane_pyr[i], ndisp_, left.channels(), use_local_init_data_cost_, stream);
}
else
{
compute_data_cost(disp_selected_pyr[cur_idx].ptr<short>(), data_cost.ptr<short>(), elem_step,
left.rows, left.cols, rows_pyr[i], cols_pyr[i], rows_pyr[i+1], i, nr_plane_pyr[i+1], left.channels(), stream);
int new_idx = (cur_idx + 1) & 1;
init_message(u[new_idx].ptr<short>(), d[new_idx].ptr<short>(), l[new_idx].ptr<short>(), r[new_idx].ptr<short>(),
u[cur_idx].ptr<short>(), d[cur_idx].ptr<short>(), l[cur_idx].ptr<short>(), r[cur_idx].ptr<short>(),
disp_selected_pyr[new_idx].ptr<short>(), disp_selected_pyr[cur_idx].ptr<short>(),
data_cost_selected.ptr<short>(), data_cost.ptr<short>(), elem_step, rows_pyr[i],
cols_pyr[i], nr_plane_pyr[i], rows_pyr[i+1], cols_pyr[i+1], nr_plane_pyr[i+1], stream);
cur_idx = new_idx;
}
calc_all_iterations(u[cur_idx].ptr<short>(), d[cur_idx].ptr<short>(), l[cur_idx].ptr<short>(), r[cur_idx].ptr<short>(),
data_cost_selected.ptr<short>(), disp_selected_pyr[cur_idx].ptr<short>(), elem_step,
rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], iters_, stream);
}
}
int new_idx = (cur_idx + 1) & 1; const int dtype = disp.fixedType() ? disp.type() : CV_16SC1;
init_message(u[new_idx].ptr<T>(), d[new_idx].ptr<T>(), l[new_idx].ptr<T>(), r[new_idx].ptr<T>(), disp.create(rows, cols, dtype);
u[cur_idx].ptr<T>(), d[cur_idx].ptr<T>(), l[cur_idx].ptr<T>(), r[cur_idx].ptr<T>(), GpuMat out = disp.getGpuMat();
disp_selected_pyr[new_idx].ptr<T>(), disp_selected_pyr[cur_idx].ptr<T>(),
data_cost_selected.ptr<T>(), data_cost.ptr<T>(), elem_step, rows_pyr[i],
cols_pyr[i], nr_plane_pyr[i], rows_pyr[i+1], cols_pyr[i+1], nr_plane_pyr[i+1], cudaStream);
cur_idx = new_idx; if (dtype != CV_16SC1)
{
outBuf_.create(rows, cols, CV_16SC1);
out = outBuf_;
} }
calc_all_iterations(u[cur_idx].ptr<T>(), d[cur_idx].ptr<T>(), l[cur_idx].ptr<T>(), r[cur_idx].ptr<T>(), out.setTo(0, _stream);
data_cost_selected.ptr<T>(), disp_selected_pyr[cur_idx].ptr<T>(), elem_step,
rows_pyr[i], cols_pyr[i], nr_plane_pyr[i], rthis.iters, cudaStream);
}
if (disp.empty()) if (msg_type_ == CV_32F)
disp.create(rows, cols, CV_16S); {
compute_disp(u[cur_idx].ptr<float>(), d[cur_idx].ptr<float>(), l[cur_idx].ptr<float>(), r[cur_idx].ptr<float>(),
out = ((disp.type() == CV_16S) ? disp : (out.create(rows, cols, CV_16S), out)); data_cost_selected.ptr<float>(), disp_selected_pyr[cur_idx].ptr<float>(), elem_step, out, nr_plane_pyr[0], stream);
}
out.setTo(zero, stream); else
{
compute_disp(u[cur_idx].ptr<short>(), d[cur_idx].ptr<short>(), l[cur_idx].ptr<short>(), r[cur_idx].ptr<short>(),
data_cost_selected.ptr<short>(), disp_selected_pyr[cur_idx].ptr<short>(), elem_step, out, nr_plane_pyr[0], stream);
}
compute_disp(u[cur_idx].ptr<T>(), d[cur_idx].ptr<T>(), l[cur_idx].ptr<T>(), r[cur_idx].ptr<T>(), if (dtype != CV_16SC1)
data_cost_selected.ptr<T>(), disp_selected_pyr[cur_idx].ptr<T>(), elem_step, out, nr_plane_pyr[0], cudaStream); out.convertTo(disp, dtype, _stream);
}
if (disp.type() != CV_16S) void StereoCSBPImpl::compute(InputArray /*data*/, OutputArray /*disparity*/, Stream& /*stream*/)
{ {
out.convertTo(disp, disp.type(), stream); CV_Error(Error::StsNotImplemented, "Not implemented");
} }
} }
Ptr<gpu::StereoConstantSpaceBP> cv::gpu::createStereoConstantSpaceBP(int ndisp, int iters, int levels, int nr_plane, int msg_type)
{
return new StereoCSBPImpl(ndisp, iters, levels, nr_plane, msg_type);
}
void cv::gpu::StereoConstantSpaceBP::estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane)
{
ndisp = (int) ((float) width / 3.14f);
if ((ndisp & 1) != 0)
ndisp++;
typedef void (*csbp_operator_t)(StereoConstantSpaceBP& rthis, GpuMat& mbuf, int mm = std::max(width, height);
GpuMat& temp, GpuMat& out, const GpuMat& left, const GpuMat& right, GpuMat& disp, Stream& stream); iters = mm / 100 + ((mm > 1200)? - 4 : 4);
const static csbp_operator_t operators[] = {0, 0, 0, csbp_operator<short>, 0, csbp_operator<float>, 0, 0}; levels = (int)::log(static_cast<double>(mm)) * 2 / 3;
if (levels == 0) levels++;
void cv::gpu::StereoConstantSpaceBP::operator()(const GpuMat& left, const GpuMat& right, GpuMat& disp, Stream& stream) nr_plane = (int) ((float) ndisp / std::pow(2.0, levels + 1));
{
CV_Assert(msg_type == CV_32F || msg_type == CV_16S);
operators[msg_type](*this, messages_buffers, temp, out, left, right, disp, stream);
} }
#endif /* !defined (HAVE_CUDA) */ #endif /* !defined (HAVE_CUDA) */
...@@ -155,10 +155,10 @@ GPU_TEST_P(StereoConstantSpaceBP, Regression) ...@@ -155,10 +155,10 @@ GPU_TEST_P(StereoConstantSpaceBP, Regression)
ASSERT_FALSE(right_image.empty()); ASSERT_FALSE(right_image.empty());
ASSERT_FALSE(disp_gold.empty()); ASSERT_FALSE(disp_gold.empty());
cv::gpu::StereoConstantSpaceBP csbp(128, 16, 4, 4); cv::Ptr<cv::gpu::StereoConstantSpaceBP> csbp = cv::gpu::createStereoConstantSpaceBP(128, 16, 4, 4);
cv::gpu::GpuMat disp; cv::gpu::GpuMat disp;
csbp(loadMat(left_image), loadMat(right_image), disp); csbp->compute(loadMat(left_image), loadMat(right_image), disp);
cv::Mat h_disp(disp); cv::Mat h_disp(disp);
h_disp.convertTo(h_disp, disp_gold.depth()); h_disp.convertTo(h_disp, disp_gold.depth());
......
...@@ -67,7 +67,7 @@ private: ...@@ -67,7 +67,7 @@ private:
Ptr<gpu::StereoBM> bm; Ptr<gpu::StereoBM> bm;
Ptr<gpu::StereoBeliefPropagation> bp; Ptr<gpu::StereoBeliefPropagation> bp;
gpu::StereoConstantSpaceBP csbp; Ptr<gpu::StereoConstantSpaceBP> csbp;
int64 work_begin; int64 work_begin;
double work_fps; double work_fps;
...@@ -174,7 +174,7 @@ void App::run() ...@@ -174,7 +174,7 @@ void App::run()
// Set common parameters // Set common parameters
bm = gpu::createStereoBM(p.ndisp); bm = gpu::createStereoBM(p.ndisp);
bp = gpu::createStereoBeliefPropagation(p.ndisp); bp = gpu::createStereoBeliefPropagation(p.ndisp);
csbp.ndisp = p.ndisp; csbp = cv::gpu::createStereoConstantSpaceBP(p.ndisp);
// Prepare disparity map of specified type // Prepare disparity map of specified type
Mat disp(left.size(), CV_8U); Mat disp(left.size(), CV_8U);
...@@ -204,7 +204,7 @@ void App::run() ...@@ -204,7 +204,7 @@ void App::run()
bm->compute(d_left, d_right, d_disp); bm->compute(d_left, d_right, d_disp);
break; break;
case Params::BP: bp->compute(d_left, d_right, d_disp); break; case Params::BP: bp->compute(d_left, d_right, d_disp); break;
case Params::CSBP: csbp(d_left, d_right, d_disp); break; case Params::CSBP: csbp->compute(d_left, d_right, d_disp); break;
} }
workEnd(); workEnd();
...@@ -236,8 +236,8 @@ void App::printParams() const ...@@ -236,8 +236,8 @@ void App::printParams() const
cout << "level_count: " << bp->getNumLevels() << endl; cout << "level_count: " << bp->getNumLevels() << endl;
break; break;
case Params::CSBP: case Params::CSBP:
cout << "iter_count: " << csbp.iters << endl; cout << "iter_count: " << csbp->getNumIters() << endl;
cout << "level_count: " << csbp.levels << endl; cout << "level_count: " << csbp->getNumLevels() << endl;
break; break;
} }
cout << endl; cout << endl;
...@@ -306,14 +306,14 @@ void App::handleKey(char key) ...@@ -306,14 +306,14 @@ void App::handleKey(char key)
cout << "ndisp: " << p.ndisp << endl; cout << "ndisp: " << p.ndisp << endl;
bm->setNumDisparities(p.ndisp); bm->setNumDisparities(p.ndisp);
bp->setNumDisparities(p.ndisp); bp->setNumDisparities(p.ndisp);
csbp.ndisp = p.ndisp; csbp->setNumDisparities(p.ndisp);
break; break;
case 'q': case 'Q': case 'q': case 'Q':
p.ndisp = max(p.ndisp - 8, 1); p.ndisp = max(p.ndisp - 8, 1);
cout << "ndisp: " << p.ndisp << endl; cout << "ndisp: " << p.ndisp << endl;
bm->setNumDisparities(p.ndisp); bm->setNumDisparities(p.ndisp);
bp->setNumDisparities(p.ndisp); bp->setNumDisparities(p.ndisp);
csbp.ndisp = p.ndisp; csbp->setNumDisparities(p.ndisp);
break; break;
case '2': case '2':
if (p.method == Params::BM) if (p.method == Params::BM)
...@@ -337,8 +337,8 @@ void App::handleKey(char key) ...@@ -337,8 +337,8 @@ void App::handleKey(char key)
} }
else if (p.method == Params::CSBP) else if (p.method == Params::CSBP)
{ {
csbp.iters += 1; csbp->setNumIters(csbp->getNumIters() + 1);
cout << "iter_count: " << csbp.iters << endl; cout << "iter_count: " << csbp->getNumIters() << endl;
} }
break; break;
case 'e': case 'E': case 'e': case 'E':
...@@ -349,8 +349,8 @@ void App::handleKey(char key) ...@@ -349,8 +349,8 @@ void App::handleKey(char key)
} }
else if (p.method == Params::CSBP) else if (p.method == Params::CSBP)
{ {
csbp.iters = max(csbp.iters - 1, 1); csbp->setNumIters(max(csbp->getNumIters() - 1, 1));
cout << "iter_count: " << csbp.iters << endl; cout << "iter_count: " << csbp->getNumIters() << endl;
} }
break; break;
case '4': case '4':
...@@ -361,8 +361,8 @@ void App::handleKey(char key) ...@@ -361,8 +361,8 @@ void App::handleKey(char key)
} }
else if (p.method == Params::CSBP) else if (p.method == Params::CSBP)
{ {
csbp.levels += 1; csbp->setNumLevels(csbp->getNumLevels() + 1);
cout << "level_count: " << csbp.levels << endl; cout << "level_count: " << csbp->getNumLevels() << endl;
} }
break; break;
case 'r': case 'R': case 'r': case 'R':
...@@ -373,8 +373,8 @@ void App::handleKey(char key) ...@@ -373,8 +373,8 @@ void App::handleKey(char key)
} }
else if (p.method == Params::CSBP) else if (p.method == Params::CSBP)
{ {
csbp.levels = max(csbp.levels - 1, 1); csbp->setNumLevels(max(csbp->getNumLevels() - 1, 1));
cout << "level_count: " << csbp.levels << endl; cout << "level_count: " << csbp->getNumLevels() << endl;
} }
break; break;
} }
......
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