#ifndef LineDetector_h__ #define LineDetector_h__ #include "StdUtils.h" #include "CVUtils.h" #include "CyclopsEnums.h" #include "CyclopsModules.h" struct PeakLineParamPack; enum PeakAlgoAccLevel; /*! \brief Locate single or multiple line edge in the given image and ROI. * * The algorithm is real-time, while its limitation is it could only detect * parallel lines with small angel range (-10, +10), relative to the scan direction of roi. * So, using this detector, you should have a basic idea of the line's direction. * * 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 LineDetector::getInstance(). * Example: * \code{.cpp} * LineDetector::Ptr ldPtr = LineDetector::getInstance("detect sth"); * ldPtr->setLineDetectType(LineDetector::PEAKLINE); // use peakline algorithm * ldPtr->setLineType(Polarity::Black2White); // set polarity * ldPtr->setLineBasis(Findby::Best); // set findby strategy * Vec4f bestLine; // result line * float bestScore = ldPtr->detectBest(img, roiVertexes, roiDir, * bestLine, nullptr, 1, 10); * \endcode * * 1.2) or, if you wish to manage the detector yourself: * \code{.cpp} * LineDetector::Ptr ldPtr = std::make_shared(); // 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 * LineDetector::Ptr pdPtr = GetModuleInstance("detect sth"); * // get for temporary usage * LineDetector::Ptr pdPtr = GetModuleInstance(); * \endcode * * see SingleLineTest and MultiLineTest for unit test */ class LineDetector : public ICyclopsModuleInstance { public: // For backward compatibility, define LineType using the same value as Polarity. typedef Polarity LineType; static const int DARK_TO_BRIGHT; static const int BRIGHT_TO_DARK; static const int BRIGHT_AND_DARK; static LineType LineTypeFromName(const char* enum_name) { return LineType::FromName(enum_name); } /*! \deprecated Get polarity of target line edge. Use getPolarity() instead. */ DEPRECATED int getLineType() const { return mPolarity.value; } /*! \deprecated Set polarity of target line edge. Use setPolarity() instead. */ DEPRECATED void setLineType(int val) { mPolarity = val; } // For backward compatibility, define LineBasis using the same value as FindBy. typedef FindBy LineBasis; static const int BEST_LINE; static const int FIRST_LINE; static const int LAST_LINE; static LineBasis LineBasisFromName(const char* enum_name) { return LineBasis::FromName(enum_name); } /*! \deprecated Get find-by strategy. Use getFindBy() instead. */ DEPRECATED int getLineBasis() const { return mFindBy.value; } /*! \deprecated Set find-by strategy. Use setFindBy() instead. */ DEPRECATED void setLineBasis(int val) { mFindBy = val; } enum LineDetectType { /*! Classic algorithm using hough transform */ HOUGHLINE = 0, /*! Hough transform adopted image pyramid technology */ HOUGHLINE_PYR = 1, /*! Approach based on sub-pixel peaks */ PEAKLINE = 2, // add more detect type before this line... }; /*! \fn setPolarity * Define polarity of line edge, default to Polarity::Either, see also getPolarity() * \fn getPolarity * Get value of polarity of line edge, see also setPolarity() */ DECLARE_PARAMETER2(Polarity, Polarity, Polarity::Black2White, Polarity::Either) /*! \fn setFindBy * Define find-by stategy of detector, 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 setLineEdgeRatio * Define minimum contrast of the edge, 0 to 100, default to 0, see also getLineEdgeRatio() * \fn getLineEdgeRatio * Get value of minimum contrast of the edge, see also setLineEdgeRatio() */ DECLARE_PARAMETER2(float, LineEdgeRatio, 0, 100) /*! \fn setLineEdgeWidth * Define edge width, default to 3, see also getLineEdgeWidth() * The value should match the real edge width, which means the range that the edge transit from black to white or vice versa. * \fn getLineEdgeWidth * Get value of edge width, see also setLineEdgeWidth() */ DECLARE_PARAMETER(int, LineEdgeWidth) /*! \fn setLineDetectType(LineDetectType) * Define which algorithm we should use for detection, default to HOUGHLINE, see also getLineDetectType() * \fn getLineDetectType * Get which algorithm we are using for detection, see also setLineDetectType() */ DECLARE_PARAMETER(LineDetectType, LineDetectType) /*! \fn setAccLevel * Define accuracy level of the algorithm, default to -1 means hardcoded defaults, see also getAccLevel() * Note: this value only works for PEAKLINE. * \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: LineDetector(LineType lineType, LineBasis lineBasis, LineDetectType detectType) : mPolarity(lineType), mLineDetectType(detectType), mFindBy(lineBasis), mAccLevel(-1), mLineEdgeRatio(0), mLineEdgeWidth(3), mNormBy(NormBy::RegionMax) {} LineDetector() : mPolarity(Polarity::Either), mLineDetectType(HOUGHLINE), mFindBy(FindBy::Best), mAccLevel(-1), mLineEdgeRatio(0), mLineEdgeWidth(3), mNormBy(NormBy::RegionMax) {} virtual ~LineDetector() {} //! Smart pointer to hold an instance of LineDetector typedef std::shared_ptr Ptr; DECL_GET_INSTANCE(LineDetector::Ptr) /*! \deprecated detect a set of candidates lines. Use detectBest() instead. */ DEPRECATED void detect(const Mat& img, vector& bestLines, vector& bestScores, float ds, Range y0Range, Range y1Range, float maxAngleDeg); /*! \deprecated detect a set of candidates lines in provided roi. Use detectBest() instead. */ DEPRECATED void detect(const Mat& img, const vector& roiVertexes, const Point2f& roiDir, vector& bestLines, vector& bestScores, float ds, float maxAngleDeg); /*! \deprecated detect a set of candidates lines in provided roi. Use detectBest() instead. */ DEPRECATED void detect(const Mat& img, const RotatedRect& rotatedRect, vector& bestLines, vector& bestScores, float ds, float maxAngleDeg); /*! \deprecated detect a set of candidates lines in provided roi. Use detectBest() instead. */ DEPRECATED float detect(const Mat& img, const RotatedRect& rotatedRect, Vec4f& bestLine, float ds, float maxAngleDeg); /*! \deprecated detect a set of candidates lines in provided roi. Use detectBest() instead. */ DEPRECATED void detect(const Mat& img, const vector& roiVertexes, float angleDeg, vector& bestLines, vector& bestScores, float ds, float maxAngleDeg); /*! Detect the best single line using the detector. * @param img input image for detection * @param bestLine output line represented using endpoints: p1.x, p1.y, p2.x, p2.y * @param allScores output, represent the score distribution along the scan direction of roi, * pass null if you don't want it * @param ds control the search step * @param maxAngleDeg angel range of the line, -10 ~ +10 * @return score of the best one, 0 if we found nothing good */ virtual float detectBest(const Mat& img, Vec4f& bestLine, vector* allScores, // null is acceptable for no need float ds, float maxAngleDeg); /** @overload * @param roiVertexes roi for detection * @param angleDeg scan direction of roi */ virtual float detectBest(const Mat& img, const vector& roiVertexes, float angleDeg, Vec4f& bestLine, vector* allScores, // null is acceptable for no need float ds, float maxAngleDeg); /** @overload * @param roiVertexes roi for detection * @param roiDir scan direction of roi */ virtual float detectBest(const Mat& img, const vector& roiVertexes, const Point2f& roiDir, Vec4f& bestLine, vector* allScores, // null is acceptable for no need float ds, float maxAngleDeg); /*! Detect multiple lines using the detector. * @param img input image for detection * @param bestLines output lines represented using endpoints: p1.x, p1.y, p2.x, p2.y * @param bestScores output, represent the scores of detected lines, * pass null if you don't want it * @param allScores output, represent the score distribution along the scan direction of roi, * pass null if you don't want it * @param minLineCount minimum number of lines there should be * @param maxLineCount maximum number of lines there should be * @param ds control the search step * @param maxAngleDeg angel range of the line, -10 ~ +10 * @return real number of lines found in the image, it may exceed the provided limitation */ virtual int detectMulti(const Mat& img, vector* bestLines, // null if you don't want the exact line pos vector* bestScores, // null if you don't want the scores of each best lines vector* allScores, // null if you don't want the all scores along y axis int minLineCount, int maxLineCount, float ds, float maxAngleDeg); /** @overload * @param roiVertexes roi for detection * @param angleDeg scan direction of roi */ virtual int detectMulti(const Mat& img, const vector& roiVertexes, float angleDeg, vector* bestLines, // null if you don't want the exact line pos vector* bestScores, // null if you don't want the scores of each best lines vector* allScores, // null if you don't want the all scores along y axis int minLineCount, int maxLineCount, float ds, float maxAngleDeg); /** @overload * @param roiVertexes roi for detection * @param roiDir scan direction of roi */ virtual int detectMulti(const Mat& img, const vector& roiVertexes, const Point2f& roiDir, vector* bestLines, // null if you don't want the exact line pos vector* bestScores, // null if you don't want the scores of each best lines vector* allScores, // null if you don't want the all scores along y axis int minLineCount, int maxLineCount, float ds, float maxAngleDeg); /*! \deprecated select the best line of black-to-white polarity among a set of candidates lines. * Use detectBest() instead. */ DEPRECATED float bestPositiveLine(const vector& lines, const vector& scores, Vec4f& bestLine); /*! \deprecated select the best line of white-to-black polarity among a set of candidates lines. * Use detectBest() instead. */ DEPRECATED float bestNegativeLine(const vector& lines, const vector& scores, Vec4f& bestLine); /*! \deprecated select the best line of either black-to-white or white-to-black polarity among a set of candidates lines. * Use detectBest() instead. */ DEPRECATED float bestAbsLine(const vector& lines, const vector& scores, Vec4f& bestLine); /*! convenient api to define which algorithm we should use for detection * @param val integer value of detect algorithm type */ DEPRECATED void setLineDetectType(int val) { mLineDetectType = static_cast(val); } /*! \deprecated select the best line of provided polarity and find-by strategy among a set of candidates lines. * Use detectBest() instead. */ DEPRECATED bool selectBest(vector& bestLines, vector& bestScores, Vec4f& bestLine, float& bestScore); protected: float houghWithPyr(const Mat& gray, Vec4f& bestLine, vector& bestScores, float ds, Range y0Range, Range y1Range, float maxAngleDeg, unsigned int totalLevel = 2, float startScale = 0.5); private: void genPeakLineParamPack(PeakLineParamPack& pack, float maxAngleDeg, PeakAlgoAccLevel defaultAccLevel); }; #endif // LineDetector_h__