原理と機能:
形態学的画像処理の理論的基礎は数学的形態学であり、形態学的処理を通じて境界情報などの画像内の意味のある領域を取得できます。
1. 腐食は、境界点を除去し、境界を内側に縮小するプロセスです。小さくて意味のないオブジェクトを削除するために使用できます。
腐食原理:
3x3 の構造要素を使用して画像の各ピクセルをスキャンし、構造要素とそれに含まれるバイナリ イメージを使用して「AND」演算を実行します。両方が 1 の場合、結果の画像のピクセルは 1 になります。それ以外の場合は 0。
2. 膨張とは、オブジェクトと接触しているすべての背景点をオブジェクトにマージし、境界を外側に拡張するプロセスです。オブジェクトの穴を埋めるために使用できます。
拡張原理:
3x3 の構造要素を使用してイメージの各ピクセルをスキャンし、構造要素とそれがカバーするバイナリ イメージで「AND」演算を実行します。両方が 0 の場合、結果のイメージのピクセルは 0 になります。それ以外の場合は 1。
3. 最初の侵食とその後の拡張のプロセスは、オープニング操作と呼ばれます。小さなオブジェクトを削除し、オブジェクトを細い点で分離し、大きなオブジェクトの領域を大きく変えることなく境界を滑らかにするために使用されます。
4. 最初に膨張し、次に腐食するプロセスを密閉操作と呼びます。オブジェクトの小さな穴を埋めたり、隣接するオブジェクトを接続したり、領域を大きく変えることなく境界を滑らかにしたりするために使用されます。
2 次元画像であろうと 3 次元画像であろうと、拡張侵食および開閉操作には非常に重要な用途があります。以下は 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
2次元の円形展開
循環畳み込みカーネルを作成する
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
開閉動作
開閉操作では、対応する侵食操作と拡張操作を実行するだけでよく、コードはここには配置されません。