Commit 7992402e authored by Roman Donchenko's avatar Roman Donchenko Committed by OpenCV Buildbot

Merge pull request #1149 from jet47:generalized-hough-refactoring

parents 18358521 7b87d72d
......@@ -216,98 +216,19 @@ Creates implementation for :ocv:class:`gpu::HoughCirclesDetector` .
gpu::GeneralizedHough
---------------------
.. ocv:class:: gpu::GeneralizedHough : public Algorithm
Base class for generalized hough transform. ::
class CV_EXPORTS GeneralizedHough : public Algorithm
{
public:
static Ptr<GeneralizedHough> create(int method);
virtual void setTemplate(InputArray templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1)) = 0;
virtual void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1)) = 0;
virtual void detect(InputArray image, OutputArray positions, int cannyThreshold = 100) = 0;
virtual void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions) = 0;
virtual void downloadResults(InputArray d_positions, OutputArray h_positions, OutputArray h_votes = noArray()) = 0;
};
Finds arbitrary template in the grayscale image using Generalized Hough Transform.
gpu::GeneralizedHough::create
-----------------------------
Creates implementation for :ocv:class:`gpu::GeneralizedHough` .
.. ocv:function:: Ptr<GeneralizedHough> gpu::GeneralizedHough::create(int method)
:param method: Combination of flags ( ``cv::GeneralizedHough::GHT_POSITION`` , ``cv::GeneralizedHough::GHT_SCALE`` , ``cv::GeneralizedHough::GHT_ROTATION`` ) specifying transformation to find.
For full affine transformations (move + scale + rotation) [Guil1999]_ algorithm is used, otherwise [Ballard1981]_ algorithm is used.
gpu::GeneralizedHough::setTemplate
gpu::createGeneralizedHoughBallard
----------------------------------
Set template to search.
.. ocv:function:: void gpu::GeneralizedHough::setTemplate(InputArray templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1))
.. ocv:function:: void gpu::GeneralizedHough::setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1))
Creates implementation for generalized hough transform from [Ballard1981]_ .
:param templ: Template image. Canny edge detector will be applied to extract template edges.
.. ocv:function:: Ptr<GeneralizedHoughBallard> gpu::createGeneralizedHoughBallard()
:param cannyThreshold: Threshold value for Canny edge detector.
:param templCenter: Center for rotation. By default image center will be used.
:param edges: Edge map for template image.
:param dx: First derivative of template image in the vertical direction. Support only ``CV_32S`` type.
:param dy: First derivative of template image in the horizontal direction. Support only ``CV_32S`` type.
gpu::GeneralizedHough::detect
-----------------------------
Finds template (set by :ocv:func:`gpu::GeneralizedHough::setTemplate` ) in the grayscale image.
.. ocv:function:: void gpu::GeneralizedHough::detect(InputArray image, OutputArray positions, int cannyThreshold = 100)
.. ocv:function:: void gpu::GeneralizedHough::detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions)
:param templ: Input image. Canny edge detector will be applied to extract template edges.
:param positions: Output vector of found objects. Each vector is encoded as a 4-element floating-point vector :math:`(x, y, scale, angle)` .
:param cannyThreshold: Threshold value for Canny edge detector.
:param edges: Edge map for input image.
:param dx: First derivative of input image in the vertical direction. Support only ``CV_32S`` type.
:param dy: First derivative of input image in the horizontal direction. Support only ``CV_32S`` type.
gpu::GeneralizedHough::downloadResults
--------------------------------------
Downloads results from :ocv:func:`gpu::GeneralizedHough::detect` to host memory.
.. ocv:function:: void gpu::GeneralizedHough::downloadResult(InputArray d_positions, OutputArray h_positions, OutputArray h_votes = noArray())
:param d_lines: Result of :ocv:func:`gpu::GeneralizedHough::detect` .
:param h_lines: Output host array.
gpu::createGeneralizedHoughGuil
-------------------------------
Creates implementation for generalized hough transform from [Guil1999]_ .
:param h_votes: Optional output array for votes. Each vector is encoded as a 3-element integer-point vector :math:`(position_votes, scale_votes, angle_votes)` .
.. ocv:function:: Ptr<GeneralizedHoughGuil> gpu::createGeneralizedHoughGuil()
......
......@@ -283,24 +283,13 @@ CV_EXPORTS Ptr<HoughCirclesDetector> createHoughCirclesDetector(float dp, float
//////////////////////////////////////
// GeneralizedHough
//! finds arbitrary template in the grayscale image using Generalized Hough Transform
//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122.
//! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038.
class CV_EXPORTS GeneralizedHough : public Algorithm
{
public:
static Ptr<GeneralizedHough> create(int method);
//! set template to search
virtual void setTemplate(InputArray templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1)) = 0;
virtual void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1)) = 0;
//! Detects position only without traslation and rotation
CV_EXPORTS Ptr<GeneralizedHoughBallard> createGeneralizedHoughBallard();
//! find template on image
virtual void detect(InputArray image, OutputArray positions, int cannyThreshold = 100) = 0;
virtual void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions) = 0;
virtual void downloadResults(InputArray d_positions, OutputArray h_positions, OutputArray h_votes = noArray()) = 0;
};
//! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038.
//! Detects position, traslation and rotation
CV_EXPORTS Ptr<GeneralizedHoughGuil> createGeneralizedHoughGuil();
////////////////////////// Corners Detection ///////////////////////////
......
......@@ -227,23 +227,59 @@ PERF_TEST_P(Sz_Dp_MinDist, HoughCircles,
//////////////////////////////////////////////////////////////////////
// GeneralizedHough
enum { GHT_POSITION = cv::GeneralizedHough::GHT_POSITION,
GHT_SCALE = cv::GeneralizedHough::GHT_SCALE,
GHT_ROTATION = cv::GeneralizedHough::GHT_ROTATION
};
PERF_TEST_P(Sz, GeneralizedHoughBallard, GPU_TYPICAL_MAT_SIZES)
{
declare.time(10);
const cv::Size imageSize = GetParam();
const cv::Mat templ = readImage("cv/shared/templ.png", cv::IMREAD_GRAYSCALE);
ASSERT_FALSE(templ.empty());
cv::Mat image(imageSize, CV_8UC1, cv::Scalar::all(0));
templ.copyTo(image(cv::Rect(50, 50, templ.cols, templ.rows)));
cv::Mat edges;
cv::Canny(image, edges, 50, 100);
cv::Mat dx, dy;
cv::Sobel(image, dx, CV_32F, 1, 0);
cv::Sobel(image, dy, CV_32F, 0, 1);
if (PERF_RUN_GPU())
{
cv::Ptr<cv::GeneralizedHoughBallard> alg = cv::gpu::createGeneralizedHoughBallard();
const cv::gpu::GpuMat d_edges(edges);
const cv::gpu::GpuMat d_dx(dx);
const cv::gpu::GpuMat d_dy(dy);
cv::gpu::GpuMat positions;
alg->setTemplate(cv::gpu::GpuMat(templ));
TEST_CYCLE() alg->detect(d_edges, d_dx, d_dy, positions);
GPU_SANITY_CHECK(positions);
}
else
{
cv::Ptr<cv::GeneralizedHoughBallard> alg = cv::createGeneralizedHoughBallard();
cv::Mat positions;
alg->setTemplate(templ);
CV_FLAGS(GHMethod, GHT_POSITION, GHT_SCALE, GHT_ROTATION);
TEST_CYCLE() alg->detect(edges, dx, dy, positions);
DEF_PARAM_TEST(Method_Sz, GHMethod, cv::Size);
CPU_SANITY_CHECK(positions);
}
}
PERF_TEST_P(Method_Sz, GeneralizedHough,
Combine(Values(GHMethod(GHT_POSITION), GHMethod(GHT_POSITION | GHT_SCALE), GHMethod(GHT_POSITION | GHT_ROTATION), GHMethod(GHT_POSITION | GHT_SCALE | GHT_ROTATION)),
GPU_TYPICAL_MAT_SIZES))
PERF_TEST_P(Sz, GeneralizedHoughGuil, GPU_TYPICAL_MAT_SIZES)
{
declare.time(10);
const int method = GET_PARAM(0);
const cv::Size imageSize = GET_PARAM(1);
const cv::Size imageSize = GetParam();
const cv::Mat templ = readImage("cv/shared/templ.png", cv::IMREAD_GRAYSCALE);
ASSERT_FALSE(templ.empty());
......@@ -281,39 +317,32 @@ PERF_TEST_P(Method_Sz, GeneralizedHough,
if (PERF_RUN_GPU())
{
cv::Ptr<cv::GeneralizedHoughGuil> alg = cv::gpu::createGeneralizedHoughGuil();
alg->setMaxAngle(90.0);
alg->setAngleStep(2.0);
const cv::gpu::GpuMat d_edges(edges);
const cv::gpu::GpuMat d_dx(dx);
const cv::gpu::GpuMat d_dy(dy);
cv::gpu::GpuMat posAndVotes;
cv::gpu::GpuMat positions;
cv::Ptr<cv::gpu::GeneralizedHough> d_hough = cv::gpu::GeneralizedHough::create(method);
if (method & GHT_ROTATION)
{
d_hough->set("maxAngle", 90.0);
d_hough->set("angleStep", 2.0);
}
alg->setTemplate(cv::gpu::GpuMat(templ));
d_hough->setTemplate(cv::gpu::GpuMat(templ));
TEST_CYCLE() alg->detect(d_edges, d_dx, d_dy, positions);
TEST_CYCLE() d_hough->detect(d_edges, d_dx, d_dy, posAndVotes);
const cv::gpu::GpuMat positions(1, posAndVotes.cols, CV_32FC4, posAndVotes.data);
GPU_SANITY_CHECK(positions);
}
else
{
cv::Mat positions;
cv::Ptr<cv::GeneralizedHoughGuil> alg = cv::createGeneralizedHoughGuil();
alg->setMaxAngle(90.0);
alg->setAngleStep(2.0);
cv::Ptr<cv::GeneralizedHough> hough = cv::GeneralizedHough::create(method);
if (method & GHT_ROTATION)
{
hough->set("maxAngle", 90.0);
hough->set("angleStep", 2.0);
}
cv::Mat positions;
hough->setTemplate(templ);
alg->setTemplate(templ);
TEST_CYCLE() hough->detect(edges, dx, dy, positions);
TEST_CYCLE() alg->detect(edges, dx, dy, positions);
CPU_SANITY_CHECK(positions);
}
......
......@@ -193,7 +193,7 @@ PARAM_TEST_CASE(GeneralizedHough, cv::gpu::DeviceInfo, UseRoi)
{
};
GPU_TEST_P(GeneralizedHough, POSITION)
GPU_TEST_P(GeneralizedHough, Ballard)
{
const cv::gpu::DeviceInfo devInfo = GET_PARAM(0);
cv::gpu::setDevice(devInfo.deviceID());
......@@ -218,16 +218,16 @@ GPU_TEST_P(GeneralizedHough, POSITION)
templ.copyTo(imageROI);
}
cv::Ptr<cv::gpu::GeneralizedHough> hough = cv::gpu::GeneralizedHough::create(cv::GeneralizedHough::GHT_POSITION);
hough->set("votesThreshold", 200);
cv::Ptr<cv::GeneralizedHoughBallard> alg = cv::gpu::createGeneralizedHoughBallard();
alg->setVotesThreshold(200);
hough->setTemplate(loadMat(templ, useRoi));
alg->setTemplate(loadMat(templ, useRoi));
cv::gpu::GpuMat d_pos;
hough->detect(loadMat(image, useRoi), d_pos);
alg->detect(loadMat(image, useRoi), d_pos);
std::vector<cv::Vec4f> pos;
hough->downloadResults(d_pos, pos);
d_pos.download(pos);
ASSERT_EQ(gold_count, pos.size());
......
......@@ -694,39 +694,104 @@ public:
//! finds arbitrary template in the grayscale image using Generalized Hough Transform
class CV_EXPORTS GeneralizedHough : public Algorithm
{
public:
//! set template to search
virtual void setTemplate(InputArray templ, Point templCenter = Point(-1, -1)) = 0;
virtual void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1)) = 0;
//! find template on image
virtual void detect(InputArray image, OutputArray positions, OutputArray votes = noArray()) = 0;
virtual void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions, OutputArray votes = noArray()) = 0;
//! Canny low threshold.
virtual void setCannyLowThresh(int cannyLowThresh) = 0;
virtual int getCannyLowThresh() const = 0;
//! Canny high threshold.
virtual void setCannyHighThresh(int cannyHighThresh) = 0;
virtual int getCannyHighThresh() const = 0;
//! Minimum distance between the centers of the detected objects.
virtual void setMinDist(double minDist) = 0;
virtual double getMinDist() const = 0;
//! Inverse ratio of the accumulator resolution to the image resolution.
virtual void setDp(double dp) = 0;
virtual double getDp() const = 0;
//! Maximal size of inner buffers.
virtual void setMaxBufferSize(int maxBufferSize) = 0;
virtual int getMaxBufferSize() const = 0;
};
//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122.
//! Detects position only without traslation and rotation
class CV_EXPORTS GeneralizedHoughBallard : public GeneralizedHough
{
public:
//! R-Table levels.
virtual void setLevels(int levels) = 0;
virtual int getLevels() const = 0;
//! The accumulator threshold for the template centers at the detection stage. The smaller it is, the more false positions may be detected.
virtual void setVotesThreshold(int votesThreshold) = 0;
virtual int getVotesThreshold() const = 0;
};
//! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038.
class CV_EXPORTS GeneralizedHough : public Algorithm
//! Detects position, traslation and rotation
class CV_EXPORTS GeneralizedHoughGuil : public GeneralizedHough
{
public:
enum { GHT_POSITION = 0,
GHT_SCALE = 1,
GHT_ROTATION = 2
};
//! Angle difference in degrees between two points in feature.
virtual void setXi(double xi) = 0;
virtual double getXi() const = 0;
static Ptr<GeneralizedHough> create(int method);
//! Feature table levels.
virtual void setLevels(int levels) = 0;
virtual int getLevels() const = 0;
virtual ~GeneralizedHough();
//! Maximal difference between angles that treated as equal.
virtual void setAngleEpsilon(double angleEpsilon) = 0;
virtual double getAngleEpsilon() const = 0;
//! set template to search
void setTemplate(InputArray templ, int cannyThreshold = 100, Point templCenter = Point(-1, -1));
void setTemplate(InputArray edges, InputArray dx, InputArray dy, Point templCenter = Point(-1, -1));
//! Minimal rotation angle to detect in degrees.
virtual void setMinAngle(double minAngle) = 0;
virtual double getMinAngle() const = 0;
//! find template on image
void detect(InputArray image, OutputArray positions, OutputArray votes = cv::noArray(), int cannyThreshold = 100);
void detect(InputArray edges, InputArray dx, InputArray dy, OutputArray positions, OutputArray votes = cv::noArray());
//! Maximal rotation angle to detect in degrees.
virtual void setMaxAngle(double maxAngle) = 0;
virtual double getMaxAngle() const = 0;
void release();
//! Angle step in degrees.
virtual void setAngleStep(double angleStep) = 0;
virtual double getAngleStep() const = 0;
protected:
virtual void setTemplateImpl(const Mat& edges, const Mat& dx, const Mat& dy, Point templCenter) = 0;
virtual void detectImpl(const Mat& edges, const Mat& dx, const Mat& dy, OutputArray positions, OutputArray votes) = 0;
virtual void releaseImpl() = 0;
private:
Mat edges_;
Mat dx_;
Mat dy_;
//! Angle votes threshold.
virtual void setAngleThresh(int angleThresh) = 0;
virtual int getAngleThresh() const = 0;
//! Minimal scale to detect.
virtual void setMinScale(double minScale) = 0;
virtual double getMinScale() const = 0;
//! Maximal scale to detect.
virtual void setMaxScale(double maxScale) = 0;
virtual double getMaxScale() const = 0;
//! Scale step.
virtual void setScaleStep(double scaleStep) = 0;
virtual double getScaleStep() const = 0;
//! Scale votes threshold.
virtual void setScaleThresh(int scaleThresh) = 0;
virtual int getScaleThresh() const = 0;
//! Position votes threshold.
virtual void setPosThresh(int posThresh) = 0;
virtual int getPosThresh() const = 0;
};
......@@ -1416,6 +1481,14 @@ CV_EXPORTS_W double pointPolygonTest( InputArray contour, Point2f pt, bool measu
CV_EXPORTS Ptr<CLAHE> createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8));
//! Ballard, D.H. (1981). Generalizing the Hough transform to detect arbitrary shapes. Pattern Recognition 13 (2): 111-122.
//! Detects position only without traslation and rotation
CV_EXPORTS Ptr<GeneralizedHoughBallard> createGeneralizedHoughBallard();
//! Guil, N., González-Linares, J.M. and Zapata, E.L. (1999). Bidimensional shape detection using an invariant approach. Pattern Recognition 32 (6): 1025-1038.
//! Detects position, traslation and rotation
CV_EXPORTS Ptr<GeneralizedHoughGuil> createGeneralizedHoughGuil();
} // cv
#endif
This diff is collapsed.
......@@ -5,13 +5,12 @@
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/gpu.hpp"
#include "opencv2/gpuimgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/contrib.hpp"
using namespace std;
using namespace cv;
using cv::gpu::GpuMat;
static Mat loadImage(const string& name)
{
......@@ -29,8 +28,7 @@ int main(int argc, const char* argv[])
CommandLineParser cmd(argc, argv,
"{ image i | pic1.png | input image }"
"{ template t | templ.png | template image }"
"{ scale s | | estimate scale }"
"{ rotation r | | estimate rotation }"
"{ full | | estimate scale and rotation }"
"{ gpu | | use gpu version }"
"{ minDist | 100 | minimum distance between the centers of the detected objects }"
"{ levels | 360 | R-Table levels }"
......@@ -45,7 +43,7 @@ int main(int argc, const char* argv[])
"{ minAngle | 0 | minimal rotation angle to detect in degrees }"
"{ maxAngle | 360 | maximal rotation angle to detect in degrees }"
"{ angleStep | 1 | angle step in degrees }"
"{ maxSize | 1000 | maximal size of inner buffers }"
"{ maxBufSize | 1000 | maximal size of inner buffers }"
"{ help h ? | | print help message }"
);
......@@ -59,8 +57,7 @@ int main(int argc, const char* argv[])
const string templName = cmd.get<string>("template");
const string imageName = cmd.get<string>("image");
const bool estimateScale = cmd.has("scale");
const bool estimateRotation = cmd.has("rotation");
const bool full = cmd.has("full");
const bool useGpu = cmd.has("gpu");
const double minDist = cmd.get<double>("minDist");
const int levels = cmd.get<int>("levels");
......@@ -75,7 +72,7 @@ int main(int argc, const char* argv[])
const double minAngle = cmd.get<double>("minAngle");
const double maxAngle = cmd.get<double>("maxAngle");
const double angleStep = cmd.get<double>("angleStep");
const int maxSize = cmd.get<int>("maxSize");
const int maxBufSize = cmd.get<int>("maxBufSize");
if (!cmd.check())
{
......@@ -86,93 +83,69 @@ int main(int argc, const char* argv[])
Mat templ = loadImage(templName);
Mat image = loadImage(imageName);
int method = cv::GeneralizedHough::GHT_POSITION;
if (estimateScale)
method += cv::GeneralizedHough::GHT_SCALE;
if (estimateRotation)
method += cv::GeneralizedHough::GHT_ROTATION;
Ptr<GeneralizedHough> alg;
if (!full)
{
Ptr<GeneralizedHoughBallard> ballard = useGpu ? gpu::createGeneralizedHoughBallard() : createGeneralizedHoughBallard();
ballard->setMinDist(minDist);
ballard->setLevels(levels);
ballard->setDp(dp);
ballard->setMaxBufferSize(maxBufSize);
ballard->setVotesThreshold(votesThreshold);
alg = ballard;
}
else
{
Ptr<GeneralizedHoughGuil> guil = useGpu ? gpu::createGeneralizedHoughGuil() : createGeneralizedHoughGuil();
guil->setMinDist(minDist);
guil->setLevels(levels);
guil->setDp(dp);
guil->setMaxBufferSize(maxBufSize);
guil->setMinAngle(minAngle);
guil->setMaxAngle(maxAngle);
guil->setAngleStep(angleStep);
guil->setAngleThresh(angleThresh);
guil->setMinScale(minScale);
guil->setMaxScale(maxScale);
guil->setScaleStep(scaleStep);
guil->setScaleThresh(scaleThresh);
guil->setPosThresh(posThresh);
alg = guil;
}
vector<Vec4f> position;
cv::TickMeter tm;
TickMeter tm;
if (useGpu)
{
GpuMat d_templ(templ);
GpuMat d_image(image);
GpuMat d_position;
Ptr<gpu::GeneralizedHough> d_hough = gpu::GeneralizedHough::create(method);
d_hough->set("minDist", minDist);
d_hough->set("levels", levels);
d_hough->set("dp", dp);
d_hough->set("maxSize", maxSize);
if (estimateScale && estimateRotation)
{
d_hough->set("angleThresh", angleThresh);
d_hough->set("scaleThresh", scaleThresh);
d_hough->set("posThresh", posThresh);
}
else
{
d_hough->set("votesThreshold", votesThreshold);
}
if (estimateScale)
{
d_hough->set("minScale", minScale);
d_hough->set("maxScale", maxScale);
d_hough->set("scaleStep", scaleStep);
}
if (estimateRotation)
{
d_hough->set("minAngle", minAngle);
d_hough->set("maxAngle", maxAngle);
d_hough->set("angleStep", angleStep);
}
d_hough->setTemplate(d_templ);
gpu::GpuMat d_templ(templ);
gpu::GpuMat d_image(image);
gpu::GpuMat d_position;
alg->setTemplate(d_templ);
tm.start();
d_hough->detect(d_image, d_position);
d_hough->downloadResults(d_position, position);
alg->detect(d_image, d_position);
d_position.download(position);
tm.stop();
}
else
{
Ptr<GeneralizedHough> hough = GeneralizedHough::create(method);
hough->set("minDist", minDist);
hough->set("levels", levels);
hough->set("dp", dp);
if (estimateScale && estimateRotation)
{
hough->set("angleThresh", angleThresh);
hough->set("scaleThresh", scaleThresh);
hough->set("posThresh", posThresh);
hough->set("maxSize", maxSize);
}
else
{
hough->set("votesThreshold", votesThreshold);
}
if (estimateScale)
{
hough->set("minScale", minScale);
hough->set("maxScale", maxScale);
hough->set("scaleStep", scaleStep);
}
if (estimateRotation)
{
hough->set("minAngle", minAngle);
hough->set("maxAngle", maxAngle);
hough->set("angleStep", angleStep);
}
hough->setTemplate(templ);
alg->setTemplate(templ);
tm.start();
hough->detect(image, position);
alg->detect(image, position);
tm.stop();
}
......
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