首先根据这篇博文https://www.cnblogs.com/xianglan/archive/2011/01/01/1923779.html,自己重新编写python代码,由于出现局部错误,导致出现了一些奇妙结果,因此写就过程如下:
结果一:
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 10 14:35:27 2019
@author: 高行吟
"""
import numpy as np
def Get_skeleton_line(img):
table = [0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,\
1,1,0,0,1,1,1,0,1,1,0,0,1,0,0,0]
r , c = img.shape
line_img = np.zeros((r , c))
new_img = np.zeros((r + 2 , c + 2))##由于本程序以窗口遍历,因此原矩阵四个方向均增加一个全零边,方便计算
new_img[1:-1 , 1:-1] = img
new_img = np.where(new_img == 1 , 0 , 1)###由于目标区域值为1,而查表法规定,一旦像素为目标,则其权重为0,因此将矩阵所有值全部反向,即是0→1,1→0,方便与权重模板temp做乘法计算
temp = np.array([[1 , 2 , 4] , [8 , 0 , 16] , [32 , 64 , 128]])###权重矩阵
for i in range(1 , r+1):
for j in range(1 , c+1):
line_img[i-1 , j-1] = table[(new_img[i-1:i+2 , j-1:j+2]*temp).sum()]###窗口矩阵与模板相乘,其和即为表索引
return line_img
上述代码处理一副图前后如下:
原图 二值图 处理后
可以看到,本来使用查表法是提取骨骼线的,结果却得到了边界线,结果似乎还很好?也可能本人孤陋寡闻,大方勿笑,反正感觉很奇妙,因此记录下来,以便以后提取边界线时查看。
按照本人理解,应该是倒数第二行代码问题,该行代码将查表后计算的值赋予到一个新的矩阵,并没有对后续查表计算产生影影响,这是不合理的,当中心点完全处于二值图内部时(即是3×3矩阵完全在目标区域内),计算得到的表索引将为0,查表得到的值同样为0,最终在与二值图目标区域内部的相同位置上,新矩阵的值同样为0,因此导致上述情况。
结果二:
按上述理解改正代码后如下:
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 10 14:35:27 2019
@author: 高行吟
"""
import numpy as np
def Get_skeleton_line(img):
table = [0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,\
1,1,0,0,1,1,1,0,1,1,0,0,1,0,0,0]
r , c = img.shape
# line_img = np.zeros((r , c))
new_img = np.zeros((r + 2 , c + 2))##由于本程序以窗口遍历,因此原矩阵四个方向均增加一个全零边,方便计算
new_img[1:-1 , 1:-1] = img
new_img = np.where(new_img == 1 , 0 , 1)###由于目标区域值为1,而查表法规定,一旦像素为目标,则其权重为0,因此将矩阵所有值全部反向,即是0→1,1→0,方便与权重模板temp做乘法计算
temp = np.array([[1 , 2 , 4] , [8 , 0 , 16] , [32 , 64 , 128]])###权重矩阵
for i in range(1 , r+1):
for j in range(1 , c+1):
# line_img[i-1 , j-1] = table[(new_img[i-1:i+2 , j-1:j+2]*temp).sum()]######窗口矩阵与模板相乘,其和即为表索引
new_img[i , j] = table[(new_img[i-1:i+2 , j-1:j+2]*temp).sum()]
return new_img[1:-1 , 1:-1]#line_img
但结果仍然未达到目的,提取的仍然不是骨骼线,但生成的图案却,,,怎么说呢,反正是很特殊,是自己平时想要获取类似的图案都无法着手的那种,而且总感觉这种图案会有些用处,但目前还想不到可以用在什么地方。。。
结果图如下,还是上面那副素材:
原图 二值图 处理后
经过与原博客代码对照,发现问题应出现在处理范围上,原博客仅针对目标像素处理,而上述一改之后的代码确是从第一个像素即开始处理,当中心像素窗口完全不在目标区域,其计算的所索引值将达到最大,从table表中可以看出,最终结果为0,与上面处理后图像的结果相符。
结果三:
按照上述理解,进行第二次修改,相对于第一修改后代码,仅增加了倒数第三行代码:
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 10 14:35:27 2019
@author: 高行吟
"""
import numpy as np
def Get_skeleton_line(img):
table = [0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,\
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,\
0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,\
1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,0,\
1,1,0,0,1,1,1,0,1,1,0,0,1,0,0,0]
r , c = img.shape
# line_img = np.zeros((r , c))
new_img = np.zeros((r + 2 , c + 2))##由于本程序以窗口遍历,因此原矩阵四个方向均增加一个全零边,方便计算
new_img[1:-1 , 1:-1] = img
new_img = np.where(new_img == 1 , 0 , 1)###由于目标区域值为1,而查表法规定,一旦像素为目标,则其权重为0,因此将矩阵所有值全部反向,即是0→1,1→0,方便与权重模板temp做乘法计算
temp = np.array([[1 , 2 , 4] , [8 , 0 , 16] , [32 , 64 , 128]])###权重矩阵
for i in range(1 , r+1):
for j in range(1 , c+1):
if new_img[i , j] == 0:####判断中心像素是否为目标像素,由于前面进行了像素值反转,因此,此处0值代表目标像素
# line_img[i-1 , j-1] = table[(new_img[i-1:i+2 , j-1:j+2]*temp).sum()]######窗口矩阵与模板相乘,其和即为表索引
new_img[i , j] = table[(new_img[i-1:i+2 , j-1:j+2]*temp).sum()]
return new_img[1:-1 , 1:-1]#line_img
按上述二改后代码运行结果正确,结果为单像素组成的连通边,如下:
原图 二值图 处理后