Metadata.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. # -*- coding: utf-8 -*-
  2. __author__ = 'wanger'
  3. __description__ = '批量生成栅格数据元数据表格 EXCEL'
  4. __date__ = '2024-11-25'
  5. __copyright__ = '(C) 2024 by siwei'
  6. __revision__ = '1.0'
  7. from osgeo import gdal, osr
  8. import openpyxl
  9. from utils import *
  10. # TODO 栅格数据文件夹
  11. folder_path = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\make\\data'
  12. # TODO 元数据输出文件夹
  13. output_path = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\make\\metadata'
  14. # TODO 元数据模板路径
  15. templatepath = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\make\\template\\template.xlsx'
  16. # 获取元数据模板文件所在的目录
  17. templatedirectory = os.path.dirname(os.path.abspath(templatepath))
  18. # TODO 空间分析图层位置 默认在模板文件夹内有一个overlap.shp 点线面要素无所谓
  19. overlapVectorPath = f"{templatedirectory}\\overlap.shp"
  20. # 绑定需要从shp数据提取的信息
  21. # data_gain_date 影像/数据获取时间
  22. # data_resolution 影像分辨率/点云密度
  23. overlapParams = {
  24. "data_resolution": "resolution",
  25. "data_gain_date": "gaindate"
  26. }
  27. # 遍历文件夹中的所有文件
  28. for filename in os.listdir(folder_path):
  29. filepath = os.path.join(folder_path, filename)
  30. # 检查文件扩展名
  31. if filename.endswith('.img') or filename.endswith('.tif'):
  32. # filepath = 'E:\\projects\\遥感技术部需求\\批量生成元数据\\数据\\分幅成果\\DEM成果\\DEM\\NH48G053055DEMK.img'
  33. dataset = gdal.Open(filepath)
  34. # TODO 读取图号
  35. image_number, image_format = getImageNumberAndFormat(filepath)
  36. file_size = getFileSize(filepath)
  37. if dataset:
  38. # TODO 获取栅格数据的行数、列数
  39. grid_row = dataset.RasterYSize
  40. grid_col = dataset.RasterXSize
  41. # TODO 格网单元尺寸
  42. grid_size = 2
  43. # TODO波段数
  44. band_size = dataset.RasterCount
  45. # TODO 无效值 list 用逗号隔开
  46. nodata_list = []
  47. # TODO 计算高程记录的小数点位数
  48. decimal_number = None
  49. for band_index in range(1, dataset.RasterCount + 1):
  50. band = dataset.GetRasterBand(band_index)
  51. nodata_list.append(band.GetNoDataValue())
  52. stats = band.GetStatistics(True, True) # 获取统计信息
  53. min_value, max_value = stats[0], stats[1]
  54. if min_value is not None and max_value is not None:
  55. # 获取高程小数位数的最大可能值
  56. decimal_number = max(len(str(min_value).split(".")[-1]),
  57. len(str(max_value).split(".")[-1])) if '.' in str(
  58. min_value) else 0
  59. # TODO 获取栅格数据左上角标
  60. cornerpoint = getImageLeftTop(dataset)
  61. # 获取地理信息
  62. geo_transform = dataset.GetGeoTransform()
  63. # 获取投影信息
  64. projection = dataset.GetProjection()
  65. # 获取栅格数据的投影信息
  66. # 创建 SpatialReference 对象并加载投影信息
  67. spatial_ref = osr.SpatialReference()
  68. spatial_ref.ImportFromWkt(projection)
  69. # TODO 投影参数集合
  70. central_meridian = None
  71. ellipsoid_radius = None
  72. ellipsoid_flat = None
  73. geodetic_datum = None
  74. projection_name = None
  75. divided_into_zones = "无分带"
  76. with_number = "无代号"
  77. plane_coordinate_unit = "米"
  78. altitude_name = "正常高"
  79. altitude_benchmark = "1985国家高程基准"
  80. if spatial_ref.IsProjected():
  81. # TODO 中央子午线
  82. central_meridian = processingNumericalValues(spatial_ref.GetProjParm(osr.SRS_PP_CENTRAL_MERIDIAN))
  83. # TODO 椭球长半径
  84. ellipsoid_radius = processingNumericalValues(spatial_ref.GetSemiMajor()) # 长半轴
  85. # TODO 椭球扁率
  86. ellipsoid_flat = f"1/{spatial_ref.GetInvFlattening():.3f}" # 反扁率(1/扁率)
  87. # TODO 所采用大地基准
  88. geodetic_datum = spatial_ref.GetAttrValue("DATUM")
  89. # TODO 地图投影名称
  90. projection_name = spatial_ref.GetAttrValue("PROJECTION")
  91. # TODO 分带方式(适用于 UTM)
  92. if geodetic_datum == "China_2000":
  93. if projection.__contains__("-degree"):
  94. number = projection.split("-degree")[0][-1:]
  95. divided_into_zones = f'{number}度带'
  96. with_number = int(central_meridian / int(number))
  97. elif spatial_ref.IsProjected() and "UTM" in projection:
  98. zone = spatial_ref.GetUTMZone()
  99. divided_into_zones = "UTM分带" if zone else "其他"
  100. with_number = zone if zone else "N/A"
  101. # TODO 平面坐标单位
  102. plane_coordinate_unit = spatial_ref.GetLinearUnitsName()
  103. linear_units = spatial_ref.GetLinearUnits() # 单位与米的换算关系
  104. # 高程系统(如果有)
  105. altitude_name = spatial_ref.GetAttrValue("VERT_CS")
  106. altitude_benchmark = spatial_ref.GetAttrValue("VERT_DATUM")
  107. metadatadict = {
  108. "image_number": image_number,
  109. "data_format": image_format,
  110. "data_volume": file_size,
  111. "grid_size": grid_size,
  112. "grid_row": grid_row,
  113. "grid_col": grid_col,
  114. "decimal_number": decimal_number,
  115. "nodata_number": ",".join(map(str, nodata_list)),
  116. "cornerpoint_lon": cornerpoint["lon"],
  117. "cornerpoint_lat": cornerpoint["lat"],
  118. "cornerpoint_x": cornerpoint["x"],
  119. "cornerpoint_y": cornerpoint["y"],
  120. "ellipsoid_radius": ellipsoid_radius,
  121. "ellipsoid_flat": ellipsoid_flat,
  122. "geodetic_datum": "2000国家大地坐标系" if geodetic_datum == "China_2000" else geodetic_datum,
  123. "projection_name": "高斯-克吕格投影" if projection_name == "Transverse_Mercator" else projection_name,
  124. "central_meridian": central_meridian,
  125. "divided_into_zones": divided_into_zones,
  126. "with_number": with_number,
  127. "plane_coordinate_unit": "米" if plane_coordinate_unit == "metre" else plane_coordinate_unit,
  128. "altitude_name": altitude_name,
  129. "altitude_benchmark": altitude_benchmark
  130. }
  131. # TODO 空间叠加
  132. for key in overlapParams:
  133. value = overlapParams[key]
  134. largest_feature = get_largest_overlapping_feature(raster_path=filepath, shp_path=overlapVectorPath)
  135. field_value = largest_feature[value]
  136. metadatadict[key] = field_value
  137. # 利用模板生成excel
  138. workbook = openpyxl.load_workbook(templatepath)
  139. sheet = workbook.active
  140. # 定义替换数据的字典
  141. replacements = {}
  142. for attr in metadatadict:
  143. key = f"<{attr}>"
  144. value = metadatadict[attr]
  145. replacements[key] = value
  146. # 遍历单元格,替换占位符
  147. for row in sheet.iter_rows():
  148. for cell in row:
  149. if isinstance(cell.value, str): # 确保单元格内容是字符串
  150. for placeholder, replacement in replacements.items():
  151. if placeholder in cell.value:
  152. # 替换占位符
  153. cell.value = cell.value.replace(placeholder, str(replacement))
  154. # 保存修改后的文件
  155. workbook.save(f'{output_path}\\{image_number}.xlsx')