提交 eff6dccb 编写于 作者: R Roman Donchenko 提交者: OpenCV Buildbot

Merge pull request #1014 from jet47:gpustereo-refactoring

此差异已折叠。
...@@ -48,199 +48,145 @@ ...@@ -48,199 +48,145 @@
#endif #endif
#include "opencv2/core/gpu.hpp" #include "opencv2/core/gpu.hpp"
#include "opencv2/calib3d.hpp"
namespace cv { namespace gpu { namespace cv { namespace gpu {
class CV_EXPORTS StereoBM_GPU /////////////////////////////////////////
// StereoBM
class CV_EXPORTS StereoBM : public cv::StereoBM
{ {
public: public:
enum { BASIC_PRESET = 0, PREFILTER_XSOBEL = 1 }; using cv::StereoBM::compute;
enum { DEFAULT_NDISP = 64, DEFAULT_WINSZ = 19 };
//! the default constructor
StereoBM_GPU();
//! the full constructor taking the camera-specific preset, number of disparities and the SAD window size. ndisparities must be multiple of 8.
StereoBM_GPU(int preset, int ndisparities = DEFAULT_NDISP, int winSize = DEFAULT_WINSZ);
//! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair
//! Output disparity has CV_8U type.
void operator()(const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream = Stream::Null());
//! Some heuristics that tries to estmate virtual void compute(InputArray left, InputArray right, OutputArray disparity, Stream& stream) = 0;
// if current GPU will be faster than CPU in this algorithm. };
// It queries current active device.
static bool checkIfGpuCallReasonable();
int preset;
int ndisp;
int winSize;
// If avergeTexThreshold == 0 => post procesing is disabled CV_EXPORTS Ptr<gpu::StereoBM> createStereoBM(int numDisparities = 64, int blockSize = 19);
// If avergeTexThreshold != 0 then disparity is set 0 in each point (x,y) where for left image
// SumOfHorizontalGradiensInWindow(x, y, winSize) < (winSize * winSize) * avergeTexThreshold
// i.e. input left image is low textured.
float avergeTexThreshold;
private: /////////////////////////////////////////
GpuMat minSSD, leBuf, riBuf; // StereoBeliefPropagation
};
// "Efficient Belief Propagation for Early Vision" //! "Efficient Belief Propagation for Early Vision" P.Felzenszwalb
// P.Felzenszwalb class CV_EXPORTS StereoBeliefPropagation : public cv::StereoMatcher
class CV_EXPORTS StereoBeliefPropagation
{ {
public: public:
enum { DEFAULT_NDISP = 64 }; using cv::StereoMatcher::compute;
enum { DEFAULT_ITERS = 5 };
enum { DEFAULT_LEVELS = 5 };
static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels);
//! the default constructor
explicit StereoBeliefPropagation(int ndisp = DEFAULT_NDISP,
int iters = DEFAULT_ITERS,
int levels = DEFAULT_LEVELS,
int msg_type = CV_32F);
//! the full constructor taking the number of disparities, number of BP iterations on each level,
//! number of levels, truncation of data cost, data weight,
//! truncation of discontinuity cost and discontinuity single jump
//! DataTerm = data_weight * min(fabs(I2-I1), max_data_term)
//! DiscTerm = min(disc_single_jump * fabs(f1-f2), max_disc_term)
//! please see paper for more details
StereoBeliefPropagation(int ndisp, int iters, int levels,
float max_data_term, float data_weight,
float max_disc_term, float disc_single_jump,
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());
virtual void compute(InputArray left, InputArray right, OutputArray disparity, Stream& stream) = 0;
//! version for user specified data term //! version for user specified data term
void operator()(const GpuMat& data, GpuMat& disparity, Stream& stream = Stream::Null()); virtual void compute(InputArray data, OutputArray disparity, Stream& stream = Stream::Null()) = 0;
int ndisp; //! number of BP iterations on each level
virtual int getNumIters() const = 0;
virtual void setNumIters(int iters) = 0;
int iters; //! number of levels
int levels; virtual int getNumLevels() const = 0;
virtual void setNumLevels(int levels) = 0;
float max_data_term; //! truncation of data cost
float data_weight; virtual double getMaxDataTerm() const = 0;
float max_disc_term; virtual void setMaxDataTerm(double max_data_term) = 0;
float disc_single_jump;
int msg_type; //! data weight
private: virtual double getDataWeight() const = 0;
GpuMat u, d, l, r, u2, d2, l2, r2; virtual void setDataWeight(double data_weight) = 0;
std::vector<GpuMat> datas;
GpuMat out;
};
// "A Constant-Space Belief Propagation Algorithm for Stereo Matching" //! truncation of discontinuity cost
// Qingxiong Yang, Liang Wang, Narendra Ahuja virtual double getMaxDiscTerm() const = 0;
// http://vision.ai.uiuc.edu/~qyang6/ virtual void setMaxDiscTerm(double max_disc_term) = 0;
class CV_EXPORTS StereoConstantSpaceBP
{
public:
enum { DEFAULT_NDISP = 128 };
enum { DEFAULT_ITERS = 8 };
enum { DEFAULT_LEVELS = 4 };
enum { DEFAULT_NR_PLANE = 4 };
static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane); //! discontinuity single jump
virtual double getDiscSingleJump() const = 0;
virtual void setDiscSingleJump(double disc_single_jump) = 0;
//! the default constructor //! type for messages (CV_16SC1 or CV_32FC1)
explicit StereoConstantSpaceBP(int ndisp = DEFAULT_NDISP, virtual int getMsgType() const = 0;
int iters = DEFAULT_ITERS, virtual void setMsgType(int msg_type) = 0;
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, static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels);
//! 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; CV_EXPORTS Ptr<gpu::StereoBeliefPropagation>
createStereoBeliefPropagation(int ndisp = 64, int iters = 5, int levels = 5, int msg_type = CV_32F);
int iters; /////////////////////////////////////////
int levels; // StereoConstantSpaceBP
int nr_plane; //! "A Constant-Space Belief Propagation Algorithm for Stereo Matching"
//! Qingxiong Yang, Liang Wang, Narendra Ahuja
//! http://vision.ai.uiuc.edu/~qyang6/
class CV_EXPORTS StereoConstantSpaceBP : public gpu::StereoBeliefPropagation
{
public:
//! number of active disparity on the first level
virtual int getNrPlane() const = 0;
virtual void setNrPlane(int nr_plane) = 0;
float max_data_term; virtual bool getUseLocalInitDataCost() const = 0;
float data_weight; virtual void setUseLocalInitDataCost(bool use_local_init_data_cost) = 0;
float max_disc_term;
float disc_single_jump;
int min_disp_th; static void estimateRecommendedParams(int width, int height, int& ndisp, int& iters, int& levels, int& nr_plane);
};
int msg_type; CV_EXPORTS Ptr<gpu::StereoConstantSpaceBP>
createStereoConstantSpaceBP(int ndisp = 128, int iters = 8, int levels = 4, int nr_plane = 4, int msg_type = CV_32F);
bool use_local_init_data_cost; /////////////////////////////////////////
private: // DisparityBilateralFilter
GpuMat messages_buffers;
GpuMat temp; //! Disparity map refinement using joint bilateral filtering given a single color image.
GpuMat out; //! Qingxiong Yang, Liang Wang, Narendra Ahuja
}; //! http://vision.ai.uiuc.edu/~qyang6/
class CV_EXPORTS DisparityBilateralFilter : public cv::Algorithm
// Disparity map refinement using joint bilateral filtering given a single color image.
// Qingxiong Yang, Liang Wang, Narendra Ahuja
// 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);
/////////////////////////////////////////
// Utility
//! 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.
//! Each element of this matrix will contain the 3D coordinates of the point (x,y,z,1), computed from the disparity map. //! Each element of this matrix will contain the 3D coordinates of the point (x,y,z,1), computed from the disparity map.
//! Q is the 4x4 perspective transformation matrix that can be obtained with cvStereoRectify. //! Q is the 4x4 perspective transformation matrix that can be obtained with cvStereoRectify.
CV_EXPORTS void reprojectImageTo3D(const GpuMat& disp, GpuMat& xyzw, const Mat& Q, int dst_cn = 4, Stream& stream = Stream::Null()); CV_EXPORTS void reprojectImageTo3D(InputArray disp, OutputArray xyzw, InputArray Q, int dst_cn = 4, Stream& stream = Stream::Null());
//! Does coloring of disparity image: [0..ndisp) -> [0..240, 1, 1] in HSV. //! Does coloring of disparity image: [0..ndisp) -> [0..240, 1, 1] in HSV.
//! Supported types of input disparity: CV_8U, CV_16S. //! Supported types of input disparity: CV_8U, CV_16S.
//! Output disparity has CV_8UC4 type in BGRA format (alpha = 255). //! Output disparity has CV_8UC4 type in BGRA format (alpha = 255).
CV_EXPORTS void drawColorDisp(const GpuMat& src_disp, GpuMat& dst_disp, int ndisp, Stream& stream = Stream::Null()); CV_EXPORTS void drawColorDisp(InputArray src_disp, OutputArray dst_disp, int ndisp, Stream& stream = Stream::Null());
}} // namespace cv { namespace gpu { }} // namespace cv { namespace gpu {
......
...@@ -63,18 +63,17 @@ PERF_TEST_P(ImagePair, StereoBM, ...@@ -63,18 +63,17 @@ PERF_TEST_P(ImagePair, StereoBM,
const cv::Mat imgRight = readImage(GET_PARAM(1), cv::IMREAD_GRAYSCALE); const cv::Mat imgRight = readImage(GET_PARAM(1), cv::IMREAD_GRAYSCALE);
ASSERT_FALSE(imgRight.empty()); ASSERT_FALSE(imgRight.empty());
const int preset = 0;
const int ndisp = 256; const int ndisp = 256;
if (PERF_RUN_GPU()) if (PERF_RUN_GPU())
{ {
cv::gpu::StereoBM_GPU d_bm(preset, ndisp); cv::Ptr<cv::StereoBM> d_bm = cv::gpu::createStereoBM(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_bm(d_imgLeft, d_imgRight, dst); TEST_CYCLE() d_bm->compute(d_imgLeft, d_imgRight, dst);
GPU_SANITY_CHECK(dst); GPU_SANITY_CHECK(dst);
} }
...@@ -108,13 +107,13 @@ PERF_TEST_P(ImagePair, StereoBeliefPropagation, ...@@ -108,13 +107,13 @@ PERF_TEST_P(ImagePair, StereoBeliefPropagation,
if (PERF_RUN_GPU()) if (PERF_RUN_GPU())
{ {
cv::gpu::StereoBeliefPropagation d_bp(ndisp); cv::Ptr<cv::gpu::StereoBeliefPropagation> d_bp = cv::gpu::createStereoBeliefPropagation(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_bp(d_imgLeft, d_imgRight, dst); TEST_CYCLE() d_bp->compute(d_imgLeft, d_imgRight, dst);
GPU_SANITY_CHECK(dst); GPU_SANITY_CHECK(dst);
} }
...@@ -142,13 +141,13 @@ PERF_TEST_P(ImagePair, StereoConstantSpaceBP, ...@@ -142,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);
} }
...@@ -174,13 +173,13 @@ PERF_TEST_P(ImagePair, DisparityBilateralFilter, ...@@ -174,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) */
...@@ -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__ */
...@@ -47,11 +47,7 @@ using namespace cv::gpu; ...@@ -47,11 +47,7 @@ using namespace cv::gpu;
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
cv::gpu::StereoBM_GPU::StereoBM_GPU() { throw_no_cuda(); } Ptr<gpu::StereoBM> cv::gpu::createStereoBM(int, int) { throw_no_cuda(); return Ptr<gpu::StereoBM>(); }
cv::gpu::StereoBM_GPU::StereoBM_GPU(int, int, int) { throw_no_cuda(); }
bool cv::gpu::StereoBM_GPU::checkIfGpuCallReasonable() { throw_no_cuda(); return false; }
void cv::gpu::StereoBM_GPU::operator() ( const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_no_cuda(); }
#else /* !defined (HAVE_CUDA) */ #else /* !defined (HAVE_CUDA) */
...@@ -67,74 +63,123 @@ namespace cv { namespace gpu { namespace cudev ...@@ -67,74 +63,123 @@ namespace cv { namespace gpu { namespace cudev
namespace namespace
{ {
const float defaultAvgTexThreshold = 3; class StereoBMImpl : public gpu::StereoBM
} {
public:
StereoBMImpl(int numDisparities, int blockSize);
cv::gpu::StereoBM_GPU::StereoBM_GPU() void compute(InputArray left, InputArray right, OutputArray disparity);
: preset(BASIC_PRESET), ndisp(DEFAULT_NDISP), winSize(DEFAULT_WINSZ), avergeTexThreshold(defaultAvgTexThreshold) void compute(InputArray left, InputArray right, OutputArray disparity, Stream& stream);
{
}
cv::gpu::StereoBM_GPU::StereoBM_GPU(int preset_, int ndisparities_, int winSize_) int getMinDisparity() const { return 0; }
: preset(preset_), ndisp(ndisparities_), winSize(winSize_), avergeTexThreshold(defaultAvgTexThreshold) void setMinDisparity(int /*minDisparity*/) {}
{
const int max_supported_ndisp = 1 << (sizeof(unsigned char) * 8);
CV_Assert(0 < ndisp && ndisp <= max_supported_ndisp);
CV_Assert(ndisp % 8 == 0);
CV_Assert(winSize % 2 == 1);
}
bool cv::gpu::StereoBM_GPU::checkIfGpuCallReasonable() int getNumDisparities() const { return ndisp_; }
{ void setNumDisparities(int numDisparities) { ndisp_ = numDisparities; }
if (0 == getCudaEnabledDeviceCount())
return false;
DeviceInfo device_info; int getBlockSize() const { return winSize_; }
void setBlockSize(int blockSize) { winSize_ = blockSize; }
if (device_info.major() > 1 || device_info.multiProcessorCount() > 16) int getSpeckleWindowSize() const { return 0; }
return true; void setSpeckleWindowSize(int /*speckleWindowSize*/) {}
return false; int getSpeckleRange() const { return 0; }
} void setSpeckleRange(int /*speckleRange*/) {}
namespace int getDisp12MaxDiff() const { return 0; }
{ void setDisp12MaxDiff(int /*disp12MaxDiff*/) {}
void stereo_bm_gpu_operator( GpuMat& minSSD, GpuMat& leBuf, GpuMat& riBuf, int preset, int ndisp, int winSize, float avergeTexThreshold, const GpuMat& left, const GpuMat& right, GpuMat& disparity, cudaStream_t stream)
int getPreFilterType() const { return preset_; }
void setPreFilterType(int preFilterType) { preset_ = preFilterType; }
int getPreFilterSize() const { return 0; }
void setPreFilterSize(int /*preFilterSize*/) {}
int getPreFilterCap() const { return preFilterCap_; }
void setPreFilterCap(int preFilterCap) { preFilterCap_ = preFilterCap; }
int getTextureThreshold() const { return avergeTexThreshold_; }
void setTextureThreshold(int textureThreshold) { avergeTexThreshold_ = textureThreshold; }
int getUniquenessRatio() const { return 0; }
void setUniquenessRatio(int /*uniquenessRatio*/) {}
int getSmallerBlockSize() const { return 0; }
void setSmallerBlockSize(int /*blockSize*/){}
Rect getROI1() const { return Rect(); }
void setROI1(Rect /*roi1*/) {}
Rect getROI2() const { return Rect(); }
void setROI2(Rect /*roi2*/) {}
private:
int preset_;
int ndisp_;
int winSize_;
int preFilterCap_;
float avergeTexThreshold_;
GpuMat minSSD_, leBuf_, riBuf_;
};
StereoBMImpl::StereoBMImpl(int numDisparities, int blockSize)
: preset_(0), ndisp_(numDisparities), winSize_(blockSize), preFilterCap_(31), avergeTexThreshold_(3)
{
}
void StereoBMImpl::compute(InputArray left, InputArray right, OutputArray disparity)
{
compute(left, right, disparity, Stream::Null());
}
void StereoBMImpl::compute(InputArray _left, InputArray _right, OutputArray _disparity, Stream& _stream)
{ {
using namespace ::cv::gpu::cudev::stereobm; using namespace ::cv::gpu::cudev::stereobm;
CV_Assert(left.rows == right.rows && left.cols == right.cols); const int max_supported_ndisp = 1 << (sizeof(unsigned char) * 8);
CV_Assert(left.type() == CV_8UC1); CV_Assert( 0 < ndisp_ && ndisp_ <= max_supported_ndisp );
CV_Assert(right.type() == CV_8UC1); CV_Assert( ndisp_ % 8 == 0 );
CV_Assert( winSize_ % 2 == 1 );
GpuMat left = _left.getGpuMat();
GpuMat right = _right.getGpuMat();
CV_Assert( left.type() == CV_8UC1 );
CV_Assert( left.size() == right.size() && left.type() == right.type() );
_disparity.create(left.size(), CV_8UC1);
GpuMat disparity = _disparity.getGpuMat();
cudaStream_t stream = StreamAccessor::getStream(_stream);
disparity.create(left.size(), CV_8U); gpu::ensureSizeIsEnough(left.size(), CV_32SC1, minSSD_);
minSSD.create(left.size(), CV_32S);
GpuMat le_for_bm = left; PtrStepSzb le_for_bm = left;
GpuMat ri_for_bm = right; PtrStepSzb ri_for_bm = right;
if (preset == StereoBM_GPU::PREFILTER_XSOBEL) if (preset_ == cv::StereoBM::PREFILTER_XSOBEL)
{ {
leBuf.create( left.size(), left.type()); gpu::ensureSizeIsEnough(left.size(), left.type(), leBuf_);
riBuf.create(right.size(), right.type()); gpu::ensureSizeIsEnough(right.size(), right.type(), riBuf_);
prefilter_xsobel( left, leBuf, 31, stream); prefilter_xsobel( left, leBuf_, preFilterCap_, stream);
prefilter_xsobel(right, riBuf, 31, stream); prefilter_xsobel(right, riBuf_, preFilterCap_, stream);
le_for_bm = leBuf; le_for_bm = leBuf_;
ri_for_bm = riBuf; ri_for_bm = riBuf_;
} }
stereoBM_GPU(le_for_bm, ri_for_bm, disparity, ndisp, winSize, minSSD, stream); stereoBM_GPU(le_for_bm, ri_for_bm, disparity, ndisp_, winSize_, minSSD_, stream);
if (avergeTexThreshold) if (avergeTexThreshold_ > 0)
postfilter_textureness(le_for_bm, winSize, avergeTexThreshold, disparity, stream); postfilter_textureness(le_for_bm, winSize_, avergeTexThreshold_, disparity, stream);
} }
} }
void cv::gpu::StereoBM_GPU::operator() ( const GpuMat& left, const GpuMat& right, GpuMat& disparity, Stream& stream) Ptr<gpu::StereoBM> cv::gpu::createStereoBM(int numDisparities, int blockSize)
{ {
stereo_bm_gpu_operator(minSSD, leBuf, riBuf, preset, ndisp, winSize, avergeTexThreshold, left, right, disparity, StreamAccessor::getStream(stream)); return new StereoBMImpl(numDisparities, blockSize);
} }
#endif /* !defined (HAVE_CUDA) */ #endif /* !defined (HAVE_CUDA) */
此差异已折叠。
...@@ -47,8 +47,8 @@ using namespace cv::gpu; ...@@ -47,8 +47,8 @@ using namespace cv::gpu;
#if !defined HAVE_CUDA || defined(CUDA_DISABLER) #if !defined HAVE_CUDA || defined(CUDA_DISABLER)
void cv::gpu::reprojectImageTo3D(const GpuMat&, GpuMat&, const Mat&, int, Stream&) { throw_no_cuda(); } void cv::gpu::reprojectImageTo3D(InputArray, OutputArray, InputArray, int, Stream&) { throw_no_cuda(); }
void cv::gpu::drawColorDisp(const GpuMat&, GpuMat&, int, Stream&) { throw_no_cuda(); } void cv::gpu::drawColorDisp(InputArray, OutputArray, int, Stream&) { throw_no_cuda(); }
#else #else
...@@ -61,7 +61,7 @@ namespace cv { namespace gpu { namespace cudev ...@@ -61,7 +61,7 @@ namespace cv { namespace gpu { namespace cudev
void reprojectImageTo3D_gpu(const PtrStepSzb disp, PtrStepSzb xyz, const float* q, cudaStream_t stream); void reprojectImageTo3D_gpu(const PtrStepSzb disp, PtrStepSzb xyz, const float* q, cudaStream_t stream);
}}} }}}
void cv::gpu::reprojectImageTo3D(const GpuMat& disp, GpuMat& xyz, const Mat& Q, int dst_cn, Stream& stream) void cv::gpu::reprojectImageTo3D(InputArray _disp, OutputArray _xyz, InputArray _Q, int dst_cn, Stream& stream)
{ {
using namespace cv::gpu::cudev; using namespace cv::gpu::cudev;
...@@ -72,11 +72,15 @@ void cv::gpu::reprojectImageTo3D(const GpuMat& disp, GpuMat& xyz, const Mat& Q, ...@@ -72,11 +72,15 @@ void cv::gpu::reprojectImageTo3D(const GpuMat& disp, GpuMat& xyz, const Mat& Q,
{reprojectImageTo3D_gpu<uchar, float4>, 0, 0, reprojectImageTo3D_gpu<short, float4>} {reprojectImageTo3D_gpu<uchar, float4>, 0, 0, reprojectImageTo3D_gpu<short, float4>}
}; };
CV_Assert(disp.type() == CV_8U || disp.type() == CV_16S); GpuMat disp = _disp.getGpuMat();
CV_Assert(Q.type() == CV_32F && Q.rows == 4 && Q.cols == 4 && Q.isContinuous()); Mat Q = _Q.getMat();
CV_Assert(dst_cn == 3 || dst_cn == 4);
xyz.create(disp.size(), CV_MAKE_TYPE(CV_32F, dst_cn)); CV_Assert( disp.type() == CV_8U || disp.type() == CV_16S );
CV_Assert( Q.type() == CV_32F && Q.rows == 4 && Q.cols == 4 && Q.isContinuous() );
CV_Assert( dst_cn == 3 || dst_cn == 4 );
_xyz.create(disp.size(), CV_MAKE_TYPE(CV_32F, dst_cn));
GpuMat xyz = _xyz.getGpuMat();
funcs[dst_cn == 4][disp.type()](disp, xyz, Q.ptr<float>(), StreamAccessor::getStream(stream)); funcs[dst_cn == 4][disp.type()](disp, xyz, Q.ptr<float>(), StreamAccessor::getStream(stream));
} }
...@@ -93,23 +97,25 @@ namespace cv { namespace gpu { namespace cudev ...@@ -93,23 +97,25 @@ namespace cv { namespace gpu { namespace cudev
namespace namespace
{ {
template <typename T> template <typename T>
void drawColorDisp_caller(const GpuMat& src, GpuMat& dst, int ndisp, const cudaStream_t& stream) void drawColorDisp_caller(const GpuMat& src, OutputArray _dst, int ndisp, const cudaStream_t& stream)
{ {
using namespace ::cv::gpu::cudev; using namespace ::cv::gpu::cudev;
dst.create(src.size(), CV_8UC4); _dst.create(src.size(), CV_8UC4);
GpuMat dst = _dst.getGpuMat();
drawColorDisp_gpu((PtrStepSz<T>)src, dst, ndisp, stream); drawColorDisp_gpu((PtrStepSz<T>)src, dst, ndisp, stream);
} }
typedef void (*drawColorDisp_caller_t)(const GpuMat& src, GpuMat& dst, int ndisp, const cudaStream_t& stream);
const drawColorDisp_caller_t drawColorDisp_callers[] = {drawColorDisp_caller<unsigned char>, 0, 0, drawColorDisp_caller<short>, 0, 0, 0, 0};
} }
void cv::gpu::drawColorDisp(const GpuMat& src, GpuMat& dst, int ndisp, Stream& stream) void cv::gpu::drawColorDisp(InputArray _src, OutputArray dst, int ndisp, Stream& stream)
{ {
CV_Assert(src.type() == CV_8U || src.type() == CV_16S); typedef void (*drawColorDisp_caller_t)(const GpuMat& src, OutputArray dst, int ndisp, const cudaStream_t& stream);
const drawColorDisp_caller_t drawColorDisp_callers[] = {drawColorDisp_caller<unsigned char>, 0, 0, drawColorDisp_caller<short>, 0, 0, 0, 0};
GpuMat src = _src.getGpuMat();
CV_Assert( src.type() == CV_8U || src.type() == CV_16S );
drawColorDisp_callers[src.type()](src, dst, ndisp, StreamAccessor::getStream(stream)); drawColorDisp_callers[src.type()](src, dst, ndisp, StreamAccessor::getStream(stream));
} }
......
...@@ -71,10 +71,10 @@ GPU_TEST_P(StereoBM, Regression) ...@@ -71,10 +71,10 @@ GPU_TEST_P(StereoBM, Regression)
ASSERT_FALSE(right_image.empty()); ASSERT_FALSE(right_image.empty());
ASSERT_FALSE(disp_gold.empty()); ASSERT_FALSE(disp_gold.empty());
cv::gpu::StereoBM_GPU bm(0, 128, 19); cv::Ptr<cv::StereoBM> bm = cv::gpu::createStereoBM(128, 19);
cv::gpu::GpuMat disp; cv::gpu::GpuMat disp;
bm(loadMat(left_image), loadMat(right_image), disp); bm->compute(loadMat(left_image), loadMat(right_image), disp);
EXPECT_MAT_NEAR(disp_gold, disp, 0.0); EXPECT_MAT_NEAR(disp_gold, disp, 0.0);
} }
...@@ -106,10 +106,15 @@ GPU_TEST_P(StereoBeliefPropagation, Regression) ...@@ -106,10 +106,15 @@ GPU_TEST_P(StereoBeliefPropagation, Regression)
ASSERT_FALSE(right_image.empty()); ASSERT_FALSE(right_image.empty());
ASSERT_FALSE(disp_gold.empty()); ASSERT_FALSE(disp_gold.empty());
cv::gpu::StereoBeliefPropagation bp(64, 8, 2, 25, 0.1f, 15, 1, CV_16S); cv::Ptr<cv::gpu::StereoBeliefPropagation> bp = cv::gpu::createStereoBeliefPropagation(64, 8, 2, CV_16S);
bp->setMaxDataTerm(25.0);
bp->setDataWeight(0.1);
bp->setMaxDiscTerm(15.0);
bp->setDiscSingleJump(1.0);
cv::gpu::GpuMat disp; cv::gpu::GpuMat disp;
bp(loadMat(left_image), loadMat(right_image), disp); bp->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());
...@@ -150,10 +155,10 @@ GPU_TEST_P(StereoConstantSpaceBP, Regression) ...@@ -150,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());
......
...@@ -85,7 +85,7 @@ void inline contextOff() ...@@ -85,7 +85,7 @@ void inline contextOff()
// GPUs data // GPUs data
GpuMat d_left[2]; GpuMat d_left[2];
GpuMat d_right[2]; GpuMat d_right[2];
StereoBM_GPU* bm[2]; Ptr<gpu::StereoBM> bm[2];
GpuMat d_result[2]; GpuMat d_result[2];
static void printHelp() static void printHelp()
...@@ -162,14 +162,14 @@ int main(int argc, char** argv) ...@@ -162,14 +162,14 @@ int main(int argc, char** argv)
contextOn(0); contextOn(0);
d_left[0].upload(left.rowRange(0, left.rows / 2)); d_left[0].upload(left.rowRange(0, left.rows / 2));
d_right[0].upload(right.rowRange(0, right.rows / 2)); d_right[0].upload(right.rowRange(0, right.rows / 2));
bm[0] = new StereoBM_GPU(); bm[0] = gpu::createStereoBM();
contextOff(); contextOff();
// Split source images for processing on the GPU #1 // Split source images for processing on the GPU #1
contextOn(1); contextOn(1);
d_left[1].upload(left.rowRange(left.rows / 2, left.rows)); d_left[1].upload(left.rowRange(left.rows / 2, left.rows));
d_right[1].upload(right.rowRange(right.rows / 2, right.rows)); d_right[1].upload(right.rowRange(right.rows / 2, right.rows));
bm[1] = new StereoBM_GPU(); bm[1] = gpu::createStereoBM();
contextOff(); contextOff();
// Execute calculation in two threads using two GPUs // Execute calculation in two threads using two GPUs
...@@ -182,7 +182,7 @@ int main(int argc, char** argv) ...@@ -182,7 +182,7 @@ int main(int argc, char** argv)
d_left[0].release(); d_left[0].release();
d_right[0].release(); d_right[0].release();
d_result[0].release(); d_result[0].release();
delete bm[0]; bm[0].release();
contextOff(); contextOff();
// Release the second GPU resources // Release the second GPU resources
...@@ -191,7 +191,7 @@ int main(int argc, char** argv) ...@@ -191,7 +191,7 @@ int main(int argc, char** argv)
d_left[1].release(); d_left[1].release();
d_right[1].release(); d_right[1].release();
d_result[1].release(); d_result[1].release();
delete bm[1]; bm[1].release();
contextOff(); contextOff();
waitKey(); waitKey();
...@@ -204,8 +204,7 @@ void Worker::operator()(int device_id) const ...@@ -204,8 +204,7 @@ void Worker::operator()(int device_id) const
{ {
contextOn(device_id); contextOn(device_id);
bm[device_id]->operator()(d_left[device_id], d_right[device_id], bm[device_id]->compute(d_left[device_id], d_right[device_id], d_result[device_id]);
d_result[device_id]);
std::cout << "GPU #" << device_id << " (" << DeviceInfo().name() std::cout << "GPU #" << device_id << " (" << DeviceInfo().name()
<< "): finished\n"; << "): finished\n";
......
...@@ -65,9 +65,9 @@ private: ...@@ -65,9 +65,9 @@ private:
Mat left, right; Mat left, right;
gpu::GpuMat d_left, d_right; gpu::GpuMat d_left, d_right;
gpu::StereoBM_GPU bm; Ptr<gpu::StereoBM> bm;
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;
...@@ -172,9 +172,9 @@ void App::run() ...@@ -172,9 +172,9 @@ void App::run()
imshow("right", right); imshow("right", right);
// Set common parameters // Set common parameters
bm.ndisp = p.ndisp; bm = gpu::createStereoBM(p.ndisp);
bp.ndisp = 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);
...@@ -201,10 +201,10 @@ void App::run() ...@@ -201,10 +201,10 @@ void App::run()
imshow("left", left); imshow("left", left);
imshow("right", right); imshow("right", right);
} }
bm(d_left, d_right, d_disp); bm->compute(d_left, d_right, d_disp);
break; break;
case Params::BP: bp(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();
...@@ -228,16 +228,16 @@ void App::printParams() const ...@@ -228,16 +228,16 @@ void App::printParams() const
switch (p.method) switch (p.method)
{ {
case Params::BM: case Params::BM:
cout << "win_size: " << bm.winSize << endl; cout << "win_size: " << bm->getBlockSize() << endl;
cout << "prefilter_sobel: " << bm.preset << endl; cout << "prefilter_sobel: " << bm->getPreFilterType() << endl;
break; break;
case Params::BP: case Params::BP:
cout << "iter_count: " << bp.iters << endl; cout << "iter_count: " << bp->getNumIters() << endl;
cout << "level_count: " << bp.levels << 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;
...@@ -289,92 +289,92 @@ void App::handleKey(char key) ...@@ -289,92 +289,92 @@ void App::handleKey(char key)
case 's': case 'S': case 's': case 'S':
if (p.method == Params::BM) if (p.method == Params::BM)
{ {
switch (bm.preset) switch (bm->getPreFilterType())
{ {
case gpu::StereoBM_GPU::BASIC_PRESET: case 0:
bm.preset = gpu::StereoBM_GPU::PREFILTER_XSOBEL; bm->setPreFilterType(cv::StereoBM::PREFILTER_XSOBEL);
break; break;
case gpu::StereoBM_GPU::PREFILTER_XSOBEL: case cv::StereoBM::PREFILTER_XSOBEL:
bm.preset = gpu::StereoBM_GPU::BASIC_PRESET; bm->setPreFilterType(0);
break; break;
} }
cout << "prefilter_sobel: " << bm.preset << endl; cout << "prefilter_sobel: " << bm->getPreFilterType() << endl;
} }
break; break;
case '1': case '1':
p.ndisp = p.ndisp == 1 ? 8 : p.ndisp + 8; p.ndisp = p.ndisp == 1 ? 8 : p.ndisp + 8;
cout << "ndisp: " << p.ndisp << endl; cout << "ndisp: " << p.ndisp << endl;
bm.ndisp = p.ndisp; bm->setNumDisparities(p.ndisp);
bp.ndisp = 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.ndisp = p.ndisp; bm->setNumDisparities(p.ndisp);
bp.ndisp = 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)
{ {
bm.winSize = min(bm.winSize + 1, 51); bm->setBlockSize(min(bm->getBlockSize() + 1, 51));
cout << "win_size: " << bm.winSize << endl; cout << "win_size: " << bm->getBlockSize() << endl;
} }
break; break;
case 'w': case 'W': case 'w': case 'W':
if (p.method == Params::BM) if (p.method == Params::BM)
{ {
bm.winSize = max(bm.winSize - 1, 2); bm->setBlockSize(max(bm->getBlockSize() - 1, 2));
cout << "win_size: " << bm.winSize << endl; cout << "win_size: " << bm->getBlockSize() << endl;
} }
break; break;
case '3': case '3':
if (p.method == Params::BP) if (p.method == Params::BP)
{ {
bp.iters += 1; bp->setNumIters(bp->getNumIters() + 1);
cout << "iter_count: " << bp.iters << endl; cout << "iter_count: " << bp->getNumIters() << endl;
} }
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':
if (p.method == Params::BP) if (p.method == Params::BP)
{ {
bp.iters = max(bp.iters - 1, 1); bp->setNumIters(max(bp->getNumIters() - 1, 1));
cout << "iter_count: " << bp.iters << endl; cout << "iter_count: " << bp->getNumIters() << endl;
} }
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':
if (p.method == Params::BP) if (p.method == Params::BP)
{ {
bp.levels += 1; bp->setNumLevels(bp->getNumLevels() + 1);
cout << "level_count: " << bp.levels << endl; cout << "level_count: " << bp->getNumLevels() << endl;
} }
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':
if (p.method == Params::BP) if (p.method == Params::BP)
{ {
bp.levels = max(bp.levels - 1, 1); bp->setNumLevels(max(bp->getNumLevels() - 1, 1));
cout << "level_count: " << bp.levels << endl; cout << "level_count: " << bp->getNumLevels() << endl;
} }
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;
} }
......
...@@ -51,7 +51,7 @@ struct Worker { void operator()(int device_id) const; }; ...@@ -51,7 +51,7 @@ struct Worker { void operator()(int device_id) const; };
// GPUs data // GPUs data
GpuMat d_left[2]; GpuMat d_left[2];
GpuMat d_right[2]; GpuMat d_right[2];
StereoBM_GPU* bm[2]; Ptr<gpu::StereoBM> bm[2];
GpuMat d_result[2]; GpuMat d_result[2];
static void printHelp() static void printHelp()
...@@ -112,13 +112,13 @@ int main(int argc, char** argv) ...@@ -112,13 +112,13 @@ int main(int argc, char** argv)
setDevice(0); setDevice(0);
d_left[0].upload(left.rowRange(0, left.rows / 2)); d_left[0].upload(left.rowRange(0, left.rows / 2));
d_right[0].upload(right.rowRange(0, right.rows / 2)); d_right[0].upload(right.rowRange(0, right.rows / 2));
bm[0] = new StereoBM_GPU(); bm[0] = gpu::createStereoBM();
// Split source images for processing on the GPU #1 // Split source images for processing on the GPU #1
setDevice(1); setDevice(1);
d_left[1].upload(left.rowRange(left.rows / 2, left.rows)); d_left[1].upload(left.rowRange(left.rows / 2, left.rows));
d_right[1].upload(right.rowRange(right.rows / 2, right.rows)); d_right[1].upload(right.rowRange(right.rows / 2, right.rows));
bm[1] = new StereoBM_GPU(); bm[1] = gpu::createStereoBM();
// Execute calculation in two threads using two GPUs // Execute calculation in two threads using two GPUs
int devices[] = {0, 1}; int devices[] = {0, 1};
...@@ -130,7 +130,7 @@ int main(int argc, char** argv) ...@@ -130,7 +130,7 @@ int main(int argc, char** argv)
d_left[0].release(); d_left[0].release();
d_right[0].release(); d_right[0].release();
d_result[0].release(); d_result[0].release();
delete bm[0]; bm[0].release();
// Release the second GPU resources // Release the second GPU resources
setDevice(1); setDevice(1);
...@@ -138,7 +138,7 @@ int main(int argc, char** argv) ...@@ -138,7 +138,7 @@ int main(int argc, char** argv)
d_left[1].release(); d_left[1].release();
d_right[1].release(); d_right[1].release();
d_result[1].release(); d_result[1].release();
delete bm[1]; bm[1].release();
waitKey(); waitKey();
return 0; return 0;
...@@ -149,8 +149,7 @@ void Worker::operator()(int device_id) const ...@@ -149,8 +149,7 @@ void Worker::operator()(int device_id) const
{ {
setDevice(device_id); setDevice(device_id);
bm[device_id]->operator()(d_left[device_id], d_right[device_id], bm[device_id]->compute(d_left[device_id], d_right[device_id], d_result[device_id]);
d_result[device_id]);
std::cout << "GPU #" << device_id << " (" << DeviceInfo().name() std::cout << "GPU #" << device_id << " (" << DeviceInfo().name()
<< "): finished\n"; << "): finished\n";
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册