事情是这样的
本着py狗好好的py不用为什么要用c++的想法
我开始了谷歌大法 python & 细化图像
环境
python2.7
openvc2.4.13.2
windows下安装opencv
OpenCV是一个C++库,用于实时处理计算机视觉方面的问题,涵盖了很多计算机视觉领域的模块。
OpenCV有两个Python接口,老版本的cv模块使用OpenCV内置的数据类型,新版本的cv2模块使用NumPy数组。
下载链接 https://opencv.org/releases.html
python2.7最好选对用openvc低一些的版本,我第一次安装选了高版本,结果无法适应,然后重装了。。。
Python_OpenCV环境配置
将opencv中的C:\opencv\build\python\2.7\x64下的cv2.pyd移动到python安装目录下的Lib\site-packages 中。
打开cmd,运行python
numpy&matplotlib
numpy和matplotlib,是两个比较简单易用的数据分析和可视化的库。
numpy
matplotlib
图像细化
图像的细化主要是针对二值图而言
所谓骨架,可以理解为图像的中轴,,一个长方形的骨架,是它的长方向上的中轴线,
圆的骨架是它的圆心,直线的骨架是它自身,孤立点的骨架也是自身。
骨架的获取主要有两种方法:
(1)基于烈火模拟
设想在同一时刻,将目标的边缘线都点燃,火的前沿以匀速向内部蔓延,当前沿相交时火焰熄灭,
火焰熄灭点的结合就是骨架。
(2)基于最大圆盘
目标的骨架是由目标内所有内切圆盘的圆心组成
我们来看看典型的图形的骨架(用粗线表示)
细化的算法有很多种,但比较常用的算法是查表法
细化是从原来的图中去掉一些点,但仍要保持原来的形状。
实际上是保持原图的骨架。
判断一个点是否能去掉是以8个相邻点(八连通)的情况来作为判据的,具体判据为:
1,内部点不能删除
2,鼓励点不能删除
3,直线端点不能删除
4,如果P是边界点,去掉P后,如果连通分量不增加,则P可删除
看看上面那些点。
第一个点不能去除,因为它是内部点
第二个点不能去除,它也是内部点
第三个点不能去除,删除后会使原来相连的部分断开
第四个点可以去除,这个点不是骨架
第五个点不可以去除,它是直线的端点
第六个点不可以去除,它是直线的端点
对于所有的这样的点,我们可以做出一张表,来判断这样的点能不能删除
我们对于黑色的像素点,对于它周围的8个点,我们赋予不同的价值,
若周围某黑色,我们认为其价值为0,为白色则取九宫格中对应的价值
对于前面那幅图中第一个点,也就是内部点,它周围的点都是黑色,所以他的总价值是0,对应于索引表的第一项
前面那幅图中第二点,它周围有三个白色点,它的总价值为1+4+32=37,对应于索引表中第三十八项
我们用这种方法,把所有点的情况映射到0~255的索引表中
我们扫描原图,对于黑色的像素点,根据周围八点的情况计算它的价值,然后查看索引表中对应项来决定是否要保留这一点
程序
# -*- coding: utf-8 -*-
"""
Created on Sat May 12 16:36:06 2018
"""
import cv2
#细化函数,输入需要细化的图片(经过二值化处理的图片)和映射矩阵array
#这个函数将根据算法,运算出中心点的对应值
def Thin(image,array):
h,w = image.shape
iThin = image
for i in range(h):
for j in range(w):
if image[i,j] == 0:
a = [1]*9
for k in range(3):
for l in range(3):
#如果3*3矩阵的点不在边界且这些值为零,也就是黑色的点
if -1<(i-1+k)<h and -1<(j-1+l)<w and iThin[i-1+k,j-1+l]==0:
a[k*3+l] = 0
sum = a[0]*1+a[1]*2+a[2]*4+a[3]*8+a[5]*16+a[6]*32+a[7]*64+a[8]*128
#然后根据array表,对ithin的那一点进行赋值。
iThin[i,j] = array[sum]*255
return iThin
#最简单的二值化函数,阈值根据图片的昏暗程度自己设定,我选的180
def Two(image):
w,h = image.shape
size = (w,h)
iTwo = image
for i in range(w):
for j in range(h):
if image[i,j]<180:
iTwo[i,j] = 0
else:
iTwo[i,j] = 255
return iTwo
#映射表
array = [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]
#读取灰度图片,并显示
img = cv2.imread('./233.png',0) #直接读为灰度图像
cv2.imshow('image',img)
cv2.waitKey(0)
#自适应二值化函数,需要修改的是55那个位置的数字,越小越精细,细节越好,噪点更多,最大不超过图片大小
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,55,2) #换行符号 \
cv2.imshow('iTwo',th3)
cv2.waitKey(0)
#获取自适应二值化的细化图,并显示
iThin = Thin(th3,array)
cv2.imshow('iThin',iThin)
cv2.waitKey(0)
#获取简单二值化的细化图,并显示
iTwo = Two(img)
iThin_2 = Thin(iTwo,array)
cv2.imshow('iTwo_2',iThin_2)
cv2.waitKey(0)
cv2.destroyAllWindows()
测试
问题
- 第一个问题是opencv安装问题,之前说了,python2.7要用低版本opencv,重装就完事儿。
- 第二个问题是程序一直报错
error: (-215) size.width>0 && size.height>0 in function imshow
结果是图像的路径问题,
图片路径中“文件夹分隔符”使用的错误。
将“\”改成“/”就好了~:blush: