Skip to content

Commit f7efcba

Browse files
authored
Merge pull request #2313 from sturkmen72:test_Edge_Drawing_Algos
* EdgeDrawing algorithms (ED EDPF EDLines EDCircles) * eliminate build warning
1 parent 4de4ede commit f7efcba

File tree

10 files changed

+6797
-13
lines changed

10 files changed

+6797
-13
lines changed

modules/ximgproc/doc/ximgproc.bib

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,47 @@ @inproceedings{BarronPoole2016
310310
publisher={Springer International Publishing},
311311
pages={617--632},
312312
}
313+
314+
@article{topal2012edge,
315+
title={Edge drawing: a combined real-time edge and segment detector},
316+
author={Topal, Cihan and Akinlar, Cuneyt},
317+
journal={Journal of Visual Communication and Image Representation},
318+
volume={23},
319+
number={6},
320+
pages={862--872},
321+
year={2012},
322+
publisher={Elsevier}
323+
}
324+
325+
@article{akinlar2011edlines,
326+
title={EDLines: A real-time line segment detector with a false detection control},
327+
author={Akinlar, Cuneyt and Topal, Cihan},
328+
journal={Pattern Recognition Letters},
329+
volume={32},
330+
number={13},
331+
pages={1633--1642},
332+
year={2011},
333+
publisher={Elsevier}
334+
}
335+
336+
@article{akinlar2012edpf,
337+
title={EDPF: a real-time parameter-free edge segment detector with a false detection control},
338+
author={Akinlar, Cuneyt and Topal, Cihan},
339+
journal={International Journal of Pattern Recognition and Artificial Intelligence},
340+
volume={26},
341+
number={01},
342+
pages={1255002},
343+
year={2012},
344+
publisher={World Scientific}
345+
}
346+
347+
@article{akinlar2013edcircles,
348+
title={EDCircles: A real-time circle detector with a false detection control},
349+
author={Akinlar, Cuneyt and Topal, Cihan},
350+
journal={Pattern Recognition},
351+
volume={46},
352+
number={3},
353+
pages={725--740},
354+
year={2013},
355+
publisher={Elsevier}
356+
}

