Actual combat | A more stable and faster method of finding circles in OpenCV--EdgeDrawing demonstration (detailed steps + code)

guide

    This article mainly introduces how to use the EdgeDrawing module to find circles in OpenCV (detailed steps + code).

background introduction

    Starting from OpenCV4.5.2, the open source library ED_Lib is encapsulated in the Contrib module to find straight lines, line segments, ellipses and circles in images. Github address:

https://github.com/CihanTopal/ED_Lib

picture

    Introduction to algorithm principle:

    The Edge Drawing (ED) algorithm is an active approach to the edge detection problem. In contrast to many other existing edge detection algorithms that follow a subtractive approach (i.e., after applying a gradient filter on the image, pixels are eliminated according to multiple rules, such as non-maximum suppression and hysteresis in Canny), the ED algorithm adopts an additive strategy The work is to select the edge pixels one by one, so it is called "edge drawing". We then process these randomly shaped edge segments to extract higher level edge features, i.e. lines, circles, ellipses, etc. A popular method for extracting edge pixels from thresholded gradient magnitudes is non-maximum suppression, which tests whether each pixel has a maximum gradient response along its gradient direction, and eliminates it if not. However, this method does not check the state of adjacent pixels, so may result in low-quality (in terms of edge continuity, smoothness, thinness, positioning) edge fragments. Instead of non-maximum suppression, ED targets a set of edge pixels and connects them by maximizing the total gradient response of edge segments. Therefore, it can extract high-quality edge fragments without additional lag steps.

picture

    Introductory documents used in OpenCV:

https://docs.opencv.org/4.5.2/d1/d1c/classcv_1_1ximgproc_1_1EdgeDrawing.html

      

Steps for usage

    The EdgeDrawing class is in Contrib's ximgproc module, and it needs to meet the following conditions to use it in C++:

    ① OpenCV >= 4.5.2

    ② CMake compiles the Contrib module

    ③ Include edge_drawing.hpp header file

    Use in Python needs to install opencv-python-contrib >=4.5.2

[1] Demonstration in 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 compatibilityfrom __future__ import print_function
import numpy as npimport cv2 as cvimport random as rngimport 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 = 20     # 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 segmentsfor 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 linesif 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 ellipsesif ellipses is not None: # Check if circles and ellipses have been found and only then iterate over these and add them to the imagefor i in range(len(ellipses)):            center = (int(ellipses[i][0][0]), int(ellipses[i][0][1]))            axes = (int(ellipses[i][0][2])+int(ellipses[i][0][3]),int(ellipses[i][0][2])+int(ellipses[i][0][4]))            angle = ellipses[i][0][5]            color = (0, 0, 255)if ellipses[i][0][2] == 0:                color = (0, 255, 0)            cv.ellipse(esrc, center, axes, angle,0, 360, color, 2, cv.LINE_AA)
    cv.imshow("detected circles and ellipses", esrc)    cv.waitKey(0)    print('Done')

if __name__ == '__main__':    print(__doc__)    main()    cv.destroyAllWindows()

    Execution command: ed.py [<image_name>]

    Example 1: edge_drawing.py 1.png

picture

picture

    Example 2: edge_drawing.py 2.png

picture

picture

    Example 3: edge_drawing.py 3.png

picture

picture

    In the above figure, green indicates found ellipses, and red indicates found circles. Of course, EdgeDrawing can also obtain edge information and find straight lines, the effect is as follows:

picture

picture

[2] Demonstration in C++:

//公众号--计算机视觉之家
#include <iostream>#include <opencv2/opencv.hpp>#include <opencv2/ximgproc/edge_drawing.hpp>
using namespace std;using namespace cv;using namespace ximgproc;
int main(){
   
     Mat src = imread("./imgs/11.bmp");  if (src.empty())  {
   
       cout << "src image is empty, check again!" << endl;    return -1;  }  //resize(src, src, Size(), 0.2, 0.2);  imshow("src", src);  Mat gray;  cvtColor(src, gray, COLOR_BGR2GRAY);
  double start = static_cast<double>(getTickCount()); //计时开始    Ptr<EdgeDrawing> ed = createEdgeDrawing();  ed->params.EdgeDetectionOperator = EdgeDrawing::PREWITT;  ed->params.MinPathLength = 50; // try changing this value between 5 to 1000  ed->params.PFmode = false; //defaut value try to swich it to true  ed->params.MinLineLength = 10; // try changing this value between 5 to 100  ed->params.NFAValidation = false; // defaut value try to swich it to false  ed->params.GradientThresholdValue = 20;

    Example 1: 

picture

    Example 2: 

picture

    Example 3:

picture

      

brief summary

    Generally speaking, the method of finding circles and straight lines provided by EdgeDrawing is easy to use and has good effect. In simple cases, the default parameters can be used. For parameter adjustment, you can refer to the documentation and try it yourself. Here are a few commonly used ones for a brief explanation. ​​​​​​​​

Ptr<EdgeDrawing> ed = createEdgeDrawing();ed->params.EdgeDetectionOperator = EdgeDrawing::LSD;ed->params.MinPathLength = 50; // try changing this value between 5 to 1000ed->params.PFmode = false; //defaut value try to swich it to trueed->params.MinLineLength = 10; // try changing this value between 5 to 100ed->params.NFAValidation = true; // defaut value try to swich it to falseed->params.GradientThresholdValue = 20;

[1] The gradient operator used by the algorithm can be selected from 4 types, and the default is PREWITT. You can set different gradient operators to try out the effect.

picture

[2] GradientThresholdValue, the smaller the value, the more circles with low contrast can be found. For example, the following are the effects of gradient thresholds of 100 and 50 respectively:

picture

picture

【3】NFAValidation: The default value is true. Indicates whether to use the NFA (number of false alarms) algorithm for line and ellipse validation. When set to false, more circles or lines can be found.

【4】MinPathLength: Minimum connection pixel length processing to create edge segments. In gradient images, the minimum length of connected pixels processed to create edge segments. Pixels with a value higher than GradientThresholdValue will be processed, the default is 10. For example, the following are the effects of gradient thresholds of 50 and 10 respectively (the smaller the value, the smaller the circle is found):

picture

picture

Guess you like

Origin blog.csdn.net/stq054188/article/details/132257149