实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)

导  读

    本文主要介绍如何在OpenCV中使用EdgeDrawing模块查找圆(详细步骤 + 代码)。

背景介绍

    从OpenCV4.5.2开始,Contrib模块中封装了开源库ED_Lib用于查找图像中的直线、线段、椭圆和圆。Github地址:

https://github.com/CihanTopal/ED_Lib

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第1张图片

    算法原理简介:

    边缘绘制(ED)算法是一种解决边缘检测问题的主动方法。与许多其他遵循减法方法的现有边缘检测算法相比(即在图像上应用梯度滤波器后,根据多种规则消除像素,例如 Canny 中的非极大值抑制和滞后),ED 算法通过加法策略工作,即逐一选取边缘像素,因此称为“边缘绘制”。然后我们处理这些随机形状的边缘段以提取更高级别的边缘特征,即直线、圆、椭圆等。从阈值梯度幅度中提取边缘像素的流行方法是非极大值抑制,它测试每个像素是否具有最大值沿其梯度方向的梯度响应,如果没有则消除。然而,此方法不检查相邻像素的状态,因此可能会导致低质量(在边缘连续性、平滑度、薄度、定位方面)边缘片段。ED 不是非极大值抑制,而是指向一组边缘像素,并通过最大化边缘段的总梯度响应来将它们连接起来。因此,它可以提取高质量的边缘片段,而不需要额外的滞后步骤。

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第2张图片

    OpenCV中使用介绍文档:

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

使用步骤

    EdgeDrawing类是在Contrib的ximgproc模块中,C++中使用它需要满足以下条件:

    ① OpenCV >= 4.5.2

    ② CMake编译Contrib模块

    ③ 包含edge_drawing.hpp头文件

    Python中使用需要安装opencv-python-contrib >=4.5.2

【1】Python中使用演示:​​​​​

#公众号--计算机视觉之家
'''This example illustrates how to use cv.ximgproc.EdgeDrawing class.
Usage:    ed.py []    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()

    执行指令:ed.py []

    实例1: edge_drawing.py 1.png

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第3张图片

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第4张图片

    实例2: edge_drawing.py 2.png

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第5张图片

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第6张图片

    实例3: edge_drawing.py 3.png

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第7张图片

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第8张图片

    上述图中,绿色表示找到的椭圆,红色表示找到的圆。当然,EdgeDrawing还可以获取边缘信息和查找直线,效果如下:

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第9张图片

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第10张图片

【2】C++中使用演示:

//公众号--计算机视觉之家
#include #include #include 
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(getTickCount()); //计时开始    Ptr 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;

    实例1: 

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第11张图片

    实例2: 

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第12张图片

    实例3:

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第13张图片

      

简单总结

    总体来说EdgeDrawing提供的找圆和直线的方法简单易用且效果好,简单情况下使用默认参数即可。参数调整可以参考文档自己尝试,这里挑几个常用的简单说明一下。​​​​​​​

Ptr 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】算法使用的梯度算子,可选4种,默认是PREWITT,大家可以设置不同的梯度算子尝试效果。

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第14张图片

【2】梯度阈值GradientThresholdValue,值越小,更能找到对比度低的圆。比如下面分别是梯度阈值为100和50的效果:

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第15张图片

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第16张图片

【3】NFAValidation:默认值为true。指示是否将NFA(错误警报数)算法用于直线和椭圆验证。设置为false时,能找到更多圆或直线。

【4】MinPathLength:最小连接像素长度处理以创建边缘段。在梯度图像中,为创建边缘段而处理的最小连接像素长度。具有高于GradientThresholdValue的值的像素将被处理,默认值为10。比如下面分别是比如下面分别是梯度阈值为50和10的效果(值越小,更小的圆被找到):

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第17张图片

实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)_第18张图片

你可能感兴趣的:(OpenCV,Python-OpenCV,opencv,人工智能,计算机视觉,图像处理,python)