当前位置:   article > 正文

opencv python 实现Canny检测后不连续不封闭轮廓的闭合_opencv怎么让未闭合的轮廓闭合

opencv怎么让未闭合的轮廓闭合

Canny检测后轮廓的闭合在网上看了一些相关文章后总结出有以下方法:

1、使用闭运算等形态学操作来对轮廓进行处理,但作为像素点级别 的形态学操作往往不能满足要求,如:两条轮廓线相距仅为一个像素,在进行闭运算操作时会使这两条轮廓粘连在一起。

2、对于规则的图像可通过对不连续的点或线段进行拟合,通过对称的修剪和补缺来处理,但适用的对象非常有限,所以只能特例分析。

3、找到图像中不连续轮廓中的端点,通过最近端点间画直线来处理,但这仅仅适用于简单的图像处理,对于一些复杂或者断续太大的轮廓反而效果比较差。

本章主要讲第三种方法,代码如下:

  1. import cv2
  2. import math
  3. import numpy as np
  4. import timeit
  5. start_time = timeit.default_timer()
  6. def point(img, h, w):
  7. p = []
  8. for i in range(h):
  9. for j in range(w):
  10. if img[i, j] == 255:
  11. r = []
  12. for y in range(i-1, i+2):
  13. for x in range(j-1, j+2):
  14. if y == i and x == j:
  15. continue
  16. if img[y, x] == 255:
  17. r.append((y, x))
  18. if len(r) > 0:
  19. if len(r) == 1:
  20. p.append((i, j))
  21. elif len(r) == 2:
  22. dy = r[0][0] - r[1][0]
  23. dx = r[0][1] - r[1][1]
  24. if abs(dy) + abs(dx) == 1:
  25. p.append((i, j))
  26. return p
  27. max_range = 30 # 设置最大的端点连线
  28. img = cv2.imread('dian.jpg')
  29. h, w, c = img.shape[:]
  30. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  31. img2 = cv2.bilateralFilter(gray, 5, 150, 150)
  32. ven = cv2.Canny(img2, 77, 220)
  33. points = point(ven, h, w)
  34. tu = np.zeros((h, w, c), np.uint8)
  35. tu[ven != 0] = 255
  36. tu1 = tu.copy()
  37. for i, j in points:
  38. tu[i, j, 0] = 0 #b
  39. tu[i, j, 1] = 0 #G
  40. tu[i, j, 2] = 255 # r
  41. cv2.imshow('tu', tu) # 查看端点
  42. for n, i in enumerate(points):
  43. points.pop(n)
  44. distances = [np.linalg.norm(np.array(p) - np.array(i)) for p in points] # 计算欧几里得距离
  45. min_index = np.argmin(distances) # 得到列表中最短距离的索引
  46. if i != points[min_index] and distances[min_index] <= max_range:
  47. cv2.line(tu1, tuple((i[1], i[0])), tuple((points[min_index][1], points[min_index][0])), (0, 0, 255), 1)
  48. cv2.imshow('dabo', tu1)
  49. end_time = timeit.default_timer()
  50. print("程序运行时间: ", end_time - start_time, "秒")
  51. cv2.waitKey(0)

一、程序分析

        在关于图像中端点的定义上,可分为如下情况:

 

 上两份对应着程序中len(r)==1的部分,下两份对应着程序中len(r)==2的部分

该部分程序实现了图像中不连续轮廓端点的寻找

  1. def point(img, h, w):
  2. p = []
  3. for i in range(h):
  4. for j in range(w):
  5. if img[i, j] == 255:
  6. r = []
  7. for y in range(i-1, i+2):
  8. for x in range(j-1, j+2):
  9. if y == i and x == j:
  10. continue
  11. if img[y, x] == 255:
  12. r.append((y, x))
  13. if len(r) > 0:
  14. if len(r) == 1:
  15. p.append((i, j))
  16. elif len(r) == 2:
  17. dy = r[0][0] - r[1][0]
  18. dx = r[0][1] - r[1][1]
  19. if abs(dy) + abs(dx) == 1:
  20. p.append((i, j))
  21. return p

 二、程序展示

        本人通过手动调整了Canny算子的阈值参数,对得到的图像进行端点的寻找后,用红色进行了标出,如下图:

下图即为最终的闭合图像,可通过调整最大画线距离max_range来控制画线

 

  1. for n, i in enumerate(points):
  2. points.pop(n)
  3. distances = [np.linalg.norm(np.array(p) - np.array(i)) for p in points] # 计算欧几里得距离
  4. min_index = np.argmin(distances) # 得到列表中最短距离的索引
  5. if i != points[min_index] and distances[min_index] <= max_range:
  6. cv2.line(tu1, tuple((i[1], i[0])), tuple((points[min_index][1], points[min_index][0])), (0, 0, 255), 1)
  7. cv2.imshow('dabo', tu1)

三,结果分析 

        可以看到结果是非常不如意的,所以本文章仅提供一个思路,并不能直接的解决一些实际问题,可以通过对端点连线处程序进行改进,使的能够对定性的端点进行连线闭合。

        如果有更好的办法欢迎各位在评论区留言!

参考文章:

Python OpenCV 连接不封闭的轮廓

canny边缘检测不连续问题

opencv 风挡轮廓补全

图像轮廓缺陷修补

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号