import os import cv2 import numpy as np import tifIO import shutil import sys import argparse import math from math import floor import json import subprocess import qgis from qgis.core import * # attach main QGIS library from qgis.utils import * # attach main python library from qgis.analysis import * from osgeo import gdal #相对路径 qgis_path = sys.executable process_path = qgis_path.split('bin')[0]+'apps\\qgis-ltr\\python\\plugins' # process_path = 'D:/code/RsSurvey/RsSurvey_Build/x64/Release/QGIS_3.22.8/apps/qgis-ltr/python/plugins/' if os.path.exists(process_path): print("exists path:"+process_path) sys.stdout.flush() else: print("fine no path:"+process_path) sys.stdout.flush() sys.path.append(process_path) qgs = QgsApplication([], False) qgs.initQgis() import processing from processing.core.Processing import Processing Processing.initialize() #添加参数 parser = argparse.ArgumentParser() parser.add_argument('--in_holedem', type=str, default='D:/A_testdata/dianli_test/00yanshou/data_train_dem/05veg_maskedTiff/', help='输入数据,经过裁剪的dem') parser.add_argument('--work_space', type=str, default='D:/A_testdata/dianli_test/00yanshou/data_train_dem/06veg_dataFill_workspace/', help='用于填补时存放中间路径及结果文件') parser.add_argument('--scale', type=float, default=0.1, help='外接矩形放大的比例') parser.add_argument('--win_size', type=int, default=3, help='空洞外扩像素') opt = parser.parse_args() in_holedem = opt.in_holedem work_space = opt.work_space scale = opt.scale win_size = opt.win_size ''' txt文件名以in_holedem中dem数据文件名命名 内容以singlehole文件开始,包含位置信息 subname, lt_x,lt_y,rb_x,rb_y tktk130_mask_id_1_hw_83_106.tif,1364,1950,1470,2033 ''' out_txt_folder = 'txt_singlehole/' singlehole_folder = 'dem_singlehole/'# 保存单个空洞 ras2pot_folder = 'raster2points/' ras2potpro_folder = 'raster2points_pro/' tinmesh_folder = 'TINMesh/' potfrommesh_folder = 'pointfrommesh/' potfrommeshfloat_folder = 'pointfrommeshfloat/' filltif_folder = 'tif/' filltifpro_folder = 'tif_pro/' out_fulltif_folder = 'out_result/'# 填补并放回的整图结果 print("win_size:%d,scale:%.4f" % (win_size, scale)) sys.stdout.flush() def findHoles(in_demfolder, out_singlehole, txt_folder): count = 0 ev = floor(win_size / 2) if os.path.exists(txt_folder): try: shutil.rmtree(txt_folder) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print("error {}".format(str(e))) sys.stdout.flush() print(-1.0) sys.stdout.flush() os.mkdir(txt_folder) if os.path.exists(out_singlehole): try: shutil.rmtree(out_singlehole) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print("error {}".format(str(e))) sys.stdout.flush() print(-1) sys.stdout.flush() os.mkdir(out_singlehole) dem_list = [] src_list = os.listdir(in_demfolder) for f in src_list: if os.path.splitext(f)[1] == '.tif' or os.path.splitext(f)[1] == '.TIF': dem_list.append(f) for imgfile in dem_list: filename = os.path.splitext(imgfile)[0] txtname = filename + '.txt' txt_route = os.path.join(txt_folder, txtname) file_handle = open(txt_route, mode='w') # file_handle.writelines(['文件名,左上角列号,左上角行号,右下角列号,右下角行号\n']) dem_route = os.path.join(in_demfolder, imgfile) proj, geotrans, dem_img, width, height = tifIO.ReadTif(dem_route) # c,h,w origin = cv2.imread(dem_route, cv2.IMREAD_UNCHANGED) img = origin.copy() # 二值化,转换类型 ret2, binary = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV) thresh_image = binary.astype(np.uint8) # 连通域分析 contours, hierarchy = cv2.findContours(thresh_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 检索最外轮廓 # contours, hierarchy = cv2.findContours(thresh_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) # 检索所有轮廓 for i in range(0, len(contours)): thisgeo = geotrans.copy() lt_x, lt_y, w, h = cv2.boundingRect(contours[i]) # 最小包络矩形的四至 # 矩形外扩,最小外扩2像元,保证空洞再小也能外扩 w_ex = floor(w * scale / 2) if floor(w * scale / 2) > 2 else 2 h_ex = floor(h * scale / 2) if floor(h * scale / 2) > 2 else 2 if lt_x - w_ex >= 0: new_lt_x = lt_x - w_ex else: new_lt_x = 0 if lt_y - h_ex >= 0: new_lt_y = lt_y - h_ex else: new_lt_y = 0 if lt_x + w + w_ex <= width: new_rb_x = lt_x + w + w_ex else: new_rb_x = width if lt_y + h + h_ex <= height: new_rb_y = lt_y + h + h_ex else: new_rb_y = height this_hole = img[new_lt_y: new_rb_y, new_lt_x: new_rb_x] flag = np.zeros(this_hole.shape, dtype=int) flag[this_hole > -9999] = 1 # 如果低于-9999,arcgis中nodata是极小的负数 # 洞不扩大 # this_hole[this_hole <=0] = np.nan # 洞外扩 new_w = new_rb_x - new_lt_x new_h = new_rb_y - new_lt_y for c in range(0, new_w): for r in range(0, new_h): if flag[r, c] == 0: for win_c in range(win_size): for win_r in range(win_size): tempr = r + win_r - ev tempc = c + win_c - ev if tempr >= 0 and tempr < new_h and tempc >= 0 and tempc < new_w: this_hole[tempr, tempc] = np.nan lon = thisgeo[0] + thisgeo[1] * new_lt_x lat = thisgeo[3] + thisgeo[5] * new_lt_y thisgeo[0] = lon thisgeo[3] = lat # fileroutesub =filename+ '_%d.tif' % count fileroutesub = filename + '_id_%d_hw_%d_%d' % (i + 1, new_h, new_w) + '.tif' fileroute = os.path.join(out_singlehole, fileroutesub) this_hole[np.where(this_hole == 0.0)] = np.nan tifIO.writeTif(fileroute, proj, thisgeo, this_hole) # 投影信息不对 # 坐标从【0,0】开始计,左上坐标【x,y】,右下坐标[x+w-1,y+h-1] file_handle.writelines([fileroutesub, ',', str(new_lt_x), ',', str(new_lt_y), ',', str(new_rb_x), ',', str(new_rb_y), '\n']) count = count + 1 file_handle.close() def confirmWorkspaceClear(rootPath): out_path_raster2points = os.path.join(rootPath, ras2pot_folder) if os.path.exists(out_path_raster2points): try: shutil.rmtree(out_path_raster2points) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print(-1.0) sys.stdout.flush() os.mkdir(out_path_raster2points) print(4) sys.stdout.flush() out_path_raster2points_pro = os.path.join(rootPath, ras2potpro_folder) if os.path.exists(out_path_raster2points_pro): try: shutil.rmtree(out_path_raster2points_pro) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print(-1.0) sys.stdout.flush() os.mkdir(out_path_raster2points_pro) print(5) sys.stdout.flush() out_path_TINMesh = os.path.join(rootPath, tinmesh_folder) if os.path.exists(out_path_TINMesh): try: shutil.rmtree(out_path_TINMesh) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print(-1.0) sys.stdout.flush() os.mkdir(out_path_TINMesh) print(6) sys.stdout.flush() out_path_pointfrommesh = os.path.join(rootPath, potfrommesh_folder) if os.path.exists(out_path_pointfrommesh): try: shutil.rmtree(out_path_pointfrommesh) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print(-1.0) sys.stdout.flush() os.mkdir(out_path_pointfrommesh) print(7) sys.stdout.flush() out_path_pointfrommeshfloat = os.path.join(rootPath, potfrommeshfloat_folder) if os.path.exists(out_path_pointfrommeshfloat): try: shutil.rmtree(out_path_pointfrommeshfloat) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print(-1.0) sys.stdout.flush() os.mkdir(out_path_pointfrommeshfloat) print(8) sys.stdout.flush() out_path_tif = os.path.join(rootPath, filltif_folder) if os.path.exists(out_path_tif): try: shutil.rmtree(out_path_tif) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print(-1.0) sys.stdout.flush() os.mkdir(out_path_tif) print(9) sys.stdout.flush() out_path_tif_pro = os.path.join(rootPath, filltifpro_folder) if os.path.exists(out_path_tif_pro): try: shutil.rmtree(out_path_tif_pro) time.sleep(2) # 防止删除操作未结束就运行mkdir() except Exception as e: print(-1.0) sys.stdout.flush() os.mkdir(out_path_tif_pro) print(10) sys.stdout.flush() def raster2points(fileName): inFile=work_space+singlehole_folder+fileName # 获取文件信息 rlayer = QgsRasterLayer(inFile, "SRTM layer name") tif_crs =rlayer.crs().toWkt() if not rlayer.isValid(): print("图层加载失败!") dataset = gdal.Open(inFile) gt = dataset.GetGeoTransform() Xmin = gt[0] Ymin = gt[3] width = dataset.RasterXSize height = dataset.RasterYSize Xmax = gt[0] + width*gt[1] + height*gt[2] Ymax = gt[3] + width*gt[4] + height*gt[5] extent = [Xmin,Xmax,min(Ymin,Ymax),max(Ymin,Ymax)] cellHeight = math.fabs(gt[1]) cellWidth = math.fabs(gt[5]) # #准备进行处理 # aid='saga:rastervaluestopoints' out_path = os.path.join(work_space,ras2pot_folder) outFile=out_path+fileName[0:fileName.index('.')]+'.geojson' # p = { # 'GRIDS': [inFile], # 'NODATA': True, # 'POLYGONS': None, # 'SHAPES': outFile, # 'TYPE': 0} # processing.run(aid, p) print(qgis_path) exe_path= qgis_path.split('python.exe')[0]+"saga_cmd.exe" print(exe_path) cammand_line=exe_path+" shapes_grid 3 -GRIDS {} -POLYGONS None -NODATA 1 -SHAPES {} -TYPE 0".format(inFile,outFile)# --flags[qr] process_status=subprocess.call(cammand_line) if 0!=process_status: print("error ") pro_aid = 'native:assignprojection' proFile = work_space+ras2potpro_folder+fileName[0:fileName.index('.')]+'.geojson' pro_p = { 'CRS': QgsCoordinateReferenceSystem('EPSG:4546'), 'INPUT': outFile, 'OUTPUT': proFile, } processing.run(pro_aid, pro_p) return fileName[0:fileName.index('.')]+'.geojson', cellHeight, cellWidth, tif_crs, extent def points2mesh(fileName,tif_crs): aid='native:tinmeshcreation' inFile=work_space+ras2potpro_folder+fileName optFile=work_space+tinmesh_folder+fileName[0:fileName.index('.')]+'.file' p={ 'CRS_OUTPUT' : QgsCoordinateReferenceSystem('EPSG:4546'), 'MESH_FORMAT' : 2, 'OUTPUT_MESH' : optFile, 'SOURCE_DATA' : [{'source': inFile,'type': 0,'attributeIndex': 3}] } processing.run(aid,p) return fileName[0:fileName.index('.')]+'.file' def getpointFromMesh(fileName, tif_crs,extent): inFile = work_space + tinmesh_folder + fileName if not os.path.exists(inFile): inFile = work_space + tinmesh_folder + fileName + '.ply' optFile = 'TEMPORARY_OUTPUT' aid = 'native:exportmeshongrid' # tif_crs p = {'CRS_OUTPUT' : QgsCoordinateReferenceSystem('EPSG:4546'), 'DATASET_GROUPS': [0], 'DATASET_TIME': {'type': 'static'}, 'EXTENT':None, 'GRID_SPACING': 0.05, 'INPUT' : inFile, 'OUTPUT': optFile, 'VECTOR_OPTION': 0} # 'EXTENT': '%.8f,%.8f,%.8f,%.8f [EPSG:4546]' % (extent[0],extent[1],extent[2],extent[3]), res = processing.run(aid, p) # Save as a shapefile Fl_ou = fileName[0:fileName.index('.')] + '.geojson' Fl_ou = work_space + potfrommesh_folder + Fl_ou options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = "geojson" QgsVectorFileWriter.writeAsVectorFormatV2(res['OUTPUT'], Fl_ou, QgsCoordinateTransformContext(), options) # TODO turn string to realNumber return fileName[0:fileName.index('.')] + '.geojson' def transString2float(fileName): inFile = work_space + potfrommesh_folder + fileName opt = work_space + potfrommeshfloat_folder + fileName optFile = open(opt, 'w') # minx=9999999 # maxx=0 # miny=99999999 # maxy=0 with open(inFile) as jsonFile: points = json.load(jsonFile) features = points['features'] for feature in features: properties = feature['properties'] Bed_Elevation = float(properties['Bed Elevation']) properties['Bed Elevation'] = Bed_Elevation # # geometry=feature['geometry'] ''' coordinates = geometry['coordinates'] x = coordinates[0] if minx>x: minx =x if maxx y: miny=y if maxy