1
0
mirror of https://github.com/opencv/opencv_contrib.git synced 2025-10-16 13:57:05 +08:00

Merge remote-tracking branch 'upstream/3.4' into merge-3.4

This commit is contained in:
Alexander Alekhin
2021-04-08 10:49:48 +00:00
3 changed files with 48 additions and 105 deletions

View File

@@ -33,48 +33,45 @@ public:
![image](pics/corridor_fld.jpg) ![image](pics/corridor_fld.jpg)
@param _image A grayscale (CV_8UC1) input image. If only a roi needs to be @param image A grayscale (CV_8UC1) input image. If only a roi needs to be
selected, use: `fld_ptr-\>detect(image(roi), lines, ...); selected, use: `fld_ptr-\>detect(image(roi), lines, ...);
lines += Scalar(roi.x, roi.y, roi.x, roi.y);` lines += Scalar(roi.x, roi.y, roi.x, roi.y);`
@param _lines A vector of Vec4f elements specifying the beginning @param lines A vector of Vec4f elements specifying the beginning
and ending point of a line. Where Vec4f is (x1, y1, x2, y2), point and ending point of a line. Where Vec4f is (x1, y1, x2, y2), point
1 is the start, point 2 - end. Returned lines are directed so that the 1 is the start, point 2 - end. Returned lines are directed so that the
brighter side is on their left. brighter side is on their left.
*/ */
CV_WRAP virtual void detect(InputArray _image, OutputArray _lines) = 0; CV_WRAP virtual void detect(InputArray image, OutputArray lines) = 0;
/** @brief Draws the line segments on a given image. /** @brief Draws the line segments on a given image.
@param _image The image, where the lines will be drawn. Should be bigger @param image The image, where the lines will be drawn. Should be bigger
or equal to the image, where the lines were found. or equal to the image, where the lines were found.
@param lines A vector of the lines that needed to be drawn. @param lines A vector of the lines that needed to be drawn.
@param draw_arrow If true, arrow heads will be drawn. @param draw_arrow If true, arrow heads will be drawn.
*/ @param linecolor Line color.
CV_WRAP virtual void drawSegments(InputOutputArray _image, InputArray lines, @param linethickness Line thickness.
bool draw_arrow = false) = 0; */
CV_WRAP virtual void drawSegments(InputOutputArray image, InputArray lines,
bool draw_arrow = false, Scalar linecolor = Scalar(0, 0, 255), int linethickness = 1) = 0;
virtual ~FastLineDetector() { } virtual ~FastLineDetector() { }
}; };
/** @brief Creates a smart pointer to a FastLineDetector object and initializes it /** @brief Creates a smart pointer to a FastLineDetector object and initializes it
@param _length_threshold 10 - Segment shorter than this will be discarded @param length_threshold Segment shorter than this will be discarded
@param _distance_threshold 1.41421356 - A point placed from a hypothesis line @param distance_threshold A point placed from a hypothesis line
segment farther than this will be segment farther than this will be regarded as an outlier
regarded as an outlier @param canny_th1 First threshold for hysteresis procedure in Canny()
@param _canny_th1 50 - First threshold for @param canny_th2 Second threshold for hysteresis procedure in Canny()
hysteresis procedure in Canny() @param canny_aperture_size Aperturesize for the sobel operator in Canny().
@param _canny_th2 50 - Second threshold for If zero, Canny() is not applied and the input image is taken as an edge image.
hysteresis procedure in Canny() @param do_merge If true, incremental merging of segments will be performed
@param _canny_aperture_size 3 - Aperturesize for the sobel operator in Canny().
If zero, Canny() is not applied and the input
image is taken as an edge image.
@param _do_merge false - If true, incremental merging of segments
will be performed
*/ */
CV_EXPORTS_W Ptr<FastLineDetector> createFastLineDetector( CV_EXPORTS_W Ptr<FastLineDetector> createFastLineDetector(
int _length_threshold = 10, float _distance_threshold = 1.414213562f, int length_threshold = 10, float distance_threshold = 1.414213562f,
double _canny_th1 = 50.0, double _canny_th2 = 50.0, int _canny_aperture_size = 3, double canny_th1 = 50.0, double canny_th2 = 50.0, int canny_aperture_size = 3,
bool _do_merge = false); bool do_merge = false);
//! @} ximgproc_fast_line_detector //! @} ximgproc_fast_line_detector
} }

