123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- # -*- coding: utf-8 -*-
- __author__ = 'wanger'
- __description__ = '批量生成栅格数据元数据表格 EXCEL'
- __date__ = '2024-11-25'
- __copyright__ = '(C) 2024 by siwei'
- __revision__ = '1.0'
- from osgeo import gdal, osr
- import openpyxl
- from utils import *
- # TODO 栅格数据文件夹
- folder_path = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\make\\data'
- # TODO 元数据输出文件夹
- output_path = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\make\\metadata'
- # TODO 元数据模板路径
- templatepath = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\make\\template\\template.xlsx'
- # 获取元数据模板文件所在的目录
- templatedirectory = os.path.dirname(os.path.abspath(templatepath))
- # TODO 空间分析图层位置 默认在模板文件夹内有一个overlap.shp 点线面要素无所谓
- overlapVectorPath = f"{templatedirectory}\\overlap.shp"
- # 绑定需要从shp数据提取的信息
- # data_gain_date 影像/数据获取时间
- # data_resolution 影像分辨率/点云密度
- overlapParams = {
- "data_resolution": "resolution",
- "data_gain_date": "gaindate"
- }
- # 遍历文件夹中的所有文件
- for filename in os.listdir(folder_path):
- filepath = os.path.join(folder_path, filename)
- # 检查文件扩展名
- if filename.endswith('.img') or filename.endswith('.tif'):
- # filepath = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\数据\\分幅成果\\DEM成果\\DEM\\NH48G053055DEMK.img'
- dataset = gdal.Open(filepath)
- # TODO 读取图号
- image_number, image_format = getImageNumberAndFormat(filepath)
- file_size = getFileSize(filepath)
- if dataset:
- # TODO 获取栅格数据的行数、列数
- grid_row = dataset.RasterYSize
- grid_col = dataset.RasterXSize
- # TODO 格网单元尺寸
- grid_size = 2
- # TODO波段数
- band_size = dataset.RasterCount
- # TODO 无效值 list 用逗号隔开
- nodata_list = []
- # TODO 计算高程记录的小数点位数
- decimal_number = None
- for band_index in range(1, dataset.RasterCount + 1):
- band = dataset.GetRasterBand(band_index)
- nodata_list.append(band.GetNoDataValue())
- stats = band.GetStatistics(True, True) # 获取统计信息
- min_value, max_value = stats[0], stats[1]
- if min_value is not None and max_value is not None:
- # 获取高程小数位数的最大可能值
- decimal_number = max(len(str(min_value).split(".")[-1]),
- len(str(max_value).split(".")[-1])) if '.' in str(
- min_value) else 0
- # TODO 获取栅格数据左上角标
- cornerpoint = getImageLeftTop(dataset)
- # 获取地理信息
- geo_transform = dataset.GetGeoTransform()
- # 获取投影信息
- projection = dataset.GetProjection()
- # 获取栅格数据的投影信息
- # 创建 SpatialReference 对象并加载投影信息
- spatial_ref = osr.SpatialReference()
- spatial_ref.ImportFromWkt(projection)
- # TODO 投影参数集合
- central_meridian = None
- ellipsoid_radius = None
- ellipsoid_flat = None
- geodetic_datum = None
- projection_name = None
- divided_into_zones = "无分带"
- with_number = "无代号"
- plane_coordinate_unit = "米"
- altitude_name = "正常高"
- altitude_benchmark = "1985国家高程基准"
- if spatial_ref.IsProjected():
- # TODO 中央子午线
- central_meridian = processingNumericalValues(spatial_ref.GetProjParm(osr.SRS_PP_CENTRAL_MERIDIAN))
- # TODO 椭球长半径
- ellipsoid_radius = processingNumericalValues(spatial_ref.GetSemiMajor()) # 长半轴
- # TODO 椭球扁率
- ellipsoid_flat = f"1/{spatial_ref.GetInvFlattening():.3f}" # 反扁率(1/扁率)
- # TODO 所采用大地基准
- geodetic_datum = spatial_ref.GetAttrValue("DATUM")
- # TODO 地图投影名称
- projection_name = spatial_ref.GetAttrValue("PROJECTION")
- # TODO 分带方式(适用于 UTM)
- if geodetic_datum == "China_2000":
- if projection.__contains__("-degree"):
- number = projection.split("-degree")[0][-1:]
- divided_into_zones = f'{number}度带'
- with_number = int(central_meridian / int(number))
- elif spatial_ref.IsProjected() and "UTM" in projection:
- zone = spatial_ref.GetUTMZone()
- divided_into_zones = "UTM分带" if zone else "其他"
- with_number = zone if zone else "N/A"
- # TODO 平面坐标单位
- plane_coordinate_unit = spatial_ref.GetLinearUnitsName()
- linear_units = spatial_ref.GetLinearUnits() # 单位与米的换算关系
- # 高程系统(如果有)
- altitude_name = spatial_ref.GetAttrValue("VERT_CS")
- altitude_benchmark = spatial_ref.GetAttrValue("VERT_DATUM")
- metadatadict = {
- "image_number": image_number,
- "data_format": image_format,
- "data_volume": file_size,
- "grid_size": grid_size,
- "grid_row": grid_row,
- "grid_col": grid_col,
- "decimal_number": decimal_number,
- "nodata_number": ",".join(map(str, nodata_list)),
- "cornerpoint_lon": cornerpoint["lon"],
- "cornerpoint_lat": cornerpoint["lat"],
- "cornerpoint_x": cornerpoint["x"],
- "cornerpoint_y": cornerpoint["y"],
- "ellipsoid_radius": ellipsoid_radius,
- "ellipsoid_flat": ellipsoid_flat,
- "geodetic_datum": "2000国家大地坐标系" if geodetic_datum == "China_2000" else geodetic_datum,
- "projection_name": "高斯-克吕格投影" if projection_name == "Transverse_Mercator" else projection_name,
- "central_meridian": central_meridian,
- "divided_into_zones": divided_into_zones,
- "with_number": with_number,
- "plane_coordinate_unit": "米" if plane_coordinate_unit == "metre" else plane_coordinate_unit,
- "altitude_name": altitude_name,
- "altitude_benchmark": altitude_benchmark
- }
- # TODO 空间叠加
- for key in overlapParams:
- value = overlapParams[key]
- largest_feature = get_largest_overlapping_feature(raster_path=filepath, shp_path=overlapVectorPath)
- field_value = largest_feature[value]
- metadatadict[key] = field_value
- # 利用模板生成excel
- workbook = openpyxl.load_workbook(templatepath)
- sheet = workbook.active
- # 定义替换数据的字典
- replacements = {}
- for attr in metadatadict:
- key = f"<{attr}>"
- value = metadatadict[attr]
- replacements[key] = value
- # 遍历单元格,替换占位符
- for row in sheet.iter_rows():
- for cell in row:
- if isinstance(cell.value, str): # 确保单元格内容是字符串
- for placeholder, replacement in replacements.items():
- if placeholder in cell.value:
- # 替换占位符
- cell.value = cell.value.replace(placeholder, str(replacement))
- # 保存修改后的文件
- workbook.save(f'{output_path}\\{image_number}.xlsx')
|