原理及作用:
形态学图像处理的理论根基是数学形态学(Mathematical Morphology),可以通过形态学处理获取图像中有意义的区域,比如边界信息。
1. 腐蚀是一种消除边界点,使边界向内部收缩的过程。可以用来消除小且无意义的物体。
腐蚀原理:
用3x3的结构元素,扫描图像的每一个像素,用结构元素与其覆盖的二值图像做“与”操作,如果都为1,结果图像的该像素为1。否则为0。
2. 膨胀是将与物体接触的所有背景点合并到该物体中,使边界向外部扩张的过程。可以用来填补物体中的空洞。
膨胀原理:
用3x3的结构元素,扫描图像的每一个像素,用结构元素与其覆盖的二值图像做“与”操作,如果都为0,结果图像的该像素为0。否则为1。
3. 先腐蚀后膨胀的过程称为开运算。用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。
4. 先膨胀后腐蚀的过程称为闭运算。用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。
不管是在二维图像还是三维图像中,膨胀腐蚀与开闭运算都有很重要的应用。下面将使用numpy来实现。(如果想要进一步加速的,可以使用cuda版本的numpy,cupy进行加速)。
膨胀
2d矩形膨胀
def conv2d_data2(data,k_size):
padd_h = k_size[0]//2
padd_w = k_size[1]//2
x_pad = np.pad(data,((padd_h,padd_h),(padd_w,padd_w)))
h_num = data.shape[0]
w_num = data.shape[1]
temp_h = np.array([x_pad[i:i+k_size[0],:] for i in range(h_num)])
temp_w = np.array([temp_h]*k_size[1]).transpose([1,0,2,3])
for i in range(1,k_size[1]):
temp_w[:,i,:,:-i] = temp_w[:,i,:,i:]
result = temp_w[:,:,:,:-(k_size[1]-1)].transpose(0,3,2,1)
return result
def dilate_rect2d(img,K_size):
data = conv2d_data2(img>0,K_size)
K = np.ones(K_size)
result = np.einsum("abef,ef->ab",data,K)
result = (result>0)*1
return result
2d圆形膨胀
制作圆形卷积核
def generate_mask2d(img_height,img_width,radius,center_y,center_x):
y = np.array(list(range(img_height))).reshape([img_height,1])
x = np.array(list(range(img_width))).reshape([1,img_width])
mask = (x-center_x)**2+(y-center_y)**2<=radius**2
return mask
圆形膨胀代码:
def dilate_circle2d(img,K_size):
data = conv2d_data2(img>0,K_size)
r = int(np.min(K_size)//2)
center_y = int(K_size[0]//2)
center_x = int(K_size[1]//2)
K = generate_mask2d(K_size[0],K_size[1],r,center_y,center_x)*1
result = np.einsum("abef,ef->ab",data,K)
result = (result>0)*1
return result
3d膨胀代码
矩形
def conv3d_data2(data,k_size):#k_size[c,h,w]
padd_c = k_size[0]//2
padd_h = k_size[1]//2
padd_w = k_size[2]//2
x_pad = np.pad(data,((padd_c,padd_c),(padd_h,padd_h),(padd_w,padd_w)))
c_num = data.shape[0]
h_num = data.shape[1]
w_num = data.shape[2]
temp_c = np.array([x_pad[i:i+k_size[0],:,:] for i in range(c_num)])
temp_h = np.array([temp_c[:,:,i:i+k_size[1],:] for i in range(h_num)])
temp_w = np.array([temp_h]*k_size[2]).transpose([2,1,0,3,4,5])
for i in range(1,k_size[2]):
temp_w[:,:,i,:,:,:-i] = temp_w[:,:,i,:,:,i:]
result = temp_w[:,:,:,:,:,:-(k_size[2]-1)].transpose([0,1,5,3,4,2])
return result
def dilate_rect3d(img,K_size):
data = conv3d_data2(img>0,K_size)
K = np.ones(K_size)
result = np.einsum("abcdef,def->abc",data,K)
result = (result>0)*1
return result
3d圆形膨胀
def generate_mask3d(img_depth,img_height,img_width,radius,center_z,center_y,center_x):
y = np.array(list(range(img_height))).reshape([1,img_height,1])
x = np.array(list(range(img_width))).reshape([1,1,img_width])
z = np.array(list(range(img_depth))).reshape([img_depth,1,1])
mask = (x-center_x)**2+(y-center_y)**2+(z-center_z)**2<=radius**2
return mask
def dilate_circle3d(img,K_size):
data = conv3d_data2(img>0,K_size)
r = int(np.min(K_size)//2)
center_z = int(K_size[0]//2)
center_y = int(K_size[1]//2)
center_x = int(K_size[2]//2)
K = generate_mask3d(K_size[0],K_size[1],K_size[2],r,center_z,center_y,center_x)*1
result = np.einsum("abcdef,def->abc",data,K)
result = np.array(result>0)*1
return result
腐蚀
2d矩形腐蚀
def erode_rect2d(img,K_size):
data = conv2d_data2(img>0,K_size)
K = np.ones(K_size)
summ = K.shape[0]*K.shape[1]
result = np.einsum("abef,ef->ab",data,K)
result = (result==summ)*1
return result
2d圆形腐蚀
def erode_circle2d(img,K_size):
data = conv2d_data2(img>0,K_size)
r = int(np.min(K_size)//2)
center_y = int(K_size[0]//2)
center_x = int(K_size[1]//2)
K = generate_mask2d(K_size[0],K_size[1],r,center_y,center_x)*1
summ =np.sum(K)
result = np.einsum("abef,ef->ab",data,K)
result = (result==summ)*1
return result
3d矩形腐蚀
def erode_rect3d(img,K_size):
data = conv3d_data2(img>0,K_size)
K = np.ones(K_size)
summ = K.shape[0]*K.shape[1]*K.shape[2]
result = np.einsum("abcdef,def->abc",data,K)
result = (result==summ)*1
return result
3d圆形腐蚀
def erode_circle3d(img,K_size):
data = conv3d_data2(img>0,K_size)
r = int(np.min(K_size)//2)
center_z = int(K_size[0]//2)
center_y = int(K_size[1]//2)
center_x = int(K_size[2]//2)
K = generate_mask3d(K_size[0],K_size[1],K_size[2],r,center_z,center_y,center_x)*1
summ =np.sum(K)
result = np.einsum("abcdef,def->abc",data,K)
result = (result==summ)*1
return result
开闭运算
开闭运算只需进行相应的腐蚀膨胀运算,此处不再放上代码。