9.scipy Ndimage


title: "9.scipy-ndimage" date: 2026-05-24T14:11:26Z

1import numpy as np
2import pylab as pl

图像处理-ndimage

形态学图像处理

 1import numpy as np
 2
 3def expand_image(img, value, out=None, size = 10):
 4    if out is None:
 5        w, h = img.shape
 6        out = np.zeros((w*size, h*size),dtype=np.uint8)
 7    
 8    tmp = np.repeat(np.repeat(img,size,0),size,1)
 9    out[:,:] = np.where(tmp, value, out)
10    out[::size,:] = 0
11    out[:,::size] = 0
12    return out
13    
14def show_image(*imgs): 
15    for idx, img in enumerate(imgs, 1):
16        ax = pl.subplot(1, len(imgs), idx)
17        pl.imshow(img, cmap="gray")   
18        ax.set_axis_off()    
19    pl.subplots_adjust(0.02, 0, 0.98, 1, 0.02, 0)        

膨胀和腐蚀

 1#%fig=四连通和八连通的膨胀运算
 2from scipy.ndimage import morphology
 3
 4def dilation_demo(a, structure=None):
 5    b = morphology.binary_dilation(a, structure)
 6    img = expand_image(a, 255)
 7    return expand_image(np.logical_xor(a,b), 150, out=img)
 8
 9a = pl.imread("scipy_morphology_demo.png")[:,:,0].astype(np.uint8)
10img1 = expand_image(a, 255)
11
12img2 = dilation_demo(a)
13img3 = dilation_demo(a, [[1,1,1],[1,1,1],[1,1,1]])
14show_image(img1, img2, img3)

png

1#%fig=不同结构元素的膨胀效果
2img4 = dilation_demo(a, [[0,0,0],[1,1,1],[0,0,0]])
3img5 = dilation_demo(a, [[0,1,0],[0,1,0],[0,1,0]])
4img6 = dilation_demo(a, [[0,1,0],[0,1,0],[0,0,0]])
5show_image(img4, img5, img6)

png

 1#%fig=四连通和八连通的腐蚀运算
 2def erosion_demo(a, structure=None):
 3    b = morphology.binary_erosion(a, structure)
 4    img = expand_image(a, 255)
 5    return expand_image(np.logical_xor(a,b), 100, out=img)
 6
 7img1 = expand_image(a, 255)
 8img2 = erosion_demo(a)
 9img3 = erosion_demo(a, [[1,1,1],[1,1,1],[1,1,1]])
10show_image(img1, img2, img3)

png

Hit和Miss

 1#%fig=Hit和Miss运算
 2def hitmiss_demo(a, structure1, structure2):
 3    b = morphology.binary_hit_or_miss(a, structure1, structure2)
 4    img = expand_image(a, 100)
 5    return expand_image(b, 255, out=img)
 6
 7img1 = expand_image(a, 255)
 8
 9img2 = hitmiss_demo(a, [[0,0,0],[0,1,0],[1,1,1]], [[1,0,0],[0,0,0],[0,0,0]])
10img3 = hitmiss_demo(a, [[0,0,0],[0,0,0],[1,1,1]], [[1,0,0],[0,1,0],[0,0,0]])
11
12show_image(img1, img2, img3)

png

 1#%fig=使用Hit和Miss进行细线化运算
 2def skeletonize(img):
 3    h1 = np.array([[0, 0, 0],[0, 1, 0],[1, 1, 1]]) #❶
 4    m1 = np.array([[1, 1, 1],[0, 0, 0],[0, 0, 0]]) 
 5    h2 = np.array([[0, 0, 0],[1, 1, 0],[0, 1, 0]]) 
 6    m2 = np.array([[0, 1, 1],[0, 0, 1],[0, 0, 0]])    
 7    hit_list = [] 
 8    miss_list = []
 9    for k in range(4): #❷
10        hit_list.append(np.rot90(h1, k))
11        hit_list.append(np.rot90(h2, k))
12        miss_list.append(np.rot90(m1, k))
13        miss_list.append(np.rot90(m2, k))    
14    img = img.copy()
15    while True:
16        last = img
17        for hit, miss in zip(hit_list, miss_list): 
18            hm = morphology.binary_hit_or_miss(img, hit, miss) #❸
19            # 从图像中删除hit_or_miss所得到的白色点
20            img = np.logical_and(img, np.logical_not(hm)) #❹
21        # 如果处理之后的图像和处理前的图像相同,则结束处理
22        if np.all(img == last): #❺
23            break
24    return img
25
26a = pl.imread("scipy_morphology_demo2.png")[:,:,0].astype(np.uint8)
27b = skeletonize(a)
28#%hide
29_, (ax1, ax2) = pl.subplots(1, 2, figsize=(9, 3))
30ax1.imshow(a, cmap="gray", interpolation="nearest")
31ax2.imshow(b, cmap="gray", interpolation="nearest")
32ax1.set_axis_off()
33ax2.set_axis_off()
34pl.subplots_adjust(0.02, 0, 0.98, 1, 0.02, 0)

png

图像分割

1squares = pl.imread("suqares.jpg")
2squares = (squares[:,:,0] < 200).astype(np.uint8) 
1from scipy.ndimage import morphology
2squares_dt = morphology.distance_transform_cdt(squares)
3print ("各种距离值", np.unique(squares_dt))
各种距离值 [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27]
1squares_core = (squares_dt > 8).astype(np.uint8)
 1from scipy.ndimage.measurements import label, center_of_mass
 2
 3def random_palette(labels, count, seed=1):
 4    np.random.seed(seed)
 5    palette = np.random.rand(count+1, 3)
 6    palette[0,:] = 0
 7    return palette[labels]
 8
 9labels, count = label(squares_core)
10h, w = labels.shape
11centers = np.array(center_of_mass(labels, labels, index=range(1, count+1)), np.int)
12cores = random_palette(labels, count)
1index = morphology.distance_transform_cdt(1-squares_core, 
2                                          return_distances=False, 
3                                          return_indices=True) #❶
4near_labels = labels[index[0], index[1]] #❷
5
6mask = (squares - squares_core).astype(bool)
7labels2 = labels.copy()
8labels2[mask] = near_labels[mask] #❸
9separated = random_palette(labels2, count)
 1#%figonly=矩形区域分割算法各个步骤的输出图像
 2fig, axes = pl.subplots(2, 3, figsize=(7.5, 5.0), )
 3fig.delaxes(axes[1, 2])
 4axes[0, 0].imshow(squares, cmap="gray");
 5axes[0, 1].imshow(squares_dt)
 6axes[0, 2].imshow(squares_core, cmap="gray")
 7ax = axes[1, 0]
 8ax.imshow(cores)
 9center_y, center_x = centers.T
10ax.plot(center_x, center_y, "o", color="white")
11ax.set_xlim(0, w)
12ax.set_ylim(h, 0)
13
14axes[1, 1].imshow(separated)
15
16for ax in axes.ravel():
17    ax.axis("off")
18    
19fig.subplots_adjust(wspace=0.01, hspace=0.01)

png