前言
经过前三章的探索,所有的技术难点已经全部打通了,如果只是单纯的使用在某张影像或者某类影像的处理,那么只需要设计一个简易的面向过程代码即可。
但这并不符合我最初的目的——即一个通用的高分影像批处理工具。因此我尝试了两种方案,一种是面向过程的写法,即为不同高分型号卫星编写不同的处理模块,然后编写一个调度器根据高分卫星型号负责调度不同的处理模块,最终完成了一个初级的代码,并且完成了其多进程和多线程的版本。但是这样的编写有一个重要的问题:很难在此基础上进行改写和修正,不利于代码的复用和修改,没有提供一个很好的接口供别人调用。第一种的单个文件局部代码附在最后。一种是面向对象的写法,在最近几天刚刚完成,下面重点介绍面向对象设计的写法。
面向对象设计
抽象类
我们的核心任务是处理GF数据,不同的高分数据由于其处理的方法细节不同,因此应该是不同的类。但是不同的类之间又有许多共同点,因此可以设计一个抽象类,不同型号卫星的类在此抽象父类的基础上继承。
抽象父类需要具有以下必须实现的方法,也就是我们处理的任务:
获取卫星对象的基本信息,这是为其他处理任务做准备工作
- 进行辐射定标
- 进行大气校正
- 进行几何校正
- 进行大气校正和几何校正
- 对象销毁时删除中间文件
基于这样的准则,设计的抽象类代码如下:
from abc import ABC
from abc import abstractmethod
class GFPCore(ABC):
@staticmethod
def parse_rpc_file(rpc_file):
# rpc_file:.rpc文件的绝对路径
# rpc_dict:符号RPC域下的16个关键字的字典
# 参考网址:http://geotiff.maptools.org/rpc_prop.html;
# https://www.osgeo.cn/gdal/development/rfc/rfc22_rpc.html
rpc_dict = {}
with open(rpc_file) as f:
text = f.read()
# .rpc文件中的RPC关键词
words = ['errBias', 'errRand', 'lineOffset', 'sampOffset', 'latOffset',
'longOffset', 'heightOffset', 'lineScale', 'sampScale', 'latScale',
'longScale', 'heightScale', 'lineNumCoef', 'lineDenCoef','sampNumCoef', 'sampDenCoef',]
# GDAL库对应的RPC关键词
keys = ['ERR_BIAS', 'ERR_RAND', 'LINE_OFF', 'SAMP_OFF', 'LAT_OFF', 'LONG_OFF',
'HEIGHT_OFF', 'LINE_SCALE', 'SAMP_SCALE', 'LAT_SCALE',
'LONG_SCALE', 'HEIGHT_SCALE', 'LINE_NUM_COEFF', 'LINE_DEN_COEFF',
'SAMP_NUM_COEFF', 'SAMP_DEN_COEFF']
for old, new in zip(words, keys):
text = text.replace(old, new)
# 以‘;\n’作为分隔符
text_list = text.split(';\n')
# 删掉无用的行
text_list = text_list[3:-2]
#
text_list[0] = text_list[0].split('\n')[1]
# 去掉制表符、换行符、空格
text_list = [item.strip('\t').replace('\n', '').replace(' ', '') for item in text_list]
for item in text_list:
# 去掉‘=’
key, value = item.split('=')
# 去掉多余的括号‘(’,‘)’
if '(' in value:
value = value.replace('(', '').replace(')', '')
rpc_dict[key] = value
for key in keys[:12]:
# 为正数添加符号‘+’
if not rpc_dict[key].startswith('-'):
rpc_dict[key] = '+' + rpc_dict[key]
# 为归一化项和误差标志添加单位
if key in ['LAT_OFF', 'LONG_OFF', 'LAT_SCALE', 'LONG_SCALE']:
rpc_dict[key] = rpc_dict[key] + ' degrees'
if key in ['LINE_OFF', 'SAMP_OFF', 'LINE_SCALE', 'SAMP_SCALE']:
rpc_dict[key] = rpc_dict[key] + ' pixels'
if key in ['ERR_BIAS', 'ERR_RAND', 'HEIGHT_OFF', 'HEIGHT_SCALE']:
rpc_dict[key] = rpc_dict[key] + ' meters'
# 处理有理函数项
for key in keys[-4:]:
values = []
for item in rpc_dict[key].split(','):
#print(item)
if not item.startswith('-'):
values.append('+'+item)
else:
values.append(item)
rpc_dict[key] = ' '.join(values)
return rpc_dict
@abstractmethod
def acquireGainBais():
"""
获取定标参数
"""
@abstractmethod
def radiometricCalibration(self,*args, **kwargs):
"""
辐射定标
"""
@abstractmethod
def