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.
292 lines
12 KiB
C
292 lines
12 KiB
C
|
4 years ago
|
#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<LineDetector>(); // 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<LineDetector>("detect sth");
|
||
|
|
* // get for temporary usage
|
||
|
|
* LineDetector::Ptr pdPtr = GetModuleInstance<LineDetector>();
|
||
|
|
* \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<LineDetector> Ptr;
|
||
|
|
DECL_GET_INSTANCE(LineDetector::Ptr)
|
||
|
|
|
||
|
|
/*! \deprecated detect a set of candidates lines. Use detectBest() instead. */
|
||
|
|
DEPRECATED void detect(const Mat& img, vector<Vec4f>& bestLines,
|
||
|
|
vector<float>& 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<Point2f>& roiVertexes,
|
||
|
|
const Point2f& roiDir,
|
||
|
|
vector<Vec4f>& bestLines, vector<float>& 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<Vec4f>& bestLines, vector<float>& 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<Point2f>& roiVertexes, float angleDeg,
|
||
|
|
vector<Vec4f>& bestLines, vector<float>& 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<float>* 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<Point2f>& roiVertexes, float angleDeg,
|
||
|
|
Vec4f& bestLine, vector<float>* 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<Point2f>& roiVertexes, const Point2f& roiDir,
|
||
|
|
Vec4f& bestLine, vector<float>* 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<Vec4f>* bestLines, // null if you don't want the exact line pos
|
||
|
|
vector<float>* bestScores, // null if you don't want the scores of each best lines
|
||
|
|
vector<float>* 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<Point2f>& roiVertexes, float angleDeg,
|
||
|
|
vector<Vec4f>* bestLines, // null if you don't want the exact line pos
|
||
|
|
vector<float>* bestScores, // null if you don't want the scores of each best lines
|
||
|
|
vector<float>* 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<Point2f>& roiVertexes, const Point2f& roiDir,
|
||
|
|
vector<Vec4f>* bestLines, // null if you don't want the exact line pos
|
||
|
|
vector<float>* bestScores, // null if you don't want the scores of each best lines
|
||
|
|
vector<float>* 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<Vec4f>& lines, const vector<float>& 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<Vec4f>& lines, const vector<float>& 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<Vec4f>& lines, const vector<float>& 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<LineDetectType>(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<Vec4f>& bestLines, vector<float>& bestScores, Vec4f& bestLine, float& bestScore);
|
||
|
|
|
||
|
|
protected:
|
||
|
|
float houghWithPyr(const Mat& gray, Vec4f& bestLine,
|
||
|
|
vector<float>& 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__
|