提出问题
遥感影像研究中,经常出现线性地物需要对其连通性进行分析,重要的一步是对其骨架进行提取,或者叫做细化操作。该步骤如果直接对整个地物进行细化,往往出现如下问题,如图1,边缘毛刺很多。
解决方法
为了解决上述问题,我们首先对大尺度影像进行裁剪,裁剪成512*512像素,裁剪拼接代码这里不给出,其他博客可搜索。然后,对小块影像进行细化操作。最后拼接成大块。细化操作代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
import glob
import os
# hilditch thining
def hilditch(img):
# get shape
H, W, C = img.shape
# prepare out image
out = np.zeros((H, W))
out[img[..., 0] > 0] = 1
# inverse pixel value
tmp = out.copy()
_tmp = 1 - tmp
count = 1
while count > 0:
count = 0
tmp = out.copy()
_tmp = 1 - tmp
tmp2 = out.copy()
_tmp2 = 1 - tmp2
# each pixel
for y in range(H):
for x in range(W):
# skip black pixel
if out[y, x] < 1:
continue
judge = 0
## condition 1
if (tmp[y, min(x+1, W-1)] * tmp[max(y-1,0 ), x] * tmp[y, max(x-1, 0)] * tmp[min(y+1, H-1), x]) == 0:
judge += 1
## condition 2
c = 0
c += (_tmp[y, min(x+1, W-1)] - _tmp[y, min(x+1, W-1)] * _tmp[max(y-1, 0), min(x+1, W-1)] * _tmp[max(y-1, 0), x])
c += (_tmp[max(y-1, 0), x] - _tmp[max(y-1, 0), x] * _tmp[max(y-1, 0), max(x-1, 0)] * _tmp[y, max(x-1, 0)])
c += (_tmp[y, max(x-1, 0)] - _tmp[y, max(x-1, 0)] * _tmp[min(y+1, H-1), max(x-1, 0)] * _tmp[min(y+1, H-1), x])
c += (_tmp[min(y+1, H-1), x] - _tmp[min(y+1, H-1), x] * _tmp[min(y+1, H-1), min(x+1, W-1)] * _tmp[y, min(x+1, W-1)])
if c == 1:
judge += 1
## condition 3
if np.sum(tmp[max(y-1, 0) : min(y+2, H), max(x-1, 0) : min(x+2, W)]) >= 3:
judge += 1
## condition 4
if np.sum(out[max(y-1, 0) : min(y+2, H), max(x-1, 0) : min(x+2, W)]) >= 2:
judge += 1
## condition 5
_tmp2 = 1 - out
c = 0
c += (_tmp2[y, min(x+1, W-1)] - _tmp2[y, min(x+1, W-1)] * _tmp2[max(y-1, 0), min(x+1, W-1)] * _tmp2[max(y-1, 0), x])
c += (_tmp2[max(y-1, 0), x] - _tmp2[max(y-1, 0), x] * (1 - tmp[max(y-1, 0), max(x-1, 0)]) * _tmp2[y, max(x-1, 0)])
c += (_tmp2[y, max(x-1, 0)] - _tmp2[y, max(x-1, 0)] * _tmp2[min(y+1, H-1), max(x-1, 0)] * _tmp2[min(y+1, H-1), x])
c += (_tmp2[min(y+1, H-1), x] - _tmp2[min(y+1, H-1), x] * _tmp2[min(y+1, H-1), min(x+1, W-1)] * _tmp2[y, min(x+1, W-1)])
if c == 1 or (out[max(y-1, 0), max(x-1,0 )] != tmp[max(y-1, 0), max(x-1, 0)]):
judge += 1
c = 0
c += (_tmp2[y, min(x+1, W-1)] - _tmp2[y, min(x+1, W-1)] * _tmp2[max(y-1, 0), min(x+1, W-1)] * (1 - tmp[max(y-1, 0), x]))
c += ((1-tmp[max(y-1, 0), x]) - (1 - tmp[max(y-1, 0), x]) * _tmp2[max(y-1, 0), max(x-1, 0)] * _tmp2[y, max(x-1, 0)])
c += (_tmp2[y, max(x-1,0 )] - _tmp2[y, max(x-1,0 )] * _tmp2[min(y+1, H-1), max(x-1, 0)] * _tmp2[min(y+1, H-1), x])
c += (_tmp2[min(y+1, H-1), x] - _tmp2[min(y+1, H-1), x] * _tmp2[min(y+1, H-1), min(x+1, W-1)] * _tmp2[y, min(x+1, W-1)])
if c == 1 or (out[max(y-1, 0), x] != tmp[max(y-1, 0), x]):
judge += 1
c = 0
c += (_tmp2[y, min(x+1, W-1)] - _tmp2[y, min(x+1, W-1)] * (1 - tmp[max(y-1, 0), min(x+1, W-1)]) * _tmp2[max(y-1, 0), x])
c += (_tmp2[max(y-1, 0), x] - _tmp2[max(y-1, 0), x] * _tmp2[max(y-1, 0), max(x-1, 0)] * _tmp2[y, max(x-1, 0)])
c += (_tmp2[y, max(x-1, 0)] - _tmp2[y, max(x-1, 0)] * _tmp2[min(y+1, H-1), max(x-1, 0)] * _tmp2[min(y+1, H-1), x])
c += (_tmp2[min(y+1, H-1), x] - _tmp2[min(y+1, H-1), x] * _tmp2[min(y+1, H-1), min(x+1, W-1)] * _tmp2[y, min(x+1, W-1)])
if c == 1 or (out[max(y-1, 0), min(x+1, W-1)] != tmp[max(y-1, 0), min(x+1, W-1)]):
judge += 1
c = 0
c += (_tmp2[y, min(x+1, W-1)] - _tmp2[y, min(x+1, W-1)] * _tmp2[max(y-1, 0), min(x+1, W-1)] * _tmp2[max(y-1, 0), x])
c += (_tmp2[max(y-1, 0), x] - _tmp2[max(y-1, 0), x] * _tmp2[max(y-1, 0), max(x-1, 0)] * (1 - tmp[y, max(x-1, 0)]))
c += ((1 - tmp[y, max(x-1, 0)]) - (1 - tmp[y, max(x-1, 0)]) * _tmp2[min(y+1, H-1), max(x-1, 0)] * _tmp2[min(y+1, H-1), x])
c += (_tmp2[min(y+1, H-1), x] - _tmp2[min(y+1, H-1), x] * _tmp2[min(y+1, H-1), min(x+1, W-1)] * _tmp2[y, min(x+1, W-1)])
if c == 1 or (out[y, max(x-1, 0)] != tmp[y, max(x-1, 0)]):
judge += 1
if judge >= 8:
out[y, x] = 0
count += 1
out = out.astype(np.uint8) * 255
return out
# Read image
image_path = './xihua/input/*.jpg'
for img_path in glob.glob(image_path):
name_out = os.path.split(img_path)[1]
print ('正在处理{}'.format(name_out))
img = cv2.imread(img_path).astype(np.float32)
_,RedThresh = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
RedThresh = cv2.medianBlur(RedThresh, ksize=3)
#OpenCV定义的结构矩形元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
eroded = cv2.erode(RedThresh,kernel,iterations = 1) #腐蚀图像
dilated = cv2.dilate(eroded,kernel,iterations = 1) #膨胀图像
# hilditch thining
out = hilditch(dilated)
# Save result
cv2.imwrite('./xihua/output/{}'.format(name_out), out)
文章评论