refactored gpu::Canny (converted it into Algorithm)
This commit is contained in:
parent
fc8476544c
commit
48fb8c4f8a
@ -48,9 +48,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "opencv2/core/gpu.hpp"
|
#include "opencv2/core/gpu.hpp"
|
||||||
#include "opencv2/core/base.hpp"
|
|
||||||
#include "opencv2/imgproc.hpp"
|
#include "opencv2/imgproc.hpp"
|
||||||
#include "opencv2/gpufilters.hpp"
|
|
||||||
|
#if defined __GNUC__
|
||||||
|
#define __OPENCV_GPUIMGPROC_DEPR_BEFORE__
|
||||||
|
#define __OPENCV_GPUIMGPROC_DEPR_AFTER__ __attribute__ ((deprecated))
|
||||||
|
#elif (defined WIN32 || defined _WIN32)
|
||||||
|
#define __OPENCV_GPUIMGPROC_DEPR_BEFORE__ __declspec(deprecated)
|
||||||
|
#define __OPENCV_GPUIMGPROC_DEPR_AFTER__
|
||||||
|
#else
|
||||||
|
#define __OPENCV_GPUIMGPROC_DEPR_BEFORE__
|
||||||
|
#define __OPENCV_GPUIMGPROC_DEPR_AFTER__
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace cv { namespace gpu {
|
namespace cv { namespace gpu {
|
||||||
|
|
||||||
@ -172,22 +181,42 @@ static inline void histRange(InputArray src, GpuMat hist[4], const GpuMat levels
|
|||||||
|
|
||||||
//////////////////////////////// Canny ////////////////////////////////
|
//////////////////////////////// Canny ////////////////////////////////
|
||||||
|
|
||||||
struct CV_EXPORTS CannyBuf
|
class CV_EXPORTS CannyEdgeDetector : public Algorithm
|
||||||
{
|
{
|
||||||
void create(const Size& image_size, int apperture_size = 3);
|
public:
|
||||||
void release();
|
virtual void detect(InputArray image, OutputArray edges) = 0;
|
||||||
|
virtual void detect(InputArray dx, InputArray dy, OutputArray edges) = 0;
|
||||||
|
|
||||||
GpuMat dx, dy;
|
virtual void setLowThreshold(double low_thresh) = 0;
|
||||||
GpuMat mag;
|
virtual double getLowThreshold() const = 0;
|
||||||
GpuMat map;
|
|
||||||
GpuMat st1, st2;
|
virtual void setHighThreshold(double high_thresh) = 0;
|
||||||
Ptr<Filter> filterDX, filterDY;
|
virtual double getHighThreshold() const = 0;
|
||||||
|
|
||||||
|
virtual void setAppertureSize(int apperture_size) = 0;
|
||||||
|
virtual int getAppertureSize() const = 0;
|
||||||
|
|
||||||
|
virtual void setL2Gradient(bool L2gradient) = 0;
|
||||||
|
virtual bool getL2Gradient() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
CV_EXPORTS void Canny(const GpuMat& image, GpuMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
|
CV_EXPORTS Ptr<CannyEdgeDetector> createCannyEdgeDetector(double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
|
||||||
CV_EXPORTS void Canny(const GpuMat& image, CannyBuf& buf, GpuMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
|
|
||||||
CV_EXPORTS void Canny(const GpuMat& dx, const GpuMat& dy, GpuMat& edges, double low_thresh, double high_thresh, bool L2gradient = false);
|
// obsolete
|
||||||
CV_EXPORTS void Canny(const GpuMat& dx, const GpuMat& dy, CannyBuf& buf, GpuMat& edges, double low_thresh, double high_thresh, bool L2gradient = false);
|
|
||||||
|
__OPENCV_GPUIMGPROC_DEPR_BEFORE__ void Canny(InputArray image, OutputArray edges,
|
||||||
|
double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false) __OPENCV_GPUIMGPROC_DEPR_AFTER__;
|
||||||
|
inline void Canny(InputArray image, OutputArray edges, double low_thresh, double high_thresh, int apperture_size, bool L2gradient)
|
||||||
|
{
|
||||||
|
gpu::createCannyEdgeDetector(low_thresh, high_thresh, apperture_size, L2gradient)->detect(image, edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
__OPENCV_GPUIMGPROC_DEPR_BEFORE__ void Canny(InputArray dx, InputArray dy, OutputArray edges,
|
||||||
|
double low_thresh, double high_thresh, bool L2gradient = false) __OPENCV_GPUIMGPROC_DEPR_AFTER__;
|
||||||
|
inline void Canny(InputArray dx, InputArray dy, OutputArray edges, double low_thresh, double high_thresh, bool L2gradient)
|
||||||
|
{
|
||||||
|
gpu::createCannyEdgeDetector(low_thresh, high_thresh, 3, L2gradient)->detect(dx, dy, edges);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////// Hough Transform ////////////////////////////
|
/////////////////////////// Hough Transform ////////////////////////////
|
||||||
|
|
||||||
@ -209,7 +238,7 @@ struct HoughCirclesBuf
|
|||||||
GpuMat edges;
|
GpuMat edges;
|
||||||
GpuMat accum;
|
GpuMat accum;
|
||||||
GpuMat list;
|
GpuMat list;
|
||||||
CannyBuf cannyBuf;
|
Ptr<CannyEdgeDetector> canny;
|
||||||
};
|
};
|
||||||
|
|
||||||
CV_EXPORTS void HoughCircles(const GpuMat& src, GpuMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096);
|
CV_EXPORTS void HoughCircles(const GpuMat& src, GpuMat& circles, int method, float dp, float minDist, int cannyThreshold, int votesThreshold, int minRadius, int maxRadius, int maxCircles = 4096);
|
||||||
@ -224,6 +253,7 @@ class CV_EXPORTS GeneralizedHough_GPU : public cv::Algorithm
|
|||||||
public:
|
public:
|
||||||
static Ptr<GeneralizedHough_GPU> create(int method);
|
static Ptr<GeneralizedHough_GPU> create(int method);
|
||||||
|
|
||||||
|
GeneralizedHough_GPU();
|
||||||
virtual ~GeneralizedHough_GPU();
|
virtual ~GeneralizedHough_GPU();
|
||||||
|
|
||||||
//! set template to search
|
//! set template to search
|
||||||
@ -245,7 +275,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
GpuMat edges_;
|
GpuMat edges_;
|
||||||
CannyBuf cannyBuf_;
|
Ptr<CannyEdgeDetector> canny_;
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////// Corners Detection ///////////////////////////
|
////////////////////////// Corners Detection ///////////////////////////
|
||||||
@ -359,4 +389,7 @@ CV_EXPORTS void blendLinear(const GpuMat& img1, const GpuMat& img2, const GpuMat
|
|||||||
|
|
||||||
}} // namespace cv { namespace gpu {
|
}} // namespace cv { namespace gpu {
|
||||||
|
|
||||||
|
#undef __OPENCV_GPUIMGPROC_DEPR_BEFORE__
|
||||||
|
#undef __OPENCV_GPUIMGPROC_DEPR_AFTER__
|
||||||
|
|
||||||
#endif /* __OPENCV_GPUIMGPROC_HPP__ */
|
#endif /* __OPENCV_GPUIMGPROC_HPP__ */
|
||||||
|
@ -70,9 +70,10 @@ PERF_TEST_P(Image_AppertureSz_L2gradient, Canny,
|
|||||||
{
|
{
|
||||||
const cv::gpu::GpuMat d_image(image);
|
const cv::gpu::GpuMat d_image(image);
|
||||||
cv::gpu::GpuMat dst;
|
cv::gpu::GpuMat dst;
|
||||||
cv::gpu::CannyBuf d_buf;
|
|
||||||
|
|
||||||
TEST_CYCLE() cv::gpu::Canny(d_image, d_buf, dst, low_thresh, high_thresh, apperture_size, useL2gradient);
|
cv::Ptr<cv::gpu::CannyEdgeDetector> canny = cv::gpu::createCannyEdgeDetector(low_thresh, high_thresh, apperture_size, useL2gradient);
|
||||||
|
|
||||||
|
TEST_CYCLE() canny->detect(d_image, dst);
|
||||||
|
|
||||||
GPU_SANITY_CHECK(dst);
|
GPU_SANITY_CHECK(dst);
|
||||||
}
|
}
|
||||||
|
@ -47,46 +47,10 @@ using namespace cv::gpu;
|
|||||||
|
|
||||||
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
|
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
|
||||||
|
|
||||||
void cv::gpu::Canny(const GpuMat&, GpuMat&, double, double, int, bool) { throw_no_cuda(); }
|
Ptr<CannyEdgeDetector> cv::gpu::createCannyEdgeDetector(double, double, int, bool) { throw_no_cuda(); return Ptr<CannyEdgeDetector>(); }
|
||||||
void cv::gpu::Canny(const GpuMat&, CannyBuf&, GpuMat&, double, double, int, bool) { throw_no_cuda(); }
|
|
||||||
void cv::gpu::Canny(const GpuMat&, const GpuMat&, GpuMat&, double, double, bool) { throw_no_cuda(); }
|
|
||||||
void cv::gpu::Canny(const GpuMat&, const GpuMat&, CannyBuf&, GpuMat&, double, double, bool) { throw_no_cuda(); }
|
|
||||||
void cv::gpu::CannyBuf::create(const Size&, int) { throw_no_cuda(); }
|
|
||||||
void cv::gpu::CannyBuf::release() { throw_no_cuda(); }
|
|
||||||
|
|
||||||
#else /* !defined (HAVE_CUDA) */
|
#else /* !defined (HAVE_CUDA) */
|
||||||
|
|
||||||
void cv::gpu::CannyBuf::create(const Size& image_size, int apperture_size)
|
|
||||||
{
|
|
||||||
if (apperture_size > 0)
|
|
||||||
{
|
|
||||||
ensureSizeIsEnough(image_size, CV_32SC1, dx);
|
|
||||||
ensureSizeIsEnough(image_size, CV_32SC1, dy);
|
|
||||||
|
|
||||||
if (apperture_size != 3)
|
|
||||||
{
|
|
||||||
filterDX = createDerivFilter(CV_8UC1, CV_32S, 1, 0, apperture_size, false, 1, BORDER_REPLICATE);
|
|
||||||
filterDY = createDerivFilter(CV_8UC1, CV_32S, 0, 1, apperture_size, false, 1, BORDER_REPLICATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureSizeIsEnough(image_size, CV_32FC1, mag);
|
|
||||||
ensureSizeIsEnough(image_size, CV_32SC1, map);
|
|
||||||
|
|
||||||
ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st1);
|
|
||||||
ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::gpu::CannyBuf::release()
|
|
||||||
{
|
|
||||||
dx.release();
|
|
||||||
dy.release();
|
|
||||||
mag.release();
|
|
||||||
map.release();
|
|
||||||
st1.release();
|
|
||||||
st2.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace canny
|
namespace canny
|
||||||
{
|
{
|
||||||
void calcMagnitude(PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzi dx, PtrStepSzi dy, PtrStepSzf mag, bool L2Grad);
|
void calcMagnitude(PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzi dx, PtrStepSzi dy, PtrStepSzf mag, bool L2Grad);
|
||||||
@ -103,84 +67,157 @@ namespace canny
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void CannyCaller(const GpuMat& dx, const GpuMat& dy, CannyBuf& buf, GpuMat& dst, float low_thresh, float high_thresh)
|
class CannyImpl : public CannyEdgeDetector
|
||||||
{
|
{
|
||||||
using namespace canny;
|
public:
|
||||||
|
CannyImpl(double low_thresh, double high_thresh, int apperture_size, bool L2gradient) :
|
||||||
|
low_thresh_(low_thresh), high_thresh_(high_thresh), apperture_size_(apperture_size), L2gradient_(L2gradient)
|
||||||
|
{
|
||||||
|
old_apperture_size_ = -1;
|
||||||
|
}
|
||||||
|
|
||||||
buf.map.setTo(Scalar::all(0));
|
void detect(InputArray image, OutputArray edges);
|
||||||
calcMap(dx, dy, buf.mag, buf.map, low_thresh, high_thresh);
|
void detect(InputArray dx, InputArray dy, OutputArray edges);
|
||||||
|
|
||||||
edgesHysteresisLocal(buf.map, buf.st1.ptr<ushort2>());
|
void setLowThreshold(double low_thresh) { low_thresh_ = low_thresh; }
|
||||||
|
double getLowThreshold() const { return low_thresh_; }
|
||||||
|
|
||||||
edgesHysteresisGlobal(buf.map, buf.st1.ptr<ushort2>(), buf.st2.ptr<ushort2>());
|
void setHighThreshold(double high_thresh) { high_thresh_ = high_thresh; }
|
||||||
|
double getHighThreshold() const { return high_thresh_; }
|
||||||
|
|
||||||
getEdges(buf.map, dst);
|
void setAppertureSize(int apperture_size) { apperture_size_ = apperture_size; }
|
||||||
|
int getAppertureSize() const { return apperture_size_; }
|
||||||
|
|
||||||
|
void setL2Gradient(bool L2gradient) { L2gradient_ = L2gradient; }
|
||||||
|
bool getL2Gradient() const { return L2gradient_; }
|
||||||
|
|
||||||
|
void write(FileStorage& fs) const
|
||||||
|
{
|
||||||
|
fs << "name" << "Canny_GPU"
|
||||||
|
<< "low_thresh" << low_thresh_
|
||||||
|
<< "high_thresh" << high_thresh_
|
||||||
|
<< "apperture_size" << apperture_size_
|
||||||
|
<< "L2gradient" << L2gradient_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(const FileNode& fn)
|
||||||
|
{
|
||||||
|
CV_Assert( String(fn["name"]) == "Canny_GPU" );
|
||||||
|
low_thresh_ = (double)fn["low_thresh"];
|
||||||
|
high_thresh_ = (double)fn["high_thresh"];
|
||||||
|
apperture_size_ = (int)fn["apperture_size"];
|
||||||
|
L2gradient_ = (int)fn["L2gradient"] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createBuf(Size image_size);
|
||||||
|
void CannyCaller(GpuMat& edges);
|
||||||
|
|
||||||
|
double low_thresh_;
|
||||||
|
double high_thresh_;
|
||||||
|
int apperture_size_;
|
||||||
|
bool L2gradient_;
|
||||||
|
|
||||||
|
GpuMat dx_, dy_;
|
||||||
|
GpuMat mag_;
|
||||||
|
GpuMat map_;
|
||||||
|
GpuMat st1_, st2_;
|
||||||
|
Ptr<Filter> filterDX_, filterDY_;
|
||||||
|
int old_apperture_size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CannyImpl::detect(InputArray _image, OutputArray _edges)
|
||||||
|
{
|
||||||
|
GpuMat image = _image.getGpuMat();
|
||||||
|
|
||||||
|
CV_Assert( image.type() == CV_8UC1 );
|
||||||
|
CV_Assert( deviceSupports(SHARED_ATOMICS) );
|
||||||
|
|
||||||
|
if (low_thresh_ > high_thresh_)
|
||||||
|
std::swap(low_thresh_, high_thresh_);
|
||||||
|
|
||||||
|
createBuf(image.size());
|
||||||
|
|
||||||
|
_edges.create(image.size(), CV_8UC1);
|
||||||
|
GpuMat edges = _edges.getGpuMat();
|
||||||
|
|
||||||
|
if (apperture_size_ == 3)
|
||||||
|
{
|
||||||
|
Size wholeSize;
|
||||||
|
Point ofs;
|
||||||
|
image.locateROI(wholeSize, ofs);
|
||||||
|
GpuMat srcWhole(wholeSize, image.type(), image.datastart, image.step);
|
||||||
|
|
||||||
|
canny::calcMagnitude(srcWhole, ofs.x, ofs.y, dx_, dy_, mag_, L2gradient_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filterDX_->apply(image, dx_);
|
||||||
|
filterDY_->apply(image, dy_);
|
||||||
|
|
||||||
|
canny::calcMagnitude(dx_, dy_, mag_, L2gradient_);
|
||||||
|
}
|
||||||
|
|
||||||
|
CannyCaller(edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CannyImpl::detect(InputArray _dx, InputArray _dy, OutputArray _edges)
|
||||||
|
{
|
||||||
|
GpuMat dx = _dx.getGpuMat();
|
||||||
|
GpuMat dy = _dy.getGpuMat();
|
||||||
|
|
||||||
|
CV_Assert( dx.type() == CV_32SC1 );
|
||||||
|
CV_Assert( dy.type() == dx.type() && dy.size() == dx.size() );
|
||||||
|
CV_Assert( deviceSupports(SHARED_ATOMICS) );
|
||||||
|
|
||||||
|
if (low_thresh_ > high_thresh_)
|
||||||
|
std::swap(low_thresh_, high_thresh_);
|
||||||
|
|
||||||
|
createBuf(dx.size());
|
||||||
|
|
||||||
|
_edges.create(dx.size(), CV_8UC1);
|
||||||
|
GpuMat edges = _edges.getGpuMat();
|
||||||
|
|
||||||
|
canny::calcMagnitude(dx_, dy_, mag_, L2gradient_);
|
||||||
|
|
||||||
|
CannyCaller(edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CannyImpl::createBuf(Size image_size)
|
||||||
|
{
|
||||||
|
ensureSizeIsEnough(image_size, CV_32SC1, dx_);
|
||||||
|
ensureSizeIsEnough(image_size, CV_32SC1, dy_);
|
||||||
|
|
||||||
|
if (apperture_size_ != 3 && apperture_size_ != old_apperture_size_)
|
||||||
|
{
|
||||||
|
filterDX_ = gpu::createDerivFilter(CV_8UC1, CV_32S, 1, 0, apperture_size_, false, 1, BORDER_REPLICATE);
|
||||||
|
filterDY_ = gpu::createDerivFilter(CV_8UC1, CV_32S, 0, 1, apperture_size_, false, 1, BORDER_REPLICATE);
|
||||||
|
old_apperture_size_ = apperture_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureSizeIsEnough(image_size, CV_32FC1, mag_);
|
||||||
|
ensureSizeIsEnough(image_size, CV_32SC1, map_);
|
||||||
|
|
||||||
|
ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st1_);
|
||||||
|
ensureSizeIsEnough(1, image_size.area(), CV_16UC2, st2_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CannyImpl::CannyCaller(GpuMat& edges)
|
||||||
|
{
|
||||||
|
map_.setTo(Scalar::all(0));
|
||||||
|
canny::calcMap(dx_, dy_, mag_, map_, static_cast<float>(low_thresh_), static_cast<float>(high_thresh_));
|
||||||
|
|
||||||
|
canny::edgesHysteresisLocal(map_, st1_.ptr<ushort2>());
|
||||||
|
|
||||||
|
canny::edgesHysteresisGlobal(map_, st1_.ptr<ushort2>(), st2_.ptr<ushort2>());
|
||||||
|
|
||||||
|
canny::getEdges(map_, edges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cv::gpu::Canny(const GpuMat& src, GpuMat& dst, double low_thresh, double high_thresh, int apperture_size, bool L2gradient)
|
Ptr<CannyEdgeDetector> cv::gpu::createCannyEdgeDetector(double low_thresh, double high_thresh, int apperture_size, bool L2gradient)
|
||||||
{
|
{
|
||||||
CannyBuf buf;
|
return new CannyImpl(low_thresh, high_thresh, apperture_size, L2gradient);
|
||||||
Canny(src, buf, dst, low_thresh, high_thresh, apperture_size, L2gradient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::gpu::Canny(const GpuMat& src, CannyBuf& buf, GpuMat& dst, double low_thresh, double high_thresh, int apperture_size, bool L2gradient)
|
|
||||||
{
|
|
||||||
using namespace canny;
|
|
||||||
|
|
||||||
CV_Assert(src.type() == CV_8UC1);
|
|
||||||
|
|
||||||
if (!deviceSupports(SHARED_ATOMICS))
|
|
||||||
CV_Error(cv::Error::StsNotImplemented, "The device doesn't support shared atomics");
|
|
||||||
|
|
||||||
if( low_thresh > high_thresh )
|
|
||||||
std::swap( low_thresh, high_thresh);
|
|
||||||
|
|
||||||
dst.create(src.size(), CV_8U);
|
|
||||||
buf.create(src.size(), apperture_size);
|
|
||||||
|
|
||||||
if (apperture_size == 3)
|
|
||||||
{
|
|
||||||
Size wholeSize;
|
|
||||||
Point ofs;
|
|
||||||
src.locateROI(wholeSize, ofs);
|
|
||||||
GpuMat srcWhole(wholeSize, src.type(), src.datastart, src.step);
|
|
||||||
|
|
||||||
calcMagnitude(srcWhole, ofs.x, ofs.y, buf.dx, buf.dy, buf.mag, L2gradient);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf.filterDX->apply(src, buf.dx);
|
|
||||||
buf.filterDY->apply(src, buf.dy);
|
|
||||||
|
|
||||||
calcMagnitude(buf.dx, buf.dy, buf.mag, L2gradient);
|
|
||||||
}
|
|
||||||
|
|
||||||
CannyCaller(buf.dx, buf.dy, buf, dst, static_cast<float>(low_thresh), static_cast<float>(high_thresh));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::gpu::Canny(const GpuMat& dx, const GpuMat& dy, GpuMat& dst, double low_thresh, double high_thresh, bool L2gradient)
|
|
||||||
{
|
|
||||||
CannyBuf buf;
|
|
||||||
Canny(dx, dy, buf, dst, low_thresh, high_thresh, L2gradient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::gpu::Canny(const GpuMat& dx, const GpuMat& dy, CannyBuf& buf, GpuMat& dst, double low_thresh, double high_thresh, bool L2gradient)
|
|
||||||
{
|
|
||||||
using namespace canny;
|
|
||||||
|
|
||||||
CV_Assert(TargetArchs::builtWith(SHARED_ATOMICS) && DeviceInfo().supports(SHARED_ATOMICS));
|
|
||||||
CV_Assert(dx.type() == CV_32SC1 && dy.type() == CV_32SC1 && dx.size() == dy.size());
|
|
||||||
|
|
||||||
if( low_thresh > high_thresh )
|
|
||||||
std::swap( low_thresh, high_thresh);
|
|
||||||
|
|
||||||
dst.create(dx.size(), CV_8U);
|
|
||||||
buf.create(dx.size(), -1);
|
|
||||||
|
|
||||||
calcMagnitude(dx, dy, buf.mag, L2gradient);
|
|
||||||
|
|
||||||
CannyCaller(dx, dy, buf, dst, static_cast<float>(low_thresh), static_cast<float>(high_thresh));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !defined (HAVE_CUDA) */
|
#endif /* !defined (HAVE_CUDA) */
|
||||||
|
@ -244,7 +244,8 @@ void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, HoughCirclesBuf&
|
|||||||
|
|
||||||
const float idp = 1.0f / dp;
|
const float idp = 1.0f / dp;
|
||||||
|
|
||||||
cv::gpu::Canny(src, buf.cannyBuf, buf.edges, std::max(cannyThreshold / 2, 1), cannyThreshold);
|
buf.canny = gpu::createCannyEdgeDetector(std::max(cannyThreshold / 2, 1), cannyThreshold);
|
||||||
|
buf.canny->detect(src, buf.edges);
|
||||||
|
|
||||||
ensureSizeIsEnough(2, src.size().area(), CV_32SC1, buf.list);
|
ensureSizeIsEnough(2, src.size().area(), CV_32SC1, buf.list);
|
||||||
unsigned int* srcPoints = buf.list.ptr<unsigned int>(0);
|
unsigned int* srcPoints = buf.list.ptr<unsigned int>(0);
|
||||||
@ -260,7 +261,13 @@ void cv::gpu::HoughCircles(const GpuMat& src, GpuMat& circles, HoughCirclesBuf&
|
|||||||
ensureSizeIsEnough(cvCeil(src.rows * idp) + 2, cvCeil(src.cols * idp) + 2, CV_32SC1, buf.accum);
|
ensureSizeIsEnough(cvCeil(src.rows * idp) + 2, cvCeil(src.cols * idp) + 2, CV_32SC1, buf.accum);
|
||||||
buf.accum.setTo(Scalar::all(0));
|
buf.accum.setTo(Scalar::all(0));
|
||||||
|
|
||||||
circlesAccumCenters_gpu(srcPoints, pointsCount, buf.cannyBuf.dx, buf.cannyBuf.dy, buf.accum, minRadius, maxRadius, idp);
|
Ptr<gpu::Filter> filterDX = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0);
|
||||||
|
Ptr<gpu::Filter> filterDY = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1);
|
||||||
|
GpuMat dx, dy;
|
||||||
|
filterDX->apply(src, dx);
|
||||||
|
filterDY->apply(src, dy);
|
||||||
|
|
||||||
|
circlesAccumCenters_gpu(srcPoints, pointsCount, dx, dy, buf.accum, minRadius, maxRadius, idp);
|
||||||
|
|
||||||
int centersCount = buildCentersList_gpu(buf.accum, centers, votesThreshold);
|
int centersCount = buildCentersList_gpu(buf.accum, centers, votesThreshold);
|
||||||
if (centersCount == 0)
|
if (centersCount == 0)
|
||||||
@ -1355,6 +1362,11 @@ Ptr<GeneralizedHough_GPU> cv::gpu::GeneralizedHough_GPU::create(int method)
|
|||||||
return Ptr<GeneralizedHough_GPU>();
|
return Ptr<GeneralizedHough_GPU>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cv::gpu::GeneralizedHough_GPU::GeneralizedHough_GPU()
|
||||||
|
{
|
||||||
|
canny_ = gpu::createCannyEdgeDetector(50, 100);
|
||||||
|
}
|
||||||
|
|
||||||
cv::gpu::GeneralizedHough_GPU::~GeneralizedHough_GPU()
|
cv::gpu::GeneralizedHough_GPU::~GeneralizedHough_GPU()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -1365,12 +1377,21 @@ void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat& templ, int cannyTh
|
|||||||
CV_Assert(cannyThreshold > 0);
|
CV_Assert(cannyThreshold > 0);
|
||||||
|
|
||||||
ensureSizeIsEnough(templ.size(), CV_8UC1, edges_);
|
ensureSizeIsEnough(templ.size(), CV_8UC1, edges_);
|
||||||
Canny(templ, cannyBuf_, edges_, cannyThreshold / 2, cannyThreshold);
|
|
||||||
|
canny_->setLowThreshold(cannyThreshold / 2);
|
||||||
|
canny_->setHighThreshold(cannyThreshold);
|
||||||
|
canny_->detect(templ, edges_);
|
||||||
|
|
||||||
if (templCenter == Point(-1, -1))
|
if (templCenter == Point(-1, -1))
|
||||||
templCenter = Point(templ.cols / 2, templ.rows / 2);
|
templCenter = Point(templ.cols / 2, templ.rows / 2);
|
||||||
|
|
||||||
setTemplateImpl(edges_, cannyBuf_.dx, cannyBuf_.dy, templCenter);
|
Ptr<gpu::Filter> filterDX = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0);
|
||||||
|
Ptr<gpu::Filter> filterDY = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1);
|
||||||
|
GpuMat dx, dy;
|
||||||
|
filterDX->apply(templ, dx);
|
||||||
|
filterDY->apply(templ, dy);
|
||||||
|
|
||||||
|
setTemplateImpl(edges_, dx, dy, templCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter)
|
void cv::gpu::GeneralizedHough_GPU::setTemplate(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, Point templCenter)
|
||||||
@ -1387,9 +1408,18 @@ void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat& image, GpuMat& position
|
|||||||
CV_Assert(cannyThreshold > 0);
|
CV_Assert(cannyThreshold > 0);
|
||||||
|
|
||||||
ensureSizeIsEnough(image.size(), CV_8UC1, edges_);
|
ensureSizeIsEnough(image.size(), CV_8UC1, edges_);
|
||||||
Canny(image, cannyBuf_, edges_, cannyThreshold / 2, cannyThreshold);
|
|
||||||
|
|
||||||
detectImpl(edges_, cannyBuf_.dx, cannyBuf_.dy, positions);
|
canny_->setLowThreshold(cannyThreshold / 2);
|
||||||
|
canny_->setHighThreshold(cannyThreshold);
|
||||||
|
canny_->detect(image, edges_);
|
||||||
|
|
||||||
|
Ptr<gpu::Filter> filterDX = gpu::createSobelFilter(CV_8UC1, CV_32S, 1, 0);
|
||||||
|
Ptr<gpu::Filter> filterDY = gpu::createSobelFilter(CV_8UC1, CV_32S, 0, 1);
|
||||||
|
GpuMat dx, dy;
|
||||||
|
filterDX->apply(image, dx);
|
||||||
|
filterDY->apply(image, dy);
|
||||||
|
|
||||||
|
detectImpl(edges_, dx, dy, positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions)
|
void cv::gpu::GeneralizedHough_GPU::detect(const GpuMat& edges, const GpuMat& dx, const GpuMat& dy, GpuMat& positions)
|
||||||
@ -1425,7 +1455,6 @@ void cv::gpu::GeneralizedHough_GPU::download(const GpuMat& d_positions, OutputAr
|
|||||||
void cv::gpu::GeneralizedHough_GPU::release()
|
void cv::gpu::GeneralizedHough_GPU::release()
|
||||||
{
|
{
|
||||||
edges_.release();
|
edges_.release();
|
||||||
cannyBuf_.release();
|
|
||||||
releaseImpl();
|
releaseImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,28 +81,15 @@ GPU_TEST_P(Canny, Accuracy)
|
|||||||
double low_thresh = 50.0;
|
double low_thresh = 50.0;
|
||||||
double high_thresh = 100.0;
|
double high_thresh = 100.0;
|
||||||
|
|
||||||
if (!supportFeature(devInfo, cv::gpu::SHARED_ATOMICS))
|
cv::Ptr<cv::gpu::CannyEdgeDetector> canny = cv::gpu::createCannyEdgeDetector(low_thresh, high_thresh, apperture_size, useL2gradient);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
cv::gpu::GpuMat edges;
|
|
||||||
cv::gpu::Canny(loadMat(img), edges, low_thresh, high_thresh, apperture_size, useL2gradient);
|
|
||||||
}
|
|
||||||
catch (const cv::Exception& e)
|
|
||||||
{
|
|
||||||
ASSERT_EQ(cv::Error::StsNotImplemented, e.code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv::gpu::GpuMat edges;
|
|
||||||
cv::gpu::Canny(loadMat(img, useRoi), edges, low_thresh, high_thresh, apperture_size, useL2gradient);
|
|
||||||
|
|
||||||
cv::Mat edges_gold;
|
cv::gpu::GpuMat edges;
|
||||||
cv::Canny(img, edges_gold, low_thresh, high_thresh, apperture_size, useL2gradient);
|
canny->detect(loadMat(img, useRoi), edges);
|
||||||
|
|
||||||
EXPECT_MAT_SIMILAR(edges_gold, edges, 2e-2);
|
cv::Mat edges_gold;
|
||||||
}
|
cv::Canny(img, edges_gold, low_thresh, high_thresh, apperture_size, useL2gradient);
|
||||||
|
|
||||||
|
EXPECT_MAT_SIMILAR(edges_gold, edges, 2e-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(GPU_ImgProc, Canny, testing::Combine(
|
INSTANTIATE_TEST_CASE_P(GPU_ImgProc, Canny, testing::Combine(
|
||||||
|
@ -31,7 +31,7 @@ int main(int argc, const char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mat mask;
|
Mat mask;
|
||||||
Canny(src, mask, 100, 200, 3);
|
cv::Canny(src, mask, 100, 200, 3);
|
||||||
|
|
||||||
Mat dst_cpu;
|
Mat dst_cpu;
|
||||||
cv::cvtColor(mask, dst_cpu, COLOR_GRAY2BGR);
|
cv::cvtColor(mask, dst_cpu, COLOR_GRAY2BGR);
|
||||||
|
@ -1072,12 +1072,13 @@ TEST(Canny)
|
|||||||
|
|
||||||
gpu::GpuMat d_img(img);
|
gpu::GpuMat d_img(img);
|
||||||
gpu::GpuMat d_edges;
|
gpu::GpuMat d_edges;
|
||||||
gpu::CannyBuf d_buf;
|
|
||||||
|
|
||||||
gpu::Canny(d_img, d_buf, d_edges, 50.0, 100.0);
|
Ptr<gpu::CannyEdgeDetector> canny = gpu::createCannyEdgeDetector(50.0, 100.0);
|
||||||
|
|
||||||
|
canny->detect(d_img, d_edges);
|
||||||
|
|
||||||
GPU_ON;
|
GPU_ON;
|
||||||
gpu::Canny(d_img, d_buf, d_edges, 50.0, 100.0);
|
canny->detect(d_img, d_edges);
|
||||||
GPU_OFF;
|
GPU_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user