通过Python在OpenCV中使用inpaint函数插值流域中的断流河流数据 背景

通过Python在OpenCV中使用inpaint函数插值流域中的断流河流数据 背景,python,opencv,mask,raster,watershed,Python,Opencv,Mask,Raster,Watershed,通过激光雷达收集的光栅文件记录流域的地形。为正确模拟流域,河流必须连续,无任何中断或中断。如下图所示,光栅文件中的道路看起来像水坝,阻断了河流 客观的 这些河流断裂是主要的问题,我正在努力,但未能消除它们 方法 通过Python,我使用了OpenCV库中的各种工具和预构建函数。我在这种方法中使用的主要功能是cv2.inpaint功能。此函数接收图像文件和遮罩文件,并在遮罩文件像素不为零的位置对原始图像进行插值 这里的主要步骤是确定掩码文件,我是通过检测河流断裂处的拐角来完成的。掩模文件将引导修

通过激光雷达收集的光栅文件记录流域的地形。为正确模拟流域,河流必须连续,无任何中断或中断。如下图所示,光栅文件中的道路看起来像水坝,阻断了河流

客观的 这些河流断裂是主要的问题,我正在努力,但未能消除它们

方法 通过Python,我使用了OpenCV库中的各种工具和预构建函数。我在这种方法中使用的主要功能是cv2.inpaint功能。此函数接收图像文件遮罩文件,并在遮罩文件像素不为零的位置对原始图像进行插值

这里的主要步骤是确定掩码文件,我是通过检测河流断裂处的拐角来完成的。掩模文件将引导修复功能根据周围像素中的图案填充像素

问题 我的问题是,这会从各个方向发生,而我要求它只能从河流本身推断像素数据。下图显示了有缺陷的结果:修复工作正常,但它也考虑了来自河外的数据

如果您愿意帮忙,我的代码如下:

import scipy.io as sio
import numpy as np
from matplotlib import pyplot as plt
import cv2

matfile = sio.loadmat('box.mat') ## box.mat original raster file linked below
ztopo = matfile['box']

#Crop smaller section for analysis
ztopo2 = ztopo[200:500, 1400:1700]


## Step 1) Isolate river
river = ztopo2.copy()
river[ztopo2<217.5] = 0
#This will become problematic for entire watershed w/o proper slicing


## Step 2) Detect Corners
dst = cv2.cornerHarris(river,3,7,0.04)
# cornerHarris arguments adjust qualities of corner markers

# Dilate Image (unnecessary)
#dst = cv2.dilate(dst,None)  

# Threshold for an optimal value, it may vary depending on the image.
# This adjusts what defines a corner
river2 = river.copy()
river2[dst>0.01*dst.max()]=[150]


## Step 3) Remove river and keep corners

#Initiate loop to isolate detected corners
i=0
j=0
rows,columns = river2.shape
for i in np.arange(rows):
    for j in np.arange(columns):
        if river2[i,j] != 150:
            river2[i,j] = 0
        j = j + 1
    i = i + 1

# Save corners as new image for import during next step.
# Import must be via cv2 as thresholding and contour detection can only work on BGR files. Sio import in line 6 (matfile = sio.loadmat('box.mat')) imports 1 dimensional image rather than BGR.
cv2.imwrite('corners.png', river2)


## Step 4) Create mask image by defining and filling a contour around the previously detected corners

#Step 4 code retrieved from http://dsp.stackexchange.com/questions/2564/opencv-c-connect-nearby-contours-based-on-distance-between-them
#Article: OpenCV/C++ connect nearby contours based on distance between them

#Initiate function to specify features of contour connections
def find_if_close(cnt1,cnt2):
    row1,row2 = cnt1.shape[0],cnt2.shape[0]
    for i in xrange(row1):
        for j in xrange(row2):
            dist = np.linalg.norm(cnt1[i]-cnt2[j])
            if abs(dist) < 50 :
                return True
            elif i==row1-1 and j==row2-1:
                return False

#import image of corners created in step 3 so thresholding can function properly
img = cv2.imread('corners.png')

#Thresholding and Finding contours only works on grayscale image
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hier = cv2.findContours(thresh,cv2.RETR_EXTERNAL,2)

LENGTH = len(contours)
status = np.zeros((LENGTH,1))

for i,cnt1 in enumerate(contours):
    x = i    
    if i != LENGTH-1:
        for j,cnt2 in enumerate(contours[i+1:]):
            x = x+1
            dist = find_if_close(cnt1,cnt2)
            if dist == True:
                val = min(status[i],status[x])
                status[x] = status[i] = val
            else:
                if status[x]==status[i]:
                    status[x] = i+1

