Skip to content

Test ED_Lib #2313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions modules/ximgproc/doc/ximgproc.bib
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,47 @@ @inproceedings{BarronPoole2016
publisher={Springer International Publishing},
pages={617--632},
}

@article{topal2012edge,
title={Edge drawing: a combined real-time edge and segment detector},
author={Topal, Cihan and Akinlar, Cuneyt},
journal={Journal of Visual Communication and Image Representation},
volume={23},
number={6},
pages={862--872},
year={2012},
publisher={Elsevier}
}

@article{akinlar2011edlines,
title={EDLines: A real-time line segment detector with a false detection control},
author={Akinlar, Cuneyt and Topal, Cihan},
journal={Pattern Recognition Letters},
volume={32},
number={13},
pages={1633--1642},
year={2011},
publisher={Elsevier}
}

@article{akinlar2012edpf,
title={EDPF: a real-time parameter-free edge segment detector with a false detection control},
author={Akinlar, Cuneyt and Topal, Cihan},
journal={International Journal of Pattern Recognition and Artificial Intelligence},
volume={26},
number={01},
pages={1255002},
year={2012},
publisher={World Scientific}
}

@article{akinlar2013edcircles,
title={EDCircles: A real-time circle detector with a false detection control},
author={Akinlar, Cuneyt and Topal, Cihan},
journal={Pattern Recognition},
volume={46},
number={3},
pages={725--740},
year={2013},
publisher={Elsevier}
}
3 changes: 3 additions & 0 deletions modules/ximgproc/include/opencv2/ximgproc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "ximgproc/sparse_match_interpolator.hpp"
#include "ximgproc/structured_edge_detection.hpp"
#include "ximgproc/edgeboxes.hpp"
#include "ximgproc/edge_drawing.hpp"
#include "ximgproc/seeds.hpp"
#include "ximgproc/segmentation.hpp"
#include "ximgproc/fast_hough_transform.hpp"
Expand Down Expand Up @@ -75,6 +76,8 @@ i.e. algorithms which somehow takes into account pixel affinities in natural ima

@defgroup ximgproc_fast_line_detector Fast line detector

@defgroup ximgproc_edge_drawing EdgeDrawing

@defgroup ximgproc_fourier Fourier descriptors
@}
*/
Expand Down
115 changes: 115 additions & 0 deletions modules/ximgproc/include/opencv2/ximgproc/edge_drawing.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

#ifndef __OPENCV_EDGE_DRAWING_HPP__
#define __OPENCV_EDGE_DRAWING_HPP__

#include <opencv2/core.hpp>

