python3 OpenCV cv2 图像的细化(骨架抽取)_图像处理作业

参考链接:http://www.cnblogs.com/xianglan/archive/2011/01/01/1923779.html

主思路和程序基本上都是参考博主的,只是在思路理解上和Python3的一些小修改.

首先是算法原理介绍:

图像细化:

图像细化主要是针对二值图而言,所谓骨架,可以理解为图像的中轴,,一个长方形的骨架,是它的长方向上的中轴线,圆的骨架是它的圆心,直线的骨架是它自身,孤立点的骨架也是自身。我们来看看典型的图形的骨架(用粗线表示)

细化的算法有很多种,但比较常用的算法是查表法

细化是从原来的图中去掉一些点,但仍要保持原来的形状。实际上是保持原图的骨架。判断一个点是否能去掉是以8个相邻点(八连通)的情况来作为判据的,具体判据为:

1,内部点不能删除

2,鼓励点不能删除

3,直线端点不能删除

4,如果P是边界点,去掉P后,如果连通分量不增加,则P可删除


看看上面那些点,就是3*3矩阵中的中心点。

第一个点不能去除,因为它是内部点

第二个点不能去除,它也是内部点

第三个点不能去除,删除后会使原来相连的部分断开

第四个点可以去除,这个点不是骨架

第五个点不可以去除,它是直线的端点

第六个点不可以去除,它是直线的端点

等等~图中无法列举出所有的情况,所以我们将有一个算法和映射,将所有的情况用表格的形式列举出来——

即假设我们要求,某个点是否需要被细化(去除),我们需要将它周围的八个点都列出来,形成一个矩阵,标号好,如上图1,然后每个位置的点,赋予不同的权值,即右边的表格值,就可以将每一种情况列举出来了。

原文中的解释是——    

我们对于黑色的像素点,对于它周围的8个点,我们赋予不同的权值,若周围为黑色,我们认为其权值为0,为白色则取九宫格中对应的权值,这个其实根据你自己图像中的值来确定,如果你的目标值本身就是白色,那么效果肯定相反

对于前面那幅图中第一个图,也就是内部点,它周围的点都是黑色,所以它的总价值是0,对应于索引表的第一项。

前面那幅图中第二点,它周围有三个白色点,它的总价值为1+4+32=37,对应于索引表中第三十八项

我们用这种方法,把所有点的情况映射到0~255的索引表中

 索引表也就是下面的16*16矩阵:

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]

        

当然如果上面的表格错误的话,最终的算法肯定会有问题的,我不知道我达到的效果不好,是不是因为这个~


然后是程序:

# -*- coding: utf-8 -*-
"""
Created on Sat May 12 16:36:06 2018

@author: lele
"""
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('letter.jpg',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()

效果图可以看到:




很明显,没有原博主的好看~

原博主的是这样的:


不知道原因是啥,可能我的二值化没处理好?我的图是截图的,不干净?

猜你喜欢

转载自blog.csdn.net/hehedadaq/article/details/80303218