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)
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)
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)
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)
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)
图像分割
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)