modules/ximgproc/include/opencv2/ximgproc.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "ximgproc/sparse_match_interpolator.hpp"
4343
#include "ximgproc/structured_edge_detection.hpp"
4444
#include "ximgproc/edgeboxes.hpp"
45+
#include "ximgproc/edge_drawing.hpp"
4546
#include "ximgproc/seeds.hpp"
4647
#include "ximgproc/segmentation.hpp"
4748
#include "ximgproc/fast_hough_transform.hpp"
@@ -75,6 +76,8 @@ i.e. algorithms which somehow takes into account pixel affinities in natural ima
7576
7677
@defgroup ximgproc_fast_line_detector Fast line detector
7778
79+
@defgroup ximgproc_edge_drawing EdgeDrawing
80+
7881
@defgroup ximgproc_fourier Fourier descriptors
7982
@}
8083
*/
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
5+
#ifndef __OPENCV_EDGE_DRAWING_HPP__
6+
#define __OPENCV_EDGE_DRAWING_HPP__
7+
8+
#include <opencv2/core.hpp>
9+
10+
namespace cv
11+
{
12+
namespace ximgproc
13+
{
14+
15+
//! @addtogroup ximgproc_edge_drawing
16+
//! @{
17+
18+
/** @brief Class implementing the ED (EdgeDrawing) @cite topal2012edge, EDLines @cite akinlar2011edlines, EDPF @cite akinlar2012edpf and EDCircles @cite akinlar2013edcircles algorithms
19+
20+
EDGE DRAWING LIBRARY FOR GEOMETRIC FEATURE EXTRACTION AND VALIDATION
21+
22+
Edge Drawing (ED) algorithm is an proactive approach on edge detection problem. In contrast to many other existing edge detection algorithms which follow a subtractive
23+
approach (i.e. after applying gradient filters onto an image eliminating pixels w.r.t. several rules, e.g. non-maximal suppression and hysteresis in Canny), ED algorithm
24+
works via an additive strategy, i.e. it picks edge pixels one by one, hence the name Edge Drawing. Then we process those random shaped edge segments to extract higher level
25+
edge features, i.e. lines, circles, ellipses, etc. The popular method of extraction edge pixels from the thresholded gradient magnitudes is non-maximal supressiun that tests
26+
every pixel whether it has the maximum gradient response along its gradient direction and eliminates if it does not. However, this method does not check status of the
27+
neighboring pixels, and therefore might result low quality (in terms of edge continuity, smoothness, thinness, localization) edge segments. Instead of non-maximal supression,
28+
ED points a set of edge pixels and join them by maximizing the total gradient response of edge segments. Therefore it can extract high quality edge segments without need for
29+
an additional hysteresis step.
30+
*/
31+
32+
class CV_EXPORTS_W EdgeDrawing : public Algorithm
33+
{
34+
public:
35+
36+
enum GradientOperator
37+
{
38+
PREWITT = 0,
39+
SOBEL = 1,
40+
SCHARR = 2,
41+
LSD = 3
42+
};
43+
44+
struct CV_EXPORTS_W_SIMPLE Params
45+
{
46+
CV_WRAP Params();
47+
//! Parameter Free mode will be activated when this value is true.
48+
CV_PROP_RW bool PFmode;
49+
//! indicates the operator used for gradient calculation.The following operation flags are available(cv::ximgproc::EdgeDrawing::GradientOperator)
50+
CV_PROP_RW int EdgeDetectionOperator;
51+
//! threshold value used to create gradient image.
52+
CV_PROP_RW int GradientThresholdValue;
53+
//! threshold value used to create gradient image.
54+
CV_PROP_RW int AnchorThresholdValue;
55+
CV_PROP_RW int ScanInterval;
56+
//! minimun connected pixels length processed to create an edge segment.
57+
CV_PROP_RW int MinPathLength;
58+
//! sigma value for internal GaussianBlur() function.
59+
CV_PROP_RW float Sigma;
60+
CV_PROP_RW bool SumFlag;
61+
//! when this value is true NFA (Number of False Alarms) algorithm will be used for line and ellipse validation.
62+
CV_PROP_RW bool NFAValidation;
63+
//! minimun line length to detect.
64+
CV_PROP_RW int MinLineLength;
65+
CV_PROP_RW double MaxDistanceBetweenTwoLines;
66+
CV_PROP_RW double LineFitErrorThreshold;
67+
CV_PROP_RW double MaxErrorThreshold;
68+
69+
void read(const FileNode& fn);
70+
void write(FileStorage& fs) const;
71+
};
72+
73+
/** @brief Detects edges and prepares them to detect lines and ellipses.
74+
75+
@param src input image
76+
*/
77+
CV_WRAP virtual void detectEdges(InputArray src) = 0;
78+
CV_WRAP virtual void getEdgeImage(OutputArray dst) = 0;
79+
CV_WRAP virtual void getGradientImage(OutputArray dst) = 0;
80+
81+
CV_WRAP virtual std::vector<std::vector<Point> > getSegments() = 0;
82+
83+
/** @brief Detects lines.
84+
85+
@param lines output Vec<4f> contains start point and end point of detected lines.
86+
@note you should call detectEdges() method before call this.
87+
*/
88+
CV_WRAP virtual void detectLines(OutputArray lines) = 0;
89+
90+
/** @brief Detects circles and ellipses.
91+
92+
@param ellipses output Vec<6d> contains center point and perimeter for circles.
93+
@note you should call detectEdges() method before call this.
94+
*/
95+
CV_WRAP virtual void detectEllipses(OutputArray ellipses) = 0;
96+
97+
CV_WRAP Params params;
98+
99+
/** @brief sets parameters.
100+
101+
this function is meant to be used for parameter setting in other languages than c++.
102+
*/
103+
CV_WRAP void setParams(const EdgeDrawing::Params& parameters);
104+
virtual ~EdgeDrawing() { }
105+
};
106+
107+
/** @brief Creates a smart pointer to a EdgeDrawing object and initializes it
108+
*/
109+
CV_EXPORTS_W Ptr<EdgeDrawing> createEdgeDrawing();
110+
//! @}
111+
112+
}
113+
}
114+
115+
#endif /* __OPENCV_EDGE_DRAWING_HPP__ */