View File

@@ -391,6 +391,7 @@ void EdgeDrawingImpl::ComputeGradient()
case SCHARR: case SCHARR:
gx = abs(3 * (com1 + com2) + 10 * (smoothImg[i * width + j + 1] - smoothImg[i * width + j - 1])); gx = abs(3 * (com1 + com2) + 10 * (smoothImg[i * width + j + 1] - smoothImg[i * width + j - 1]));
gy = abs(3 * (com1 - com2) + 10 * (smoothImg[(i + 1) * width + j] - smoothImg[(i - 1) * width + j])); gy = abs(3 * (com1 - com2) + 10 * (smoothImg[(i + 1) * width + j] - smoothImg[(i - 1) * width + j]));
break;
case LSD: case LSD:
// com1 and com2 differs from previous operators, because LSD has 2x2 kernel // com1 and com2 differs from previous operators, because LSD has 2x2 kernel
com1 = smoothImg[(i + 1) * width + j + 1] - smoothImg[i * width + j]; com1 = smoothImg[(i + 1) * width + j + 1] - smoothImg[i * width + j];
@@ -398,6 +399,7 @@ void EdgeDrawingImpl::ComputeGradient()
gx = abs(com1 + com2); gx = abs(com1 + com2);
gy = abs(com1 - com2); gy = abs(com1 - com2);
break;
} }
int sum; int sum;
@@ -2943,7 +2945,7 @@ void EdgeDrawingImpl::DetectArcs()
bm->move(noPixels); bm->move(noPixels);
// Try to fit a circle to the entire arc of lines // Try to fit a circle to the entire arc of lines
double xc, yc, radius, circleFitError; double xc = -1, yc = -1, radius = -1, circleFitError = -1;
CircleFit(x, y, noPixels, &xc, &yc, &radius, &circleFitError); CircleFit(x, y, noPixels, &xc, &yc, &radius, &circleFitError);
double coverage = noPixels / (CV_2PI * radius); double coverage = noPixels / (CV_2PI * radius);

View File

