You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
7.3 KiB
C++
207 lines
7.3 KiB
C++
/*!
|
|
* \file CircleDetector.h
|
|
* \date 2018/08/06
|
|
*
|
|
* \author Lin, Chi
|
|
* Contact: lin.chi@hzleaper.com
|
|
*
|
|
*
|
|
* \note
|
|
*/
|
|
|
|
#ifndef __CircleDetector_h_
|
|
#define __CircleDetector_h_
|
|
|
|
#include "StdUtils.h"
|
|
#include "CVUtils.h"
|
|
#include "CyclopsEnums.h"
|
|
#include "CyclopsModules.h"
|
|
|
|
struct PeakCircleParamPack;
|
|
enum PeakAlgoAccLevel;
|
|
|
|
/*! \brief Located single or multiple circles in the given image and ROI.
|
|
*
|
|
* We support several algorithms in this detector, choose one suitable for your scenario.
|
|
* If you are pretty sure where the circle center is, use PeakCircle;
|
|
* otherwise, you should use either HoughCircle or EDCircle depending on the performance and accuracy requirement.
|
|
*
|
|
* 1) If you are using Cyclops as static library,
|
|
* 1.1) and you want global factory to manage the detector for you, initialize the detector
|
|
* via CircleDetector::getInstance().
|
|
* Example:
|
|
* \code{.cpp}
|
|
* CircleDetector::Ptr cdPtr = CircleDetector::getInstance("detect sth");
|
|
* cdPtr->setAlgoType(CircleDetector::PeakCircle); // use peakcircle algorithm
|
|
* cdPtr->setLineType(Polarity::Black2White); // set polarity
|
|
* cdPtr->setLineBasis(Findby::Best); // set findby strategy
|
|
* cdPtr->setRadii(90, 110); // set radii range
|
|
* Vec3f bestCircle; // result circle
|
|
* float bestScore = cdPtr->detectBest(img, Point2f(200, 300), // give estimated center point, and run the detection
|
|
* bestCircle, nullptr);
|
|
*
|
|
* // delete it later
|
|
* CircleDetector::deleteInstance("detect sth");
|
|
* \endcode
|
|
*
|
|
* 1.2) or, if you wish to manage the detector yourself:
|
|
* \code{.cpp}
|
|
* CircleDetector::Ptr ldPtr = std::make_shared<CircleDetector>(); // remember to hold the smart pointer
|
|
* // balabala, same as above
|
|
* // ...
|
|
* \endcode
|
|
*
|
|
* 2) If you are using Cyclops as dynamic library,
|
|
* initialize and manipulate the detector via CyclopsModules APIs.
|
|
* Example:
|
|
* \code{.cpp}
|
|
* // get a long-term detector, and give it an unique name
|
|
* CircleDetector::Ptr cdPtr = GetModuleInstance<CircleDetector>("detect sth");
|
|
* // get for temporary usage
|
|
* CircleDetector::Ptr localCdPtr = GetModuleInstance<CircleDetector>();
|
|
*
|
|
* // delete it later
|
|
* DeleteModuleInstance<CircleDetector>("detect sth");
|
|
* \endcode
|
|
*
|
|
* see SingleCircleTest and MultiCircleTest for unit test
|
|
*/
|
|
class CircleDetector : public ICyclopsModuleInstance
|
|
{
|
|
public:
|
|
|
|
enum CircleDetectAlgoType
|
|
{
|
|
/*! Classic algorithm using hough transform, similar as Matlab's imfindcircles */
|
|
HoughCircle = 0,
|
|
/*! Approach based on sub-pixel peaks. Limitation: detect only almost concentric circles near center of image */
|
|
PeakCircle = 1,
|
|
/*! Approach adopted from "EDCircles: A Real-time Parameter-free Circle Detector with a False Detection Control"
|
|
\link http://ceng.anadolu.edu.tr/cv/edcircles/
|
|
*/
|
|
EDCircle = 2,
|
|
};
|
|
|
|
/*! \fn setPolarity
|
|
* Define polarity of circle edge, Polarity::Black2White to Polarity::Either, default to Polarity::Either, see also getPolarity()
|
|
* \fn getPolarity
|
|
* Get value of polarity of circle edge, see also setPolarity()
|
|
*/
|
|
DECLARE_PARAMETER2(Polarity, Polarity, Polarity::Black2White, Polarity::Either)
|
|
/*! \fn setFindBy
|
|
* Define find-by stategy of detector, FindBy::Best to FindBy::Last, default to FindBy::Best, see also getFindBy()
|
|
* \fn getFindBy
|
|
* Get value of find-by stategy of detector, see also setFindBy()
|
|
*/
|
|
DECLARE_PARAMETER2(FindBy, FindBy, FindBy::Best, FindBy::All)
|
|
/*! \fn setACThres
|
|
* Define minimum acceptable score, 0 to 100, default to 0, see also getACThres()
|
|
* \fn getACThres
|
|
* Get value of minimum acceptable score, see also setACThres()
|
|
*/
|
|
DECLARE_PARAMETER2(int, ACThres, 0, 100)
|
|
/*! \fn setEdgeWidth
|
|
* Define edge width, default to 3, see also getEdgeWidth()
|
|
* The value should match the real edge width, which means the range that the edge transit from black to white or vice versa.
|
|
* \fn getEdgeWidth
|
|
* Get value of edge width, see also setEdgeWidth()
|
|
*/
|
|
DECLARE_PARAMETER(int, EdgeWidth)
|
|
/*! \fn setAlgoType
|
|
* Define which algorithm we should use for detection, default to PeakCircle, see also getAlgoType()
|
|
* \fn getAlgoType
|
|
* Get which algorithm we are using for detection, see also setAlgoType()
|
|
*/
|
|
DECLARE_PARAMETER2(CircleDetectAlgoType, AlgoType, HoughCircle, PeakCircle)
|
|
/*! \fn setRadii
|
|
* Define the radii range [val1, val2]
|
|
* \fn getRadiiStart
|
|
* Get value of minimum circle radii
|
|
* \fn getRadiiEnd
|
|
* Get value of maximum circle radii
|
|
*/
|
|
DECLARE_PARAMETER_PAIR(unsigned int, Radii)
|
|
/*! \fn setAccLevel
|
|
* Define accuracy level of the algorithm, default to -1 means hardcoded defaults, see also getAccLevel()
|
|
* Note: this value only works for PeakCircle.
|
|
* \fn getAccLevel
|
|
* Get value of accuracy level of the algorithm, see also setAccLevel()
|
|
*/
|
|
DECLARE_PARAMETER(int, AccLevel)
|
|
/*! \fn setNormBy
|
|
* Define how to normalized scores, default to NormBy::RegionMax, see also getNormBy()
|
|
* \fn getNormBy
|
|
* Get value of how to normalized scores, see also setNormBy()
|
|
*/
|
|
DECLARE_PARAMETER(NormBy, NormBy)
|
|
|
|
public:
|
|
CircleDetector(Polarity polarity, FindBy findby, CircleDetectAlgoType algoType) :
|
|
mPolarity(polarity), mFindBy(findby), mAlgoType(algoType),
|
|
mACThres(0), mEdgeWidth(3), mAccLevel(-1), mNormBy(NormBy::RegionMax)
|
|
{}
|
|
CircleDetector() :
|
|
mPolarity(Polarity::Either), mFindBy(FindBy::Best), mAlgoType(PeakCircle),
|
|
mACThres(0), mEdgeWidth(3), mAccLevel(-1), mNormBy(NormBy::RegionMax)
|
|
{}
|
|
virtual ~CircleDetector() {}
|
|
|
|
//! Smart pointer to hold an instance of CircleDetector
|
|
typedef std::shared_ptr<CircleDetector> Ptr;
|
|
DECL_GET_INSTANCE(CircleDetector::Ptr)
|
|
|
|
/*! Detect the best single circle edge using the detector
|
|
* @param img input image for detection
|
|
* @param bestCircle output circle: center.x, center.y, radii
|
|
* @param allScores output, represent the score distribution among defined radii range,
|
|
* pass null if you don't want it
|
|
* @param mask input mask for exclude some pixel from detection
|
|
* @return score of the best one, 0 if we found nothing good
|
|
*/
|
|
virtual float detectBest(const Mat& img,
|
|
Vec3f& bestCircle,
|
|
vector<float>* allScores = nullptr,
|
|
Mat* mask = nullptr);
|
|
|
|
/** @overload */
|
|
virtual float detectBest(const Mat& img,
|
|
const Point2f& estCenter,
|
|
Vec3f& bestCircle,
|
|
vector<float>* allScores = nullptr);
|
|
|
|
/*! Detect multiple circle edge using the detector
|
|
* @param img input image for detection
|
|
* @param bestCircles output circles: center.x, center.y, radii
|
|
* @param bestScoresoutput scores of several best circles
|
|
* @param allScores output, represent the score distribution among defined radii range,
|
|
* pass null if you don't want it
|
|
* @param minCount minimum number of circles there should be
|
|
* @param maxCount maximum number of circles there should be
|
|
* @param mask input mask for exclude some pixel from detection
|
|
* @return real number of lines found in the image, it may exceed the provided limitation
|
|
*/
|
|
virtual int detectMulti(const Mat& img,
|
|
vector<Vec3f>* bestCircles,
|
|
vector<float>* bestScores,
|
|
vector<float>* allScores = nullptr,
|
|
int minCount = 0,
|
|
int maxCount = 10,
|
|
Mat* mask = nullptr);
|
|
|
|
/** @overload */
|
|
virtual int detectMulti(const Mat& img,
|
|
const Point2f& estCenter,
|
|
vector<Vec3f>* bestCircles,
|
|
vector<float>* bestScores,
|
|
vector<float>* allScores = nullptr,
|
|
int minCount = 0,
|
|
int maxCount = 10);
|
|
|
|
private:
|
|
void genPeakCircleParamPack(PeakCircleParamPack& pack, PeakAlgoAccLevel defaultAccLevel);
|
|
|
|
};
|
|
|
|
#endif // CircleDetector_h_
|
|
|