modules/ximgproc/include/opencv2/ximgproc/fast_line_detector.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class CV_EXPORTS_W FastLineDetector : public Algorithm
6868
@param _canny_aperture_size 3 - Aperturesize for the sobel
6969
operator in Canny()
7070
@param _do_merge false - If true, incremental merging of segments
71-
will be perfomred
71+
will be performed
7272
*/
7373
CV_EXPORTS_W Ptr<FastLineDetector> createFastLineDetector(
7474
int _length_threshold = 10, float _distance_threshold = 1.414213562f,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#ifdef HAVE_OPENCV_XIMGPROC
2+
typedef cv::ximgproc::EdgeDrawing::Params EdgeDrawing_Params;
3+
#endif
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/python
2+
3+
'''
4+
This example illustrates how to use cv.ximgproc.EdgeDrawing class.
5+
6+
Usage:
7+
ed.py [<image_name>]
8+
image argument defaults to board.jpg
9+
'''
10+
11+
# Python 2/3 compatibility
12+
from __future__ import print_function
13+
14+
import numpy as np
15+
import cv2 as cv
16+
import random as rng
17+
import sys
18+
19+
rng.seed(12345)
20+
21+
def main():
22+
try:
23+
fn = sys.argv[1]
24+
except IndexError:
25+
fn = 'board.jpg'
26+
27+
src = cv.imread(cv.samples.findFile(fn))
28+
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
29+
cv.imshow("source", src)
30+
31+
ssrc = src.copy()*0
32+
lsrc = src.copy()
33+
esrc = src.copy()
34+
35+
ed = cv.ximgproc.createEdgeDrawing()
36+
37+
# you can change parameters (refer the documentation to see all parameters)
38+
EDParams = cv.ximgproc_EdgeDrawing_Params()
39+
EDParams.MinPathLength = 50 # try changing this value between 5 to 1000
40+
EDParams.PFmode = False # defaut value try to swich it to True
41+
EDParams.MinLineLength = 10 # try changing this value between 5 to 100
42+
EDParams.NFAValidation = True # defaut value try to swich it to False
43+
44+
ed.setParams(EDParams)
45+
46+
# Detect edges
47+
# you should call this before detectLines() and detectEllipses()
48+
ed.detectEdges(gray)
49+
segments = ed.getSegments()
50+
lines = ed.detectLines()
51+
ellipses = ed.detectEllipses()
52+
53+
#Draw detected edge segments
54+
for i in range(len(segments)):
55+
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
56+
cv.polylines(ssrc, [segments[i]], False, color, 1, cv.LINE_8)
57+
58+
cv.imshow("detected edge segments", ssrc)
59+
60+
#Draw detected lines
61+
if lines is not None: # Check if the lines have been found and only then iterate over these and add them to the image
62+
lines = np.uint16(np.around(lines))
63+
for i in range(len(lines)):
64+
cv.line(lsrc, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 1, cv.LINE_AA)
65+
66+
cv.imshow("detected lines", lsrc)
67+
68+
#Draw detected circles and ellipses
69+
if ellipses is not None: # Check if circles and ellipses have been found and only then iterate over these and add them to the image
70+
ellipses = np.uint16(np.around(ellipses))
71+
for i in range(len(ellipses)):
72+
color = (0, 0, 255)
73+
if ellipses[i][0][2] == 0:
74+
color = (0, 255, 0)
75+
cv.ellipse(esrc, (ellipses[i][0][0], ellipses[i][0][1]), (ellipses[i][0][2]+ellipses[i][0][3],ellipses[i][0][2]+ellipses[i][0][4]),ellipses[i][0][5],0, 360, color, 2, cv.LINE_AA)
76+
77+
cv.imshow("detected ellipses", esrc)
78+
cv.waitKey(0)
79+
print('Done')
80+
81+
82+
if __name__ == '__main__':
83+
print(__doc__)
84+
main()
85+
cv.destroyAllWindows()

modules/ximgproc/samples/fld_lines.cpp

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ using namespace cv::ximgproc;
1111

1212
int main(int argc, char** argv)
1313
{
14-
std::string in;
15-
cv::CommandLineParser parser(argc, argv, "{@input|../samples/data/corridor.jpg|input image}{help h||show help message}");
14+
string in;
15+
CommandLineParser parser(argc, argv, "{@input|corridor.jpg|input image}{help h||show help message}");
1616
if (parser.has("help"))
1717
{
1818
parser.printMessage();
1919
return 0;
2020
}
21-
in = parser.get<string>("@input");
21+
in = samples::findFile(parser.get<string>("@input"));
2222

2323
Mat image = imread(in, IMREAD_GRAYSCALE);
2424

@@ -40,7 +40,7 @@ int main(int argc, char** argv)
4040
// canny_aperture_size 3 - Aperturesize for the sobel
4141
// operator in Canny()
4242
// do_merge false - If true, incremental merging of segments
43-
// will be perfomred
43+
// will be performed
4444
int length_threshold = 10;
4545
float distance_threshold = 1.41421356f;
4646
double canny_th1 = 50.0;
@@ -50,27 +50,84 @@ int main(int argc, char** argv)
5050
Ptr<FastLineDetector> fld = createFastLineDetector(length_threshold,
5151
distance_threshold, canny_th1, canny_th2, canny_aperture_size,
5252
do_merge);
53-
vector<Vec4f> lines_fld;
53+
vector<Vec4f> lines;
5454

5555
// Because of some CPU's power strategy, it seems that the first running of
5656
// an algorithm takes much longer. So here we run the algorithm 10 times
5757
// to see the algorithm's processing time with sufficiently warmed-up
5858
// CPU performance.
59-
for(int run_count = 0; run_count < 10; run_count++) {
59+
for (int run_count = 0; run_count < 5; run_count++) {
6060
double freq = getTickFrequency();
61-
lines_fld.clear();
61+
lines.clear();
6262
int64 start = getTickCount();
6363
// Detect the lines with FLD
64-
fld->detect(image, lines_fld);
64+
fld->detect(image, lines);
6565
double duration_ms = double(getTickCount() - start) * 1000 / freq;
66-
std::cout << "Elapsed time for FLD " << duration_ms << " ms." << std::endl;
66+
cout << "Elapsed time for FLD " << duration_ms << " ms." << endl;
6767
}
6868

6969
// Show found lines with FLD
7070
Mat line_image_fld(image);
71-
fld->drawSegments(line_image_fld, lines_fld);
71+
fld->drawSegments(line_image_fld, lines);
7272
imshow("FLD result", line_image_fld);
7373

74+
waitKey(1);
75+
76+
Ptr<EdgeDrawing> ed = createEdgeDrawing();
77+
ed->params.EdgeDetectionOperator = EdgeDrawing::SOBEL;
78+
ed->params.GradientThresholdValue = 38;
79+
ed->params.AnchorThresholdValue = 8;
80+
81+
vector<Vec6d> ellipses;
82+
83+
for (int run_count = 0; run_count < 5; run_count++) {
84+
double freq = getTickFrequency();
85+
lines.clear();
86+
int64 start = getTickCount();
87+
88+
// Detect edges
89+
//you should call this before detectLines() and detectEllipses()
90+
ed->detectEdges(image);
91+
92+
// Detect lines
93+
ed->detectLines(lines);
94+
double duration_ms = double(getTickCount() - start) * 1000 / freq;
95+
cout << "Elapsed time for EdgeDrawing detectLines " << duration_ms << " ms." << endl;
96+
97+
start = getTickCount();
98+
// Detect circles and ellipses
99+
ed->detectEllipses(ellipses);
100+
duration_ms = double(getTickCount() - start) * 1000 / freq;
101+
cout << "Elapsed time for EdgeDrawing detectEllipses " << duration_ms << " ms." << endl;
102+
}
103+
104+
Mat edge_image_ed = Mat::zeros(image.size(), CV_8UC3);
105+
vector<vector<Point> > segments = ed->getSegments();
106+
107+
for (size_t i = 0; i < segments.size(); i++)
108+
{
109+
const Point* pts = &segments[i][0];
110+
int n = (int)segments[i].size();
111+
polylines(edge_image_ed, &pts, &n, 1, false, Scalar((rand() & 255), (rand() & 255), (rand() & 255)), 1);
112+
}
113+
114+
imshow("EdgeDrawing detected edges", edge_image_ed);
115+
116+
Mat line_image_ed(image);
117+
fld->drawSegments(line_image_ed, lines);
118+
119+
// Draw circles and ellipses
120+
for (size_t i = 0; i < ellipses.size(); i++)
121+
{
122+
Point center((int)ellipses[i][0], (int)ellipses[i][1]);
123+
Size axes((int)ellipses[i][2] + (int)ellipses[i][3], (int)ellipses[i][2] + (int)ellipses[i][4]);
124+
double angle(ellipses[i][5]);
125+
Scalar color = ellipses[i][2] == 0 ? Scalar(255, 255, 0) : Scalar(0, 255, 0);
126+
127+
ellipse(line_image_ed, center, axes, angle, 0, 360, color, 2, LINE_AA);
128+
}
129+
130+
imshow("EdgeDrawing result", line_image_ed);
74131
waitKey();
75132
return 0;
76133
}

0 commit comments

Comments
 (0)