opencv特征提取,opencv 算法精解
本文主要介绍opencv骨架提取的算法步骤。
00-1010前言1。算法步骤1。算法步骤2。分析2。代码实现1。预处理2。骨架提取实现
目录
个人骨骼提取是开放操作过程的不可逆性。
前言
一.算法步骤
首先对比一下官方的算法步骤:
1.获取原始图像的第一个地址,图像的宽度和高度,并设置循环标志1。
2.用结构元素蚀刻原始图像,并保存腐蚀结果。
3.将循环标志设置为0。如果腐蚀结果中有一点是255,即原始图像还没有完全腐蚀成空集,则将循环标志设置为1。
4.打开具有结构元素的蚀刻图像(消除小的白色区域),并计算蚀刻和打开操作之间的差异(消除白色区域)。
5.利用[4]中得到的结果与之前得到的骨架进行并运算,从而得到本次循环得到的骨架。
6.将此循环中保存的腐蚀结果指定给原始图像。
7.重复步骤[2]-[6],直到原始图像被腐蚀成空集。
最终的骨架就是结果。
1.算法步骤
作者的理解是这样的:
输入:img(二进制图像)
输出:out(图像与img形状相同,初始化全为0)
而img的像素值为255(在这个循环中,我们的二值图像被腐蚀到全黑)为:
蚀刻img图像
img上的开放操作
Img2=打开操作之前的图像减去打开操作之后的图像。
out=img2
在外
先说开放操作,就是先蚀刻图像,再进行扩展。上面的核心点就是这一步(img2=打开操作前的图像减去打开操作后的图像)。这里为什么说个人感觉骨架的提取是开运算过程的不可逆?我们来分析一下这个开放的操作流程:
1.如果打开操作后的图像与打开操作前的图像不同,如下图所示:
可以看到,这张图中的白色部分大部分都比较小。我们打开这张图,先腐蚀,很容易让一些白色的部分消失。然后在这个白色部分消失后,我们将腐蚀的图片展开,消失的白色部分无法展开回来。这些缺失的部分是开放操作过程中不可逆的部分。
然后我们在后面(img2=打开操作前的图像减去打开操作后的图像)。这一步我们得到开运算过程中消失的白色部分,也就是开运算过程中不可逆的部分,然后叠加在out上。
然后通过不断腐蚀,打开图像,在打开操作中得到所有这些图像的不可逆部分,得到我们的骨架。
2.如果打开操作后的图像与打开操作前的图像不同,那么在这种情况下,我们得到img2中的每个元素在这一步都是0(img 2=打开操作前的图像减去打开操作后的图像)。然后在后面的步骤out=img2中,out等价于相同,下一个循环继续把白色部分侵蚀得更小,直到不可逆部分出现在开运算中,然后叠加在out上。
所以,粗略来说,骨架提取就是不断侵蚀和细化我们的前景区域,直到前景被压缩到更精细的程度。这是我们骨架提取的部分。
2.分析
二.代码实现
我们这里的图片是作为灰度图片读入的,然后需要阈值处理才能转换成二值图像。
那么我们的图片可能会受到其他一些大噪音的影响。首先我们对图像进行腐蚀,手动过滤掉一些过滤可能过滤不掉的大噪音。
用来选择一个好的二元图。
导入cv2
将numpy作为np导入
导入操作系统
定义细化(img_path):
img=cv2.imread(img_path,cv2。IMREAD _灰度)
# thresh,img=cv2.threshold(img,0,255,cv2。THRESH_BINARY cv2。OTSU)
thresh,img=cv2.threshold(img,50,255,cv2。阈值_
BINARY)
h, w = img.shape[0:2]
#前景背景反转
for i in range(h):
for j in range(w):
if img[i, j] == 255:
img[i, j] = 0
else:
img[i, j] = 255
cv2.namedWindow("binary", 0)
cv2.resizeWindow("binary", 640, 480)
cv2.imshow(binary, img)
dst = img.copy()
num_erode = 0
while (True):
if np.sum(dst) == 0:
break
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
dst = cv2.erode(dst, kernel)
cv2.namedWindow("z", 0)
cv2.resizeWindow("z", 640, 480)
cv2.imshow(z, dst)
c = cv2.waitKey(0)
if c == ord("q"):
print("保存")
cv2.imwrite("./refine.png", dst)
break
num_erode = num_erode + 1
if __name__ == __main__:
refine("input.png")
在这里需要注意的是我们对图像进行二值化可能会将我们的背景和前景反转,在这里我们需要反转回来。否则的话把反转的代码注释掉即可。
我的原图如下:
然后经过腐蚀的图片如下:
2. 骨架提取实现
然后下面就是骨架提取的代码了:
骨架提取 import cv2 import numpy as np #由于我们经过之前的代码转换到了二值图,所以这里不需要转换 img = cv2.imread(refine.png, cv2.IMREAD_GRAYSCALE) dst = img.copy() skeleton = np.zeros(dst.shape, np.uint8) while (True): if np.sum(dst) == 0: break kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (7, 7)) dst = cv2.erode(dst, kernel, None, None, 1) open_dst = cv2.morphologyEx(dst, cv2.MORPH_OPEN, kernel) result = dst - open_dst skeleton = skeleton + result cv2.waitKey(1) cv2.namedWindow("result",0) cv2.resizeWindow("result",640,480) cv2.imshow(result, skeleton) cv2.imwrite("output.png",skeleton) cv2.waitKey(0) cv2.destroyAllWindows()
在这里我们可以通过开运算的结果元大小来稍微调整一下提取的骨架粗细。
77开运算结构元提取的骨架如下:
55开运算结构元提取的骨架如下:
到此这篇关于深入解析opencv骨架提取的算法步骤的文章就介绍到这了,更多相关opencv骨架提取内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。