ISCE_INSAR/contrib/stack/topsStack/cutUnWrapperBox.py

366 lines
12 KiB
Python
Raw Normal View History

2023-06-05 05:31:17 +00:00
# 裁剪 解缠后干涉图
# 注意 这个裁剪步骤并未纳入到标准的 干涉处理流程中,属于单独执行步骤
# 不考虑处理异常
# author :chenzenghui
# time : 2023.06.04
# 影像裁剪干涉图,这里使用 四至坐标进行裁剪
# 影像裁剪流程
# 1. 获取范围
# 2. 获取裁剪影像范围
# 3. 逐像素裁剪
# 4. 数据格式为isce专用格式
##############################
# 需要裁剪数据类型
# a. geom_reference
# 1. hgt.hdr
# 2. incLocal.hdr
# 3. lat.hdr
# 4. lon.hdr
# 5. los.hdr
# 6. shadowMask.hdr
# b. interferograms
# 1. filt_fine.unw.vrt
# c. SLC
##############################
import os
import sys
import numpy as np
from osgeo import gdal
import argparse
import shutil
import isce
import isceobj
from isce import logging
from iscesys.Component.Component import Component
from isceobj.Util.ImageUtil import ImageLib as IML
from isceobj.Image import createUnwImage
from osgeo import gdal,osr,ogr
logger = logging.getLogger('isce.insar')
def gdal2isce_xml(fname):
"""
Generate ISCE xml file from gdal supported file
Example: import isce
from applications.gdal2isce_xml import gdal2isce_xml
xml_file = gdal2isce_xml(fname+'.vrt')
"""
# open the GDAL file and get typical data informationi
GDAL2ISCE_DATATYPE = {
1 : 'BYTE',
2 : 'uint16',
3 : 'SHORT',
4 : 'uint32',
5 : 'INT',
6 : 'FLOAT',
7 : 'DOUBLE',
10: 'CFLOAT',
11: 'complex128',
}
# GDAL2NUMPY_DATATYPE = {
# 1 : np.uint8,
# 2 : np.uint16,
# 3 : np.int16,
# 4 : np.uint32,
# 5 : np.int32,
# 6 : np.float32,
# 7 : np.float64,
# 10: np.complex64,
# 11: np.complex128,
# }
# check if the input file is a vrt
fbase, fext = os.path.splitext(fname)
print(fext)
if fext == ".vrt":
outname = fbase
else:
outname = fname
print(outname)
# open the GDAL file and get typical ds information
ds = gdal.Open(fname, gdal.GA_ReadOnly)
width = ds.RasterXSize
length = ds.RasterYSize
bands = ds.RasterCount
print("width: " + "\t" + str(width))
print("length: " + "\t" + str(length))
print("num of bands:" + "\t" + str(bands))
# getting the datatype information
raster = ds.GetRasterBand(1)
dataTypeGdal = raster.DataType
# user look-up dictionary from gdal to isce format
dataType= GDAL2ISCE_DATATYPE[dataTypeGdal]
print("dataType: " + "\t" + str(dataType))
# transformation contains gridcorners (lines/pixels or lonlat and the spacing 1/-1 or deltalon/deltalat)
transform = ds.GetGeoTransform()
# if a complex data type, then create complex image
# if a real data type, then create a regular image
img = isceobj.createImage()
img.setFilename(os.path.abspath(outname))
img.setWidth(width)
img.setLength(length)
img.setAccessMode('READ')
img.bands = bands
img.dataType = dataType
# interleave
md = ds.GetMetadata('IMAGE_STRUCTURE')
sch = md.get('INTERLEAVE', None)
if sch == 'LINE':
img.scheme = 'BIL'
elif sch == 'PIXEL':
img.scheme = 'BIP'
elif sch == 'BAND':
img.scheme = 'BSQ'
else:
print('Unrecognized interleaving scheme, {}'.format(sch))
if bands < 2:
print('Assuming default, BIP')
img.scheme = 'BIP'
else:
print('Assuming default, BSQ')
img.scheme = 'BSQ'
img.firstLongitude = transform[0]
img.firstLatitude = transform[3]
img.deltaLatitude = transform[5]
img.deltaLongitude = transform[1]
xml_file = outname + ".xml"
img.dump(xml_file)
return xml_file
def get_geom_mask(bbox,lon_path,lat_path):
# bbox=[NSWE]
# 使用gdal 读取
# lon
lon_ds=gdal.Open(lon_path,gdal.GA_ReadOnly)
lat_ds=gdal.Open(lat_path,gdal.GA_ReadOnly)
#
lon_height=lon_ds.RasterYSize
lon_width=lon_ds.RasterYSize
lon_count=lon_ds.RasterCount
lat_height=lat_ds.RasterYSize
lat_width=lat_ds.RasterYSize
lat_count=lat_ds.RasterCount
if lon_height==lat_height and lon_width==lat_width and lon_count==lat_count:
print("lon and lat check pass!!!")
else:
logger.error("lon and lat check don't pass!!")
sys.exit(1)
lon_data=lon_ds.ReadAsArray()
lat_data=lat_ds.ReadAsArray()
S,N,W,E=bbox
mask=None
# 判断是否跨越+-180
if W-E>180: # 跨
mask=(lat_data<N) & (lat_data>S) & (lon_data<W) & (lon_data>E)
else:
mask=(lat_data<N) & (lat_data>S) & (lon_data>W) & (lon_data<E)
# 获取最大最小值
col_mask=np.sum(mask,axis=0)
line_mask=np.sum(mask,axis=1)
row_min=np.min(np.nonzero(line_mask))
row_max=np.max(np.nonzero(line_mask))+1
col_min=np.min(np.nonzero(col_mask))
col_max=np.max(np.nonzero(col_mask))+1
del col_mask,line_mask,lon_data,lat_data,lat_ds,lon_ds
#mask=mask[row_min:row_max,col_min:col_max]
return [row_min,row_max,col_min,col_max]#,mask
def repairGeom_refrence(source_geom_path,target_geo_path,mask_bbox,ext_vrt=".vrt",ext_xml=".aux.xml"):
# 读写文件
row_min,row_max,col_min,col_max=mask_bbox
# 文件名
vrt_path=source_geom_path+".vrt"
ds=gdal.Open(vrt_path)
band_num=ds.RasterCount
im_geotrans = ds.GetGeoTransform() #仿射矩阵,左上角像素的大地坐标和像素分辨率
im_proj = ds.GetProjection() #地图投影信息,字符串表示
# 使用gdal 进行计算
driver = gdal.GetDriverByName("ENVI")
datatype=ds.GetRasterBand(1).DataType
#datatype=gdal.GetDataTypeName(datatype)
dataset = driver.Create(target_geo_path, int(col_max-col_min), int(row_max-row_min), band_num, datatype)
if dataset.RasterCount!=band_num:
dataset = driver.Create(target_geo_path, int(col_max-col_min), int(row_max-row_min), band_num, datatype)
dataset.SetGeoTransform(im_geotrans)
dataset.SetProjection(im_proj)
# 保存数据
for i in range(band_num):
temp_data=ds.GetRasterBand(i+1).ReadAsArray()
temp_data=temp_data[row_min:row_max,col_min:col_max]
dataset.GetRasterBand(i+1).WriteArray(temp_data)
print(target_geo_path,dataset.RasterCount,band_num)
# 构建aux.xml
# 构建 vrt
gdal.Translate(target_geo_path+".vrt", dataset, options='-of VRT')
# 使用 gdal2isce_xml.py 构建坐标
gdal2isce_xml(target_geo_path)
del dataset,ds
def geom_referenceProcess(source_geom_reference_path,target_geom_reference_path,bbox):
# 1. hgt.hdr
# 2. incLocal.hdr
# 3. lat.hdr
# 4. lon.hdr
# 5. los.hdr
# 6. shadowMask.hdr
# a. source_geom_reference_path
hgt_path=os.path.join(source_geom_reference_path,"hgt.rdr")
incLocal_path=os.path.join(source_geom_reference_path,"incLocal.rdr")
lat_path=os.path.join(source_geom_reference_path,"lat.rdr")
lon_path=os.path.join(source_geom_reference_path,"lon.rdr")
los_path=os.path.join(source_geom_reference_path,"los.rdr")
shadowMask_path=os.path.join(source_geom_reference_path,"shadowMask.rdr")
# b. target_geom_reference_path
target_hgt_path=os.path.join(target_geom_reference_path,"hgt.rdr")
target_incLocal_path=os.path.join(target_geom_reference_path,"incLocal.rdr")
target_lat_path=os.path.join(target_geom_reference_path,"lat.rdr")
target_lon_path=os.path.join(target_geom_reference_path,"lon.rdr")
target_los_path=os.path.join(target_geom_reference_path,"los.rdr")
target_shadowMask_path=os.path.join(target_geom_reference_path,"shadowMask.rdr")
# c. clipmask
clipmask=get_geom_mask(bbox,lon_path,lat_path)
# step 1
repairGeom_refrence(hgt_path,target_hgt_path,clipmask,ext_vrt=".vrt",ext_xml=".xml")
repairGeom_refrence(incLocal_path,target_incLocal_path,clipmask,ext_vrt=".vrt",ext_xml=".xml")
repairGeom_refrence(lat_path,target_lat_path,clipmask,ext_vrt=".vrt",ext_xml=".xml")
repairGeom_refrence(lon_path,target_lon_path,clipmask,ext_vrt=".vrt",ext_xml=".xml")
repairGeom_refrence(los_path,target_los_path,clipmask,ext_vrt=".vrt",ext_xml=".xml")
repairGeom_refrence(shadowMask_path,target_shadowMask_path,clipmask)
return clipmask
pass
def ifgfileProcess(src_unw_path,to_unw_path,clipmask):
# umw 文件夹下文件类型
# filt_fine.cor ok
# filt_fine.int ok
# filt_fine.unw ok
# filt_fine.unw.conncomp ok
# fine.cor ok
# fine.cor.full ok
# fine.int ok
# fine.int.full ok
filenames=os.listdir(src_unw_path)
# 直接复制
for fname_copy in ["fine.cor.full","fine.int.full "]:
for filename in filenames:
if filename.find(fname_copy)>=0:
shutil.copyfile(
os.path.join(src_unw_path,filename),
os.path.join(to_unw_path,filename)
)
filenames.remove(filename)
else:
continue
# 处理其他文件
for fobjname in ["fine.int","filt_fine.cor","filt_fine.int","filt_fine.unw.conncomp"]: # band num = 1
repairGeom_refrence(os.path.join(src_unw_path,fobjname),
os.path.join(to_unw_path,fobjname),clipmask,ext_vrt=".vrt",ext_xml=".aux.xml")
for fobjname in ["fine.cor","filt_fine.unw"]: # band num=2
repairGeom_refrence(os.path.join(src_unw_path,fobjname),
os.path.join(to_unw_path,fobjname),clipmask,ext_vrt=".vrt",ext_xml=".aux.xml")
pass
def ifgProcess(src_ifg_path,to_ifg_path,clipmask):
for unw_foldername in os.listdir(src_ifg_path):
src_unw_path=os.path.join(src_ifg_path,unw_foldername)
if os.path.isdir(src_unw_path):
to_unw_path=os.path.join(to_ifg_path,unw_foldername)
# 清理文件夹
if os.path.exists(to_unw_path):
shutil.rmtree(to_unw_path)
else:
pass
os.makedirs(to_unw_path)
# 判断文件夹是否可用
ifgfileProcess(src_unw_path,to_unw_path,clipmask)
else:
continue
pass
def slcProcess(src_slc_path,to_slc_path):
if os.path.exists(to_slc_path):
shutil.rmtree(to_slc_path)
shutil.copytree(src_slc_path,to_slc_path)
def CutProcess(inps):
source_path=inps.source_path
outpath=inps.outpath
NoData=inps.Nodatavalue
bbox=inps.bbox
# 路径构建
src_geom_path=os.path.join(source_path,"geom_reference")
src_ifg_path=os.path.join(source_path,"interferograms")
src_slc_path=os.path.join(source_path,"SLC")
to_geom_path=os.path.join(outpath,"geom_reference")
to_ifg_path=os.path.join(outpath,"interferograms")
to_slc_path=os.path.join(outpath,"SLC")
for folder_path in [to_geom_path,to_ifg_path,to_slc_path]:
if os.path.exists(folder_path):
shutil.rmtree(folder_path)
os.makedirs(folder_path)
# geom_reference
clipmask=geom_referenceProcess(src_geom_path,to_geom_path,bbox)
# ifg
ifgProcess(src_ifg_path,to_ifg_path,clipmask)
# SLC 直接复制
slcProcess(src_slc_path,to_slc_path)
def main():
#if not argument provided force the --help flag
if(len(sys.argv) == 1):
sys.argv.append('-h')
# Use the epilog to add usage examples
epilog = '将格式为tif 的DEM 转换为ISCE 支持的DEM格式:\n\n'
epilog += 'Usage examples:\n\n'
epilog += 'cutUnWrapper.py -i merge_folder_path -o new_merge_folder_path -b "37.8 38 109.2 109.3" \n\n'
#set the formatter_class=argparse.RawDescriptionHelpFormatter otherwise it splits the epilog lines with its own default format
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,epilog=epilog)
parser.add_argument('-i', '--source', type = str, default ="/mnt/e/isce2/cygwin_sice2/merged", dest = 'source_path', help = '输入 merged 文件夹地址')
parser.add_argument('-o', '--outpath', type = str, default = '/mnt/e/isce2/cygwin_sice2/new_merged', dest = 'outpath', help = '输出文件 merged 文件夹地址')
parser.add_argument('-b', '--bbox', type = str, default = "37.8 38 109.2 109.3", dest = 'bbox', help = '裁剪bbox')
parser.add_argument('-Nodata', '--Nodata', type = float, default = 0.0, dest = 'Nodatavalue', help = '解缠无效值填充')
args = parser.parse_args()
args.bbox=[float(i) for i in args.bbox.split()]
CutProcess(args)
# processDEM2ISCE("DEM2ISCE",args.source_path,args.outpath,args.fillvalue,args.Nodatavalue)
return -1
if __name__=="__main__":
# 测试
sys.exit(main())