@@ -21,46 +21,14 @@ namespace ximgproc{
class FastLineDetectorImpl : public FastLineDetector class FastLineDetectorImpl : public FastLineDetector
{ {
public: public:
/**
* @param _length_threshold 10 - Segment shorter than this will be discarded
* @param _distance_threshold 1.41421356 - A point placed from a hypothesis line segment
* farther than this will be regarded as an outlier
* @param _canny_th1 50 - First threshold for
* _ hysteresis procedure in Canny()
* @param _canny_th2 50 - Second threshold for
* _ hysteresis procedure in Canny()
* @param _canny_aperture_size 3 - Aperturesize for the sobel operator in Canny().
* If zero, Canny() is not applied and the input
* image is taken as an edge image.
* @param _do_merge false - If true, incremental merging of segments
* will be performed
*/
FastLineDetectorImpl(int _length_threshold = 10, float _distance_threshold = 1.414213562f, FastLineDetectorImpl(int _length_threshold = 10, float _distance_threshold = 1.414213562f,
double _canny_th1 = 50.0, double _canny_th2 = 50.0, int _canny_aperture_size = 3, double _canny_th1 = 50.0, double _canny_th2 = 50.0, int _canny_aperture_size = 3,
bool _do_merge = false); bool _do_merge = false);
/** void detect(InputArray image, OutputArray lines) CV_OVERRIDE;
* Detect lines in the input image.
*
* @param _image A grayscale(CV_8UC1) input image.
* If only a roi needs to be selected, use
* lsd_ptr->detect(image(roi), ..., lines);
* lines += Scalar(roi.x, roi.y, roi.x, roi.y);
* @param _lines Return: A vector of Vec4f elements specifying the beginning and ending point of
* a line. Where Vec4f is (x1, y1, x2, y2), point 1 is the start, point 2 is the end.
* Returned lines are directed so that the brighter side is placed on left.
*/
void detect(InputArray _image, OutputArray _lines) CV_OVERRIDE;
/** void drawSegments(InputOutputArray image, InputArray lines, bool draw_arrow = false, Scalar linecolor = Scalar(0, 0, 255), int linethickness = 1) CV_OVERRIDE;
* Draw lines on the given canvas.
*
* @param image The image, where lines will be drawn
* Should have the size of the image, where the lines were found
* @param lines The lines that need to be drawn
* @param draw_arrow If true, arrow heads will be drawn
*/
void drawSegments(InputOutputArray _image, InputArray lines, bool draw_arrow = false) CV_OVERRIDE;
private: private:
int imagewidth, imageheight, threshold_length; int imagewidth, imageheight, threshold_length;
@@ -85,25 +53,24 @@ class FastLineDetectorImpl : public FastLineDetector
void lineDetection(const Mat& src, std::vector<SEGMENT>& segments_all); void lineDetection(const Mat& src, std::vector<SEGMENT>& segments_all);
void pointInboardTest(const Mat& src, Point2i& pt); void pointInboardTest(const Size srcSize, Point2i& pt);
inline void getAngle(SEGMENT& seg); inline void getAngle(SEGMENT& seg);
void additionalOperationsOnSegment(const Mat& src, SEGMENT& seg); void additionalOperationsOnSegment(const Mat& src, SEGMENT& seg);
void drawSegment(Mat& mat, const SEGMENT& seg, Scalar bgr = Scalar(0,255,0), void drawSegment(InputOutputArray image, const SEGMENT& seg, Scalar bgr = Scalar(0,255,0), int thickness = 1, bool directed = true);
int thickness = 1, bool directed = true);
}; };
///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////
CV_EXPORTS Ptr<FastLineDetector> createFastLineDetector( CV_EXPORTS Ptr<FastLineDetector> createFastLineDetector(
int _length_threshold, float _distance_threshold, int length_threshold, float distance_threshold,
double _canny_th1, double _canny_th2, int _canny_aperture_size, bool _do_merge) double canny_th1, double canny_th2, int canny_aperture_size, bool do_merge)
{ {
return makePtr<FastLineDetectorImpl>( return makePtr<FastLineDetectorImpl>(
_length_threshold, _distance_threshold, length_threshold, distance_threshold,
_canny_th1, _canny_th2, _canny_aperture_size, _do_merge); canny_th1, canny_th2, canny_aperture_size, do_merge);
} }
///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////
@@ -136,30 +103,23 @@ void FastLineDetectorImpl::detect(InputArray _image, OutputArray _lines)
Mat(lines).copyTo(_lines); Mat(lines).copyTo(_lines);
} }
void FastLineDetectorImpl::drawSegments(InputOutputArray _image, InputArray lines, bool draw_arrow) void FastLineDetectorImpl::drawSegments(InputOutputArray image, InputArray lines, bool draw_arrow, Scalar linecolor, int linethickness)
{ {
CV_INSTRUMENT_REGION(); CV_INSTRUMENT_REGION();
CV_Assert(!_image.empty() && (_image.channels() == 1 || _image.channels() == 3)); int cn = image.channels();
CV_Assert(!image.empty() && ( cn == 1 || cn == 3 || cn == 4));
Mat gray; if (cn == 1)
if (_image.channels() == 1)
{ {
gray = _image.getMatRef(); cvtColor(image, image, COLOR_GRAY2BGR);
} }
else if (_image.channels() == 3) else
{ {
cvtColor(_image, gray, COLOR_BGR2GRAY); cvtColor(image, image, COLOR_BGRA2GRAY);
cvtColor(image, image, cn == 3 ? COLOR_GRAY2BGR : COLOR_GRAY2BGRA);
} }
// Create a 3 channel image in order to draw colored lines
std::vector<Mat> planes;
planes.push_back(gray);
planes.push_back(gray);
planes.push_back(gray);
merge(planes, _image);
double gap = 10.0; double gap = 10.0;
double arrow_angle = 30.0; double arrow_angle = 30.0;
@@ -172,7 +132,7 @@ void FastLineDetectorImpl::drawSegments(InputOutputArray _image, InputArray line
const Vec4f& v = _lines.at<Vec4f>(i); const Vec4f& v = _lines.at<Vec4f>(i);
Point2f b(v[0], v[1]); Point2f b(v[0], v[1]);
Point2f e(v[2], v[3]); Point2f e(v[2], v[3]);
line(_image.getMatRef(), b, e, Scalar(0, 0, 255), 1); line(image, b, e, linecolor, linethickness);
if(draw_arrow) if(draw_arrow)
{ {
SEGMENT seg; SEGMENT seg;
@@ -185,8 +145,8 @@ void FastLineDetectorImpl::drawSegments(InputOutputArray _image, InputArray line
Point2i p1; Point2i p1;
p1.x = cvRound(seg.x2 - gap*cos(arrow_angle * CV_PI / 180.0 + ang)); p1.x = cvRound(seg.x2 - gap*cos(arrow_angle * CV_PI / 180.0 + ang));
p1.y = cvRound(seg.y2 - gap*sin(arrow_angle * CV_PI / 180.0 + ang)); p1.y = cvRound(seg.y2 - gap*sin(arrow_angle * CV_PI / 180.0 + ang));
pointInboardTest(_image.getMatRef(), p1); pointInboardTest(image.size(), p1);
line(_image.getMatRef(), Point(cvRound(seg.x2), cvRound(seg.y2)), p1, Scalar(0,0,255), 1); line(image, Point(cvRound(seg.x2), cvRound(seg.y2)), p1, linecolor, linethickness);
} }
} }
} }
@@ -477,10 +437,10 @@ void FastLineDetectorImpl::extractSegments(const std::vector<Point2i>& points, s
} }
} }
void FastLineDetectorImpl::pointInboardTest(const Mat& src, Point2i& pt) void FastLineDetectorImpl::pointInboardTest(const Size srcSize, Point2i& pt)
{ {
pt.x = pt.x <= 5 ? 5 : pt.x >= src.cols - 5 ? src.cols - 5 : pt.x; pt.x = pt.x <= 5 ? 5 : pt.x >= srcSize.width - 5 ? srcSize.width - 5 : pt.x;
pt.y = pt.y <= 5 ? 5 : pt.y >= src.rows - 5 ? src.rows - 5 : pt.y; pt.y = pt.y <= 5 ? 5 : pt.y >= srcSize.height - 5 ? srcSize.height - 5 : pt.y;
} }
bool FastLineDetectorImpl::getPointChain(const Mat& img, Point pt, bool FastLineDetectorImpl::getPointChain(const Mat& img, Point pt,
@@ -692,8 +652,8 @@ void FastLineDetectorImpl::additionalOperationsOnSegment(const Mat& src, SEGMENT
points_right[i].y = cvRound(points[i].y + gap*sin(90.0 * CV_PI / 180.0 + ang)); points_right[i].y = cvRound(points[i].y + gap*sin(90.0 * CV_PI / 180.0 + ang));
points_left[i].x = cvRound(points[i].x - gap*cos(90.0 * CV_PI / 180.0 + ang)); points_left[i].x = cvRound(points[i].x - gap*cos(90.0 * CV_PI / 180.0 + ang));
points_left[i].y = cvRound(points[i].y - gap*sin(90.0 * CV_PI / 180.0 + ang)); points_left[i].y = cvRound(points[i].y - gap*sin(90.0 * CV_PI / 180.0 + ang));
pointInboardTest(src, points_right[i]); pointInboardTest(src.size(), points_right[i]);
pointInboardTest(src, points_left[i]); pointInboardTest(src.size(), points_left[i]);
} }
int iR = 0, iL = 0; int iR = 0, iL = 0;
@@ -717,21 +677,5 @@ void FastLineDetectorImpl::additionalOperationsOnSegment(const Mat& src, SEGMENT
return; return;
} }
void FastLineDetectorImpl::drawSegment(Mat& mat, const SEGMENT& seg, Scalar bgr, int thickness, bool directed)
{
double gap = 10.0;
double ang = (double)seg.angle;
double arrow_angle = 30.0;
Point2i p1;
p1.x = cvRound(seg.x2 - gap*cos(arrow_angle * CV_PI / 180.0 + ang));
p1.y = cvRound(seg.y2 - gap*sin(arrow_angle * CV_PI / 180.0 + ang));
pointInboardTest(mat, p1);
line(mat, Point(cvRound(seg.x1), cvRound(seg.y1)),
Point(cvRound(seg.x2), cvRound(seg.y2)), bgr, thickness, 1);
if(directed)
line(mat, Point(cvRound(seg.x2), cvRound(seg.y2)), p1, bgr, thickness, 1);
}
} // namespace cv } // namespace cv
} // namespace ximgproc } // namespace ximgproc