namespace cv
{
namespace ximgproc
{

//! @addtogroup ximgproc_edge_drawing
//! @{

/** @brief Class implementing the ED (EdgeDrawing) @cite topal2012edge, EDLines @cite akinlar2011edlines, EDPF @cite akinlar2012edpf and EDCircles @cite akinlar2013edcircles algorithms

EDGE DRAWING LIBRARY FOR GEOMETRIC FEATURE EXTRACTION AND VALIDATION

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
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
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
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
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
neighboring pixels, and therefore might result low quality (in terms of edge continuity, smoothness, thinness, localization) edge segments. Instead of non-maximal supression,
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
an additional hysteresis step.
*/

class CV_EXPORTS_W EdgeDrawing : public Algorithm
{
public:

enum GradientOperator
{
PREWITT = 0,
SOBEL = 1,
SCHARR = 2,
LSD = 3
};

struct CV_EXPORTS_W_SIMPLE Params
{
CV_WRAP Params();
//! Parameter Free mode will be activated when this value is true.
CV_PROP_RW bool PFmode;
//! indicates the operator used for gradient calculation.The following operation flags are available(cv::ximgproc::EdgeDrawing::GradientOperator)
CV_PROP_RW int EdgeDetectionOperator;
//! threshold value used to create gradient image.
CV_PROP_RW int GradientThresholdValue;
//! threshold value used to create gradient image.
CV_PROP_RW int AnchorThresholdValue;
CV_PROP_RW int ScanInterval;
//! minimun connected pixels length processed to create an edge segment.
CV_PROP_RW int MinPathLength;
//! sigma value for internal GaussianBlur() function.
CV_PROP_RW float Sigma;
CV_PROP_RW bool SumFlag;
//! when this value is true NFA (Number of False Alarms) algorithm will be used for line and ellipse validation.
CV_PROP_RW bool NFAValidation;
//! minimun line length to detect.
CV_PROP_RW int MinLineLength;
CV_PROP_RW double MaxDistanceBetweenTwoLines;
CV_PROP_RW double LineFitErrorThreshold;
CV_PROP_RW double MaxErrorThreshold;

void read(const FileNode& fn);
void write(FileStorage& fs) const;
};

/** @brief Detects edges and prepares them to detect lines and ellipses.

@param src input image
*/
CV_WRAP virtual void detectEdges(InputArray src) = 0;
CV_WRAP virtual void getEdgeImage(OutputArray dst) = 0;
CV_WRAP virtual void getGradientImage(OutputArray dst) = 0;

CV_WRAP virtual std::vector<std::vector<Point> > getSegments() = 0;

/** @brief Detects lines.

@param lines output Vec<4f> contains start point and end point of detected lines.
@note you should call detectEdges() method before call this.
*/
CV_WRAP virtual void detectLines(OutputArray lines) = 0;

/** @brief Detects circles and ellipses.

@param ellipses output Vec<6d> contains center point and perimeter for circles.
@note you should call detectEdges() method before call this.
*/
CV_WRAP virtual void detectEllipses(OutputArray ellipses) = 0;

CV_WRAP Params params;

/** @brief sets parameters.

this function is meant to be used for parameter setting in other languages than c++.
*/
CV_WRAP void setParams(const EdgeDrawing::Params& parameters);
virtual ~EdgeDrawing() { }
};

/** @brief Creates a smart pointer to a EdgeDrawing object and initializes it
*/
CV_EXPORTS_W Ptr<EdgeDrawing> createEdgeDrawing();
//! @}

}
}

#endif /* __OPENCV_EDGE_DRAWING_HPP__ */
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class CV_EXPORTS_W FastLineDetector : public Algorithm
@param _canny_aperture_size 3 - Aperturesize for the sobel
operator in Canny()
@param _do_merge false - If true, incremental merging of segments
will be perfomred
will be performed
*/
CV_EXPORTS_W Ptr<FastLineDetector> createFastLineDetector(
int _length_threshold = 10, float _distance_threshold = 1.414213562f,
Expand Down
3 changes: 3 additions & 0 deletions modules/ximgproc/misc/python/pyopencv_ximgproc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#ifdef HAVE_OPENCV_XIMGPROC
typedef cv::ximgproc::EdgeDrawing::Params EdgeDrawing_Params;
#endif
85 changes: 85 additions & 0 deletions modules/ximgproc/samples/edge_drawing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/python

'''
This example illustrates how to use cv.ximgproc.EdgeDrawing class.

Usage:
ed.py [<image_name>]
image argument defaults to board.jpg
'''

# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2 as cv
import random as rng
import sys

rng.seed(12345)

def main():
try:
fn = sys.argv[1]
except IndexError:
fn = 'board.jpg'

src = cv.imread(cv.samples.findFile(fn))
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
cv.imshow("source", src)

ssrc = src.copy()*0
lsrc = src.copy()
esrc = src.copy()

ed = cv.ximgproc.createEdgeDrawing()

# you can change parameters (refer the documentation to see all parameters)
EDParams = cv.ximgproc_EdgeDrawing_Params()
EDParams.MinPathLength = 50 # try changing this value between 5 to 1000
EDParams.PFmode = False # defaut value try to swich it to True
EDParams.MinLineLength = 10 # try changing this value between 5 to 100
EDParams.NFAValidation = True # defaut value try to swich it to False

ed.setParams(EDParams)

# Detect edges
# you should call this before detectLines() and detectEllipses()
ed.detectEdges(gray)
segments = ed.getSegments()
lines = ed.detectLines()
ellipses = ed.detectEllipses()

#Draw detected edge segments
for i in range(len(segments)):
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
cv.polylines(ssrc, [segments[i]], False, color, 1, cv.LINE_8)

cv.imshow("detected edge segments", ssrc)

#Draw detected lines
if lines is not None: # Check if the lines have been found and only then iterate over these and add them to the image
lines = np.uint16(np.around(lines))
for i in range(len(lines)):
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)

cv.imshow("detected lines", lsrc)

#Draw detected circles and ellipses
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
ellipses = np.uint16(np.around(ellipses))
for i in range(len(ellipses)):
color = (0, 0, 255)
if ellipses[i][0][2] == 0:
color = (0, 255, 0)
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)

cv.imshow("detected ellipses", esrc)
cv.waitKey(0)
print('Done')


if __name__ == '__main__':
print(__doc__)
main()
cv.destroyAllWindows()
77 changes: 67 additions & 10 deletions modules/ximgproc/samples/fld_lines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ using namespace cv::ximgproc;

int main(int argc, char** argv)
{
std::string in;
cv::CommandLineParser parser(argc, argv, "{@input|../samples/data/corridor.jpg|input image}{help h||show help message}");
string in;
CommandLineParser parser(argc, argv, "{@input|corridor.jpg|input image}{help h||show help message}");
if (parser.has("help"))
{
parser.printMessage();
return 0;
}
in = parser.get<string>("@input");
in = samples::findFile(parser.get<string>("@input"));

Mat image = imread(in, IMREAD_GRAYSCALE);

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

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

// Show found lines with FLD
Mat line_image_fld(image);
fld->drawSegments(line_image_fld, lines_fld);
fld->drawSegments(line_image_fld, lines);
imshow("FLD result", line_image_fld);

waitKey(1);

Ptr<EdgeDrawing> ed = createEdgeDrawing();
ed->params.EdgeDetectionOperator = EdgeDrawing::SOBEL;
ed->params.GradientThresholdValue = 38;
ed->params.AnchorThresholdValue = 8;

vector<Vec6d> ellipses;

for (int run_count = 0; run_count < 5; run_count++) {
double freq = getTickFrequency();
lines.clear();
int64 start = getTickCount();

// Detect edges
//you should call this before detectLines() and detectEllipses()
ed->detectEdges(image);

// Detect lines
ed->detectLines(lines);
double duration_ms = double(getTickCount() - start) * 1000 / freq;
cout << "Elapsed time for EdgeDrawing detectLines " << duration_ms << " ms." << endl;

start = getTickCount();
// Detect circles and ellipses
ed->detectEllipses(ellipses);
duration_ms = double(getTickCount() - start) * 1000 / freq;
cout << "Elapsed time for EdgeDrawing detectEllipses " << duration_ms << " ms." << endl;
}

Mat edge_image_ed = Mat::zeros(image.size(), CV_8UC3);
vector<vector<Point> > segments = ed->getSegments();

for (size_t i = 0; i < segments.size(); i++)
{
const Point* pts = &segments[i][0];
int n = (int)segments[i].size();
polylines(edge_image_ed, &pts, &n, 1, false, Scalar((rand() & 255), (rand() & 255), (rand() & 255)), 1);
}

imshow("EdgeDrawing detected edges", edge_image_ed);

Mat line_image_ed(image);
fld->drawSegments(line_image_ed, lines);

// Draw circles and ellipses
for (size_t i = 0; i < ellipses.size(); i++)
{
Point center((int)ellipses[i][0], (int)ellipses[i][1]);
Size axes((int)ellipses[i][2] + (int)ellipses[i][3], (int)ellipses[i][2] + (int)ellipses[i][4]);
double angle(ellipses[i][5]);
Scalar color = ellipses[i][2] == 0 ? Scalar(255, 255, 0) : Scalar(0, 255, 0);

ellipse(line_image_ed, center, axes, angle, 0, 360, color, 2, LINE_AA);
}

imshow("EdgeDrawing result", line_image_ed);
waitKey();
return 0;
}
Loading