# 一米正射辅助数据处理类 import time import math import numpy as np from osgeo import gdal from xml.etree.ElementTree import ElementTree from scipy.optimize import leastsq class OrthoAuxData: def __init__(self): pass @staticmethod def time_stamp(tm): list = tm.split(':') sec = math.ceil(float(list[2])) tm1 = list[0] + ':' + list[1] + ':' + str(sec) tmArr = time.strptime(tm1, "%Y-%m-%d %H:%M:%S") # tmArr = time.strptime(tm1, "%Y-%m-%d %H:%M:%S.%f") ts = float(time.mktime(tmArr)) # 转换为时间戳 return ts @staticmethod def read_meta(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() T = [] Xs = [] Ys = [] Zs = [] Vsx = [] Vsy = [] Vsz = [] GPS_data = root.find('GPS') for child in GPS_data: Xs.append(float(child.find('xPosition').text)) Ys.append(float(child.find('yPosition').text)) Zs.append(float(child.find('zPosition').text)) Vsx.append(float(child.find('xVelocity').text)) Vsy.append(float(child.find('yVelocity').text)) Vsz.append(float(child.find('zVelocity').text)) tm = child.find('TimeStamp').text ts = OrthoAuxData.time_stamp(tm) T.append(ts) meta_data = [Xs, Ys, Zs, Vsx, Vsy, Vsz] return T, meta_data @staticmethod def read_control_points(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() imageinfo = root.find('imageinfo') center = imageinfo.find('center') corner = imageinfo.find('corner') ctrl_pts = [[] for i in range(2)] ctrl_pts[0].append(float(center.find('longitude').text)) ctrl_pts[1].append(float(center.find('latitude').text)) for child in corner: ctrl_pts[0].append(float(child.find('longitude').text)) ctrl_pts[1].append(float(child.find('latitude').text)) return ctrl_pts @staticmethod def read_dem(dem_resampled_path, flag=1): in_ds = gdal.Open(dem_resampled_path) gt = list(in_ds.GetGeoTransform()) bands_num = in_ds.RasterCount x_size = in_ds.RasterXSize y_size = in_ds.RasterYSize pstn_arr = np.zeros([y_size, x_size, 3], dtype=np.float) for i in range(1, bands_num + 1): data = in_ds.GetRasterBand(i).ReadAsArray(0, 0, x_size, y_size) for y in range(y_size): for x in range(x_size): longitude = gt[0] + x * gt[1] latitude = gt[3] + y * gt[5] altitude = data[y, x] if flag == 1: pstn = OrthoAuxData.LLA2XYZ(longitude, latitude, altitude) else: pstn = [longitude, latitude, altitude] pstn_arr[y, x, 0] = pstn[0] pstn_arr[y, x, 1] = pstn[1] pstn_arr[y, x, 2] = pstn[2] del in_ds, data return pstn_arr @staticmethod def read_demM(dem_resampled_path, part_cnt, r_cnt, c_cnt, flag=1): in_ds = gdal.Open(dem_resampled_path) gt = list(in_ds.GetGeoTransform()) bands_num = in_ds.RasterCount x_size = in_ds.RasterXSize // part_cnt y_size = in_ds.RasterYSize // part_cnt x = [[i] * y_size for i in range(x_size)] y = [[i] * x_size for i in range(y_size)] x = np.array(x) x = x.T y = np.array(y) x_off = c_cnt * x_size y_off = r_cnt * y_size gt[0] = gt[0] + c_cnt * x_size * gt[1] gt[3] = gt[3] + r_cnt * y_size * gt[5] for i in range(1, bands_num + 1): data = in_ds.GetRasterBand(i).ReadAsArray(x_off, y_off, x_size, y_size) altitude = data / 255 * 1024 longitude = gt[0] + x * gt[1] latitude = gt[3] + y * gt[5] if flag == 1: pstn = OrthoAuxData.LLA2XYZM(longitude, latitude, altitude) else: pstn = [longitude, latitude, altitude] del in_ds, data return pstn @staticmethod def read_dem_row(dem_resampled_path, p, flag=1): in_ds = gdal.Open(dem_resampled_path) gt = list(in_ds.GetGeoTransform()) bands_num = in_ds.RasterCount x_size = in_ds.RasterXSize y_size = in_ds.RasterYSize x = [[i] for i in range(x_size)] x = np.array(x) x = x.T y = np.ones((1, x_size)) * p x_off = 0 y_off = p for i in range(1, bands_num + 1): data = in_ds.GetRasterBand(i).ReadAsArray(x_off, y_off, x_size, 1) altitude = data longitude = gt[0] + x * gt[1] latitude = gt[3] + y * gt[5] if flag == 1: pstn = OrthoAuxData.LLA2XYZM(longitude, latitude, altitude) else: pstn = [longitude, latitude, altitude] del in_ds, data return pstn @staticmethod def orbit_fitting(time_array, meta_data): # 最小二乘法求解轨道参数 T0 = (time_array[0] + time_array[len(time_array)-1]) / 2 t = [] for i in range(len(time_array)): t.append(time_array[i]-T0) def func(p, x): w3, w2, w1, w0 = p return w3*x**3 + w2*x**2 + w1*x + w0 def error(p, x, y): return func(p, x) - y orbital_paras = [] for j in range(len(meta_data)): p0 = [1, 2, 3, 4] x = np.array(t) y = np.array(meta_data[j]) Para = leastsq(error, p0, args=(x, y)) orbital_paras.append(Para[0]) print(Para[0], Para[1]) return orbital_paras, T0 @staticmethod def get_PRF(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() sensor = root.find('sensor') waveParams = sensor.find('waveParams') PRF = float(waveParams.find('wave').find('prf').text) return PRF @staticmethod def get_delta_R(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() sensor = root.find('sensor') pulseWidth = float(sensor.find('waveParams').find('wave').find('pulseWidth').text) bandWidth = float(sensor.find('waveParams').find('wave').find('bandWidth').text) c = 299792458 delta_R = c / (1000000 * 2 * bandWidth) return delta_R @staticmethod def get_doppler_rate_coef(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() processinfo = root.find('processinfo') doppler = processinfo.find('DopplerRateValuesCoefficients') t0 = float(processinfo.find('DopplerParametersReferenceTime').text) r0 = float(doppler.find('r0').text) r1 = float(doppler.find('r1').text) r2 = float(doppler.find('r2').text) r3 = float(doppler.find('r3').text) r4 = float(doppler.find('r4').text) return t0, np.array([r0, r1, r2, r3, r4]).reshape(5, 1) @staticmethod def get_doppler_center_coef(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() processinfo = root.find('processinfo') doppler = processinfo.find('DopplerCentroidCoefficients') b0 = float(doppler.find('d0').text) b1 = float(doppler.find('d1').text) b2 = float(doppler.find('d2').text) return b0, b1, b2 @staticmethod def get_lamda(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() sensor = root.find('sensor') λ = float(sensor.find('lamda').text) return λ @staticmethod def get_t0(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() imageinfo = root.find('imageinfo') tm = imageinfo.find('imagingTime').find('start').text t0 = OrthoAuxData.time_stamp(tm) return t0 @staticmethod def get_start_and_end_time(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() imageinfo = root.find('imageinfo') tm0 = imageinfo.find('imagingTime').find('start').text tm1 = imageinfo.find('imagingTime').find('end').text starttime = OrthoAuxData.time_stamp(tm0) endtime = OrthoAuxData.time_stamp(tm1) return starttime, endtime @staticmethod def get_width_and_height(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() imageinfo = root.find('imageinfo') width = int(imageinfo.find('width').text) height = int(imageinfo.find('height').text) return width, height @staticmethod def get_R0(meta_file_path): tree = ElementTree() tree.parse(meta_file_path) root = tree.getroot() imageinfo = root.find('imageinfo') R0 = float(imageinfo.find('nearRange').text) return R0 @staticmethod def get_h(): h = 6.6 return h @staticmethod def LLA2XYZ(longitude, latitude, altitude): ''' WGS-84坐标系下:经纬度坐标转空间直角坐标 ''' # 经纬度余弦值 cosLat = math.cos(latitude * math.pi / 180) sinLat = math.sin(latitude * math.pi / 180) cosLon = math.cos(longitude * math.pi / 180) sinLon = math.sin(longitude * math.pi / 180) # WGS84坐标系参数 rad = 6378137.0 #地球赤道平均半径 f = 1.0/298.257224 #WGS84椭球扁率 C = 1.0/math.sqrt(cosLat*cosLat + (1-f)*(1-f)*sinLat*sinLat) S = (1-f)*(1-f)*C h = altitude # 计算XYZ坐标 X = (rad * C + h) * cosLat * cosLon Y = (rad * C + h) * cosLat * sinLon Z = (rad * S + h) * sinLat # return np.array([X, Y, Z]).reshape(1,3) return [X, Y, Z] @staticmethod def LLA2XYZM(longitude, latitude, altitude): # 经纬度余弦值 cosLat = np.cos(latitude * math.pi / 180).reshape(-1,1) sinLat = np.sin(latitude * math.pi / 180).reshape(-1,1) cosLon = np.cos(longitude * math.pi / 180).reshape(-1,1) sinLon = np.sin(longitude * math.pi / 180).reshape(-1,1) # WGS84坐标系参数 rad = 6378137.0 #地球赤道平均半径 f = 1.0/298.257224 #WGS84椭球扁率 C = 1.0/(np.sqrt(cosLat*cosLat + (1-f)*(1-f)*sinLat*sinLat)).reshape(-1,1) S = (1-f)*(1-f)*C h = altitude.reshape(-1,1) # 计算XYZ坐标 X = (rad * C + h) * cosLat * cosLon Y = (rad * C + h) * cosLat * sinLon Z = (rad * S + h) * sinLat return [X, Y, Z] @staticmethod def XYZ2LLA(X, Y, Z): ''' 大地坐标系转经纬度 适用于WGS84坐标系 args: x,y,z return: lat,long,altitude ''' # WGS84坐标系的参数 a = 6378137.0 # 椭球长半轴 b = 6356752.314245 # 椭球短半轴 ea = np.sqrt((a ** 2 - b ** 2) / a ** 2) eb = np.sqrt((a ** 2 - b ** 2) / b ** 2) p = np.sqrt(X ** 2 + Y ** 2) theta = np.arctan2(Z * a, p * b) # 计算经纬度及海拔 longitude = np.arctan2(Y, X) latitude = np.arctan2(Z + eb ** 2 * b * np.sin(theta) ** 3, p - ea ** 2 * a * np.cos(theta) ** 3) N = a / np.sqrt(1 - ea ** 2 * np.sin(latitude) ** 2) altitude = p / np.cos(latitude) - N # return np.array([np.degrees(latitude), np.degrees(longitude), altitude]) return [np.degrees(longitude), np.degrees(latitude), altitude] @staticmethod def XYZ2LLAM(X, Y, Z): ''' 大地坐标系转经纬度 适用于WGS84坐标系 args: x,y,z return: lat,long,altitude ''' # WGS84坐标系的参数 a = 6378137.0 # 椭球长半轴 b = 6356752.314245 # 椭球短半轴 ea = np.sqrt((a ** 2 - b ** 2) / a ** 2) eb = np.sqrt((a ** 2 - b ** 2) / b ** 2) p = np.sqrt(X ** 2 + Y ** 2) theta = np.arctan2(Z * a, p * b) # 计算经纬度及海拔 longitude = np.arctan2(Y, X) latitude = np.arctan2(Z + eb ** 2 * b * np.sin(theta) ** 3, p - ea ** 2 * a * np.cos(theta) ** 3) N = a / np.sqrt(1 - ea ** 2 * np.sin(latitude) ** 2) altitude = p / np.cos(latitude) - N # return np.array([np.degrees(latitude), np.degrees(longitude), altitude]) return [np.degrees(longitude), np.degrees(latitude), altitude] @staticmethod def world2Pixel(geoMatrix, x, y): """ 使用GDAL库的geomatrix对象((gdal.GetGeoTransform()))计算地理坐标的像素位置 """ ulx = geoMatrix[0] uly = geoMatrix[3] xDist = geoMatrix[1] yDist = geoMatrix[5] rtnX = geoMatrix[2] rtnY = geoMatrix[4] pixel = int((x - ulx) / xDist) line = int((uly - y) / abs(yDist)) return pixel, line @staticmethod def sar_intensity_synthesis(in_sar_tif, out_sar_tif): # 获取SLC格式SAR影像的相关信息 in_ds = gdal.Open(in_sar_tif) bands_num = in_ds.RasterCount rows = in_ds.RasterYSize columns = in_ds.RasterXSize proj = in_ds.GetProjection() geotrans = in_ds.GetGeoTransform() # 创建输出的SAR强度图 gtiff_driver = gdal.GetDriverByName('GTiff') out_ds = gtiff_driver.Create(out_sar_tif, columns, rows, 1) out_ds.SetProjection(proj) out_ds.SetGeoTransform(geotrans) # 输出SAR强度图 in_data1 = in_ds.GetRasterBand(1).ReadAsArray(0, 0, columns, rows) in_data1 = in_data1/10 in_data1 = np.power(10, in_data1) in_data2 = in_ds.GetRasterBand(2).ReadAsArray(0, 0, columns, rows) in_data2 = in_data2 / 10 in_data2 = np.power(10, in_data2) out_data = np.sqrt(in_data1**2 + in_data2**2) out_ds.GetRasterBand(1).WriteArray(out_data) del in_ds, out_ds