unified = []
maximum = int(status.max())+1
for i in xrange(maximum):
    pos = np.where(status==i)[0]
    if pos.size != 0:
        cont = np.vstack(contours[i] for i in pos)
        hull = cv2.convexHull(cont) # I don't know why/how this is used
        unified.append(hull)


cv2.drawContours(img,unified,-1,(0,255,0),1) #Last argument specifies contour width
cv2.drawContours(thresh,unified,-1,255,-1)

# Thresh is the filled contour while img is the contour itself
# The contour surrounds the corners

#cv2.imshow('pic', thresh) #Produces black and white image


## Step 5) Merge via inpaint
river = np.uint8(river)
ztopo2 = np.uint8(ztopo2)

thresh[thresh>0] = 1
#new = river.copy()
merged = cv2.inpaint(river,thresh,12,cv2.INPAINT_TELEA)

plt.imshow(merged)
plt.colorbar()
plt.show()
将scipy.io导入为sio
将numpy作为np导入
从matplotlib导入pyplot作为plt
进口cv2
matfile=sio.loadmat('box.mat')##box.mat原始光栅文件链接如下
ztopo=matfile['box']
#裁剪较小的截面进行分析
ztopo2=ztopo[200:500,1400:1700]
##步骤1)隔离河流
river=ztop2.copy()
河流[ztopo20.01*dst.max()]=[150]
##步骤3)清除河流并保留角落
#启动循环以隔离检测到的角点
i=0
j=0
行、列=2.2.2形状
对于np.arange中的i(行):
对于np.arange中的j(列):
如果river2[i,j]!=150:
river2[i,j]=0
j=j+1
i=i+1
#将角点另存为新图像,以便在下一步中导入。
#导入必须通过cv2,因为阈值和轮廓检测只能在BGR文件上工作。第6行中的Sio导入(matfile=Sio.loadmat('box.mat'))导入一维图像,而不是BGR。
cv2.imwrite('corners.png',river2)
##步骤4)通过定义和填充先前检测到的拐角周围的轮廓来创建遮罩图像
#步骤4从中检索的代码http://dsp.stackexchange.com/questions/2564/opencv-c-connect-nearby-contours-based-on-distance-between-them
#文章:OpenCV/C++根据轮廓之间的距离连接附近的轮廓
#启动函数以指定轮廓连接的特征
如果关闭,def查找(cnt1、cnt2):
行1,行2=cnt1.shape[0],cnt2.shape[0]
对于X范围内的i(第1行):
对于X范围内的j(第2行):
dist=np.linalg.norm(cnt1[i]-cnt2[j])
如果abs(距离)<50:
返回真值
如果i==第1-1行和j==第2-1行:
返回错误
#导入在步骤3中创建的角点图像,以便阈值可以正常工作
img=cv2.imread('corners.png')
#阈值和查找轮廓仅适用于灰度图像
灰色=cv2.CVT颜色(img,cv2.COLOR\U BGR2GRAY)
ret,thresh=cv2.阈值(灰色,127255,cv2.thresh_二进制)
等高线,hier=cv2.已找到的等高线(阈值,cv2.外部,2)
长度=长度(轮廓)
状态=np.零((长度,1))
对于i,枚举中的cnt1(等高线):
x=i
如果我长度-1:
对于j,枚举中的cnt2(等高线[i+1:]):
x=x+1
dist=如果关闭则查找(cnt1,cnt2)
如果dist==True:
val=min(状态[i],状态[x])
状态[x]=状态[i]=val
其他:
如果状态[x]==状态[i]:
状态[x]=i+1
统一=[]
最大值=int(status.max())+1
对于X范围内的i(最大值):
pos=np.其中(status==i)[0]
如果位置大小!=0:
cont=np.vstack(位置i的轮廓[i]
赫尔=cv2.convxhull(续)#我不知道为什么/如何使用它
统一.append(外壳)
cv2.drawContours(img,统一,-1,(0255,0),1)#最后一个参数指定轮廓宽度
cv2.拉深轮廓线(thresh,统一,-1255,-1)
#Thresh是填充轮廓,而img是轮廓本身
#轮廓围绕着各个角落
#cv2.imshow('pic',thresh)#产生黑白图像
##步骤5)通过修复合并
河流=np.uint8(河流)
ztop2=np.uint8(ztop2)
脱粒[脱粒>0]=1
#new=river.copy()
合并=cv2.修复(river,thresh,12,cv2.修复)
plt.imshow(合并)
plt.colorbar()
plt.show()
这里是指向“box.mat”光栅数据的链接,供您参考。这是指向“box.mat”光栅数据的链接,供您参考。