• 改进的最大内切圆算法求裂缝轮廓宽度


    前段时间我将网上最大内切圆算法进行了代码的整理,原先博主上传的代码稍微有点乱,可能也是它自己使用,大家可以看这篇整理好的:最大内切圆算法计算裂缝宽度

    最大内切圆算法详解

    一个圆与给定的多边形或曲线的每一条边或曲线都相切的圆。而我们就是需要计算的是给定图像的轮廓的最大内切圆,也就是与轮廓的每一条边都相切的圆中直径最大的圆。这样直径就是我们的轮廓的宽度了。

    既然要求轮廓的内接圆,从圆的特点来说,想要唯一的确定一个圆,就是要知道它的圆心和半径。好的,那现在的问题就从求取轮廓的内接圆,巧妙地转变成求取某个点和一个多边形的距离和关系。

    opencv中有一个函数pointPolygonTest就是能够得到某个点和某个多边形之间的关系,例如这个点是在多边形内部、外部、或者是在多边形上,还能得到该点距离多边形的像素距离。那问题其实就很好解决了。我们再使用cv2.minMaxLoc(src)来获得给定的数组中寻找最小值和最大值的位置,它的语法如下

    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(src)

    其中,src是输入的数组或图像。函数会返回最小值min_val和最大值max_val,以及它们在数组中的位置最小值的位置min_loc和最大值的位置max_loc。 

    讲到这里我想大家也知道怎么求轮廓的宽度了吧,即为:max_loc * 2。

    详细代码

    1. import cv2
    2. import string
    3. import numpy as np
    4. import pyzjr as pz
    5. def incircle(img, contours_arr, color=(0, 0, 255)):
    6. """
    7. 轮廓最大内切圆算法,所有轮廓当中的内切圆
    8. """
    9. result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    10. raw_dist = np.zeros(img.shape, dtype=np.float32)
    11. letters = list(string.ascii_uppercase)
    12. label = {}
    13. for k, contours in enumerate(contours_arr):
    14. for i in range(img.shape[0]):
    15. for j in range(img.shape[1]):
    16. raw_dist[i, j] = cv2.pointPolygonTest(contours, (j, i), True)
    17. min_val, max_val, _, max_dist_pt = cv2.minMaxLoc(raw_dist)
    18. label[letters[k]] = max_val * 2
    19. radius = int(max_val)
    20. cv2.circle(result, max_dist_pt, radius, color, 1, 1, 0)
    21. return result, label
    22. if __name__=="__main__":
    23. path = r"D:\PythonProject\RoadCrack\dimension2_data\num/001.png"
    24. img = cv2.imread(path)
    25. gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    26. thresh = pz.BinaryImg(img)
    27. contours_arr, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    28. result, label = incircle(gray_img, contours_arr)
    29. print("裂缝宽度:",label)
    30. cv2.imwrite("result.png",result)

    先检测轮廓,你可以使用opencv的findContours。需要确保是ndarray数组的形式。

    裂缝宽度: {'A': 5.656854152679443, 'B': 4.4721360206604}

    现在我们就能知道两条裂缝对应的最大内切圆直径,即裂缝的宽度。

    算法对比

    并且从时间角度来看:

    • 原先的最大内切圆算法: 1.79125 sec
    • 改进后的内切圆算法:  1.05487 sec

    从计算的直径上来看:

    • 原先的最大内切圆算法:13.81
    • 改进后的内切圆算法:{'A': 14.0}

    这里的实现比较简单,只是嵌套的循环比较多,但能存储每条裂缝对应的宽度。


    2023/10/22更新
    1. # pip install pyzjr==1.2.5
    2. import cv2
    3. import pyzjr as pz
    4. from pyzjr.augmentation import incircle
    5. if __name__=="__main__":
    6. path = r"D:\PythonProject\RoadCrack\dimension2_data\num/001.png"
    7. img = cv2.imread(path)
    8. gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    9. thresh = pz.BinaryImg(img)
    10. contours_arr, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    11. result, label = incircle(gray_img, contours_arr)
    12. print("裂缝宽度:",label)
    13. cv2.imwrite("result.png",result)
  • 相关阅读:
    高并发高可用之RabbitMQ
    [附源码]SSM计算机毕业设计影院售票系统JAVA
    Flutter之安卓端极光推送使用
    Oracle中的索引和分区
    菜鸟学Kubernetes(K8s)系列——(番外)安装Ingress-Nginx(工作原理)
    MySQL (2)
    Spring高手之路——深入理解与实现IOC依赖查找与依赖注入
    管理学复习重点
    HashMap与HashTable、HashSet的区别
    两数之和-(哈希)
  • 原文地址:https://blog.csdn.net/m0_62919535/article/details/133387359