Canny检测后轮廓的闭合在网上看了一些相关文章后总结出有以下方法:
1、使用闭运算等形态学操作来对轮廓进行处理,但作为像素点级别 的形态学操作往往不能满足要求,如:两条轮廓线相距仅为一个像素,在进行闭运算操作时会使这两条轮廓粘连在一起。
2、对于规则的图像可通过对不连续的点或线段进行拟合,通过对称的修剪和补缺来处理,但适用的对象非常有限,所以只能特例分析。
3、找到图像中不连续轮廓中的端点,通过最近端点间画直线来处理,但这仅仅适用于简单的图像处理,对于一些复杂或者断续太大的轮廓反而效果比较差。
本章主要讲第三种方法,代码如下:
import cv2
import math
import numpy as np
import timeit
start_time = timeit.default_timer()
def point(img, h, w):
p = []
for i in range(h):
for j in range(w):
if img[i, j] == 255:
r = []
for y in range(i-1, i+2):
for x in range(j-1, j+2):
if y == i and x == j:
continue
if img[y, x] == 255:
r.append((y, x))
if len(r) > 0:
if len(r) == 1:
p.append((i, j))
elif len(r) == 2:
dy = r[0][0] - r[1][0]
dx = r[0][1] - r[1][1]
if abs(dy) + abs(dx) == 1:
p.append((i, j))
return p
max_range = 30 # 设置最大的端点连线
img = cv2.imread('dian.jpg')
h, w, c = img.shape[:]
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = cv2.bilateralFilter(gray, 5, 150, 150)
ven = cv2.Canny(img2, 77, 220)
points = point(ven, h, w)
tu = np.zeros((h, w, c), np.uint8)
tu[ven != 0] = 255
tu1 = tu.copy()
for i, j in points:
tu[i, j, 0] = 0 #b
tu[i, j, 1] = 0 #G
tu[i, j, 2] = 255 # r
cv2.imshow('tu', tu) # 查看端点
for n, i in enumerate(points):
points.pop(n)
distances = [np.linalg.norm(np.array(p) - np.array(i)) for p in points] # 计算欧几里得距离
min_index = np.argmin(distances) # 得到列表中最短距离的索引
if i != points[min_index] and distances[min_index] <= max_range:
cv2.line(tu1, tuple((i[1], i[0])), tuple((points[min_index][1], points[min_index][0])), (0, 0, 255), 1)
cv2.imshow('dabo', tu1)
end_time = timeit.default_timer()
print("程序运行时间: ", end_time - start_time, "秒")
cv2.waitKey(0)
一、程序分析
在关于图像中端点的定义上,可分为如下情况:
上两份对应着程序中len(r)==1的部分,下两份对应着程序中len(r)==2的部分
该部分程序实现了图像中不连续轮廓端点的寻找
def point(img, h, w):
p = []
for i in range(h):
for j in range(w):
if img[i, j] == 255:
r = []
for y in range(i-1, i+2):
for x in range(j-1, j+2):
if y == i and x == j:
continue
if img[y, x] == 255:
r.append((y, x))
if len(r) > 0:
if len(r) == 1:
p.append((i, j))
elif len(r) == 2:
dy = r[0][0] - r[1][0]
dx = r[0][1] - r[1][1]
if abs(dy) + abs(dx) == 1:
p.append((i, j))
return p
二、程序展示
本人通过手动调整了Canny算子的阈值参数,对得到的图像进行端点的寻找后,用红色进行了标出,如下图:
下图即为最终的闭合图像,可通过调整最大画线距离max_range来控制画线
for n, i in enumerate(points):
points.pop(n)
distances = [np.linalg.norm(np.array(p) - np.array(i)) for p in points] # 计算欧几里得距离
min_index = np.argmin(distances) # 得到列表中最短距离的索引
if i != points[min_index] and distances[min_index] <= max_range:
cv2.line(tu1, tuple((i[1], i[0])), tuple((points[min_index][1], points[min_index][0])), (0, 0, 255), 1)
cv2.imshow('dabo', tu1)
三,结果分析
可以看到结果是非常不如意的,所以本文章仅提供一个思路,并不能直接的解决一些实际问题,可以通过对端点连线处程序进行改进,使的能够对定性的端点进行连线闭合。
如果有更好的办法欢迎各位在评论区留言!
参考文章:
Python OpenCV 连接不封闭的轮廓
canny边缘检测不连续问题
opencv 风挡轮廓补全文章来源:https://www.toymoban.com/news/detail-851118.html
图像轮廓缺陷修补文章来源地址https://www.toymoban.com/news/detail-851118.html
到了这里,关于opencv python 实现Canny检测后不连续不封闭轮廓的闭合的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!