/*! * \file ArcDetector.h * \date 2020/04/28 16:41 * * \author lucas.ma * Contact: lucas.ma@hzleaper.com * * TODO: null * * \note */ #ifndef _AnnulusSectorDetector_H__ #define _AnnulusSectorDetector_H__ #include "StdUtils.h" #include "CVUtils.h" #include "CyclopsEnums.h" #include "CyclopsModules.h" struct PeakCircleParamPack; enum PeakAlgoAccLevel; struct ArcCurve { ArcCurve() : mCircle(Vec3f(0, 0, 0)), mStartPnt(Point2f(0, 0)), mEndPnt(Point2f(0, 0)) {} ArcCurve(const Vec3f& circle, const Point2f& sp, const Point2f& ep) : mCircle(circle), mStartPnt(sp), mEndPnt(ep) {} float getAngle() const { Point2f dsp = mStartPnt - Point2f(mCircle[0], mCircle[1]); Point2f dep = mEndPnt - Point2f(mCircle[0], mCircle[1]); Point2f ns = dsp / sqrt(dsp.x * dsp.x + dsp.y* dsp.y); Point2f ne = dep / sqrt(dep.x * dep.x + dep.y * dep.y); float endAngle = fastAtan2(ne.y, ne.x); float startAngle = fastAtan2(ns.y, ns.x); float angle = endAngle - startAngle; if (startAngle > endAngle) angle = angle + 360; return angle; } bool isEmpty() const { return mCircle == Vec3f::zeros(); } public: Vec3f mCircle; Point2f mStartPnt; Point2f mEndPnt; }; class ArcDectector : public ICyclopsModuleInstance { public: /*! \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 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: ArcDectector(Polarity polarity, FindBy findby) : mPolarity(polarity), mFindBy(findby), mACThres(0), mEdgeWidth(3), mAccLevel(-1), mNormBy(NormBy::RegionMax) {}; ArcDectector() : mPolarity(Polarity::Either), mFindBy(FindBy::Best), mACThres(0), mEdgeWidth(3), mAccLevel(-1), mNormBy(NormBy::RegionMax) {}; virtual ~ArcDectector() {}; typedef std::shared_ptr Ptr; DECL_GET_INSTANCE(ArcDectector::Ptr) /*! Detect the best single arc edge using the detector * @param img input image for detection * @param bestArc output arc: Vec3f(center.x, center.y, radii), vector{startPoint, endPoint} * @param estCenter input initial estimated center of circular arc, if estCenter == nullptr, then it will automatically use center of input image as estimated center * @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, ArcCurve& bestArc, Point2f* estCenter = nullptr, vector* allScores = nullptr, Mat* mask = nullptr); /** @overload */ /*! Detect the best single arc edge using the detector * @param img input image for detection * @param shapePnts input defined annulus sector ROI * @param bestArc output arc: Vec3f(center.x, center.y, radii), vector{startPoint, endPoint} * @param allScores output, represent the score distribution among defined radii range, * pass null if you don't want it * @return score of the best one, 0 if we found nothing good */ virtual float detectBest(const Mat& img, const vector& shapePnts, ArcCurve& bestArc, vector* allScores = nullptr); /*! Detect multiple arc edge using the detector * @param img input image for detection * @param bestArc output arcs * @param bestScores output scores of several best arcs * @param estCenter input initial estimated center of circular arc, if estCenter == Point2f(0,0), then it will automatically use center of input image as estimated center * @param allScores output, represent the score distribution among defined radii range, * pass null if you don't want it * @param minCount minimum number of arcs there should be * @param maxCount maximum number of arcs there should be * @param mask input mask for exclude some pixel from detection * @return real number of arcs found in the image, it may exceed the provided limitation */ virtual int detectMulti(const Mat& img, vector* bestArcs, vector* bestScores, Point2f* estCenter = nullptr, vector* allScores = nullptr, int minCount = 0, int maxCount = 10, Mat* mask = nullptr); /** @overload */ /*! Detect multiple arc edge using the detector * @param img input image for detection * @param shapePnts input defined annulus sector ROI * @param bestArc output arcs * @param bestScores output scores of several best arcs * @param input initial estimated center of circular arc, if estCenter == Point2f(0,0), then it will automatically use center of input image as estimated center * @param allScores output, represent the score distribution among defined radii range, * pass null if you don't want it * @param minCount minimum number of arcs there should be * @param maxCount maximum number of arcs there should be * @return real number of arcs found in the image, it may exceed the provided limitation */ virtual int detectMulti(const Mat& img, const vector& shapePnts, vector* bestArcs, vector* bestScores, vector* allScores = nullptr, int minCount = 0, int maxCount = 10); private: void genPeakArcParamPack(PeakCircleParamPack & pack, PeakAlgoAccLevel defaultAccLevel); }; #endif // _AnnulusSectorDetector_H__