修改metadata.xml,添加boundingbox

This commit is contained in:
weixin_46229132 2025-02-14 17:31:39 +08:00
parent 9b151d0768
commit 3df39f76d2
5 changed files with 82 additions and 34 deletions

View File

@ -1,6 +1,6 @@
import argparse
from datetime import timedelta
from odm_preprocess import PreprocessConfig, ImagePreprocessor
from odm_preprocess_fast import PreprocessConfig, ImagePreprocessor
def parse_args():
parser = argparse.ArgumentParser(description='ODM预处理工具')

View File

@ -259,12 +259,12 @@ class ImagePreprocessor:
"""合并所有网格的OBJ模型并转换为OSGB格式"""
self.logger.info("开始合并OBJ模型")
merger = MergeObj(self.config.output_dir)
center_coords = merger.merge_grid_obj(grid_points)
center_lon, center_lat, bounding_box = merger.merge_grid_obj(grid_points)
# 转换为OSGB格式
self.logger.info("开始转换为OSGB格式")
processor = ObjPostProcessor(self.config.output_dir)
if not processor.convert_to_osgb(center_coords):
if not processor.convert_to_osgb(center_lon, center_lat, bounding_box):
self.logger.error("OSGB转换失败")
def post_process(self, successful_grid_points: Dict[tuple, pd.DataFrame], grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]):

View File

@ -259,12 +259,12 @@ class ImagePreprocessor:
"""合并所有网格的OBJ模型并转换为OSGB格式"""
self.logger.info("开始合并OBJ模型")
merger = MergeObj(self.config.output_dir)
center_coords = merger.merge_grid_obj(grid_points)
center_lon, center_lat, bounding_box = merger.merge_grid_obj(grid_points)
# 转换为OSGB格式
self.logger.info("开始转换为OSGB格式")
processor = ObjPostProcessor(self.config.output_dir)
if not processor.convert_to_osgb(center_coords):
if not processor.convert_to_osgb(center_lon, center_lat, bounding_box):
self.logger.error("OSGB转换失败")
def post_process(self, successful_grid_points: Dict[tuple, pd.DataFrame], grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]):

View File

@ -124,6 +124,12 @@ class MergeObj:
output_model_dir = os.path.join(self.output_dir, "texturing")
os.makedirs(output_model_dir, exist_ok=True)
# 初始化全局边界框坐标
global_min_lon = float('inf')
global_min_lat = float('inf')
global_max_lon = float('-inf')
global_max_lat = float('-inf')
# 第一次遍历获取所有grid的UTM范围
for grid_id, points in grid_points.items():
base_dir = os.path.join(
@ -170,16 +176,28 @@ class MergeObj:
log_file = os.path.join(
base_dir, "..", "odm_orthophoto", "odm_orthophoto_log.txt")
utm_offset = self.read_utm_offset(log_file)
modified_obj = self.modify_obj_coordinates(obj_path, utm_offset)
modified_obj = self.modify_obj_coordinates(
obj_path, utm_offset)
# 读取obj文件内容
vertices, tex_coords, normals, faces, face_materials, _ = self.read_obj(modified_obj)
vertices, tex_coords, normals, faces, face_materials, _ = self.read_obj(
modified_obj)
# 计算当前grid的中心点
grid_center_lon, grid_center_lat = self.get_center_coordinates(vertices)
grid_center_lon, grid_center_lat, grid_bounding_box = self.get_center_coordinates(
vertices)
grid_centers.append((grid_center_lon, grid_center_lat))
self.logger.info(
f"网格 ({grid_id[0]},{grid_id[1]}) 中心点经纬度: ({grid_center_lon}, {grid_center_lat})")
# 更新全局边界框坐标
global_min_lon = min(
global_min_lon, grid_bounding_box['LB_lon'])
global_min_lat = min(
global_min_lat, grid_bounding_box['LB_lat'])
global_max_lon = max(
global_max_lon, grid_bounding_box['RU_lon'])
global_max_lat = max(
global_max_lat, grid_bounding_box['RU_lat'])
# 复制并重命名纹理文件
texture_map = self.copy_and_rename_texture(
@ -211,13 +229,16 @@ class MergeObj:
for face, material in zip(faces, face_materials):
# 调整面的索引
new_face_v = [f + v_offset for f in face[0]]
new_face_vt = [f + vt_offset for f in face[1]] if face[1] else []
new_face_vn = [f + vn_offset for f in face[2]] if face[2] else []
new_face_vt = [
f + vt_offset for f in face[1]] if face[1] else []
new_face_vn = [
f + vn_offset for f in face[2]] if face[2] else []
all_faces.append((new_face_v, new_face_vt, new_face_vn))
# 添加材质前缀
if material:
all_face_materials.append(f"material_{grid_id[0]}_{grid_id[1]}_{material}")
all_face_materials.append(
f"material_{grid_id[0]}_{grid_id[1]}_{material}")
else:
all_face_materials.append(material)
@ -240,23 +261,29 @@ class MergeObj:
all_faces, all_face_materials, "textured_model.mtl")
# 计算整体中心点
center_lon = sum(center[0] for center in grid_centers) / len(grid_centers)
center_lat = sum(center[1] for center in grid_centers) / len(grid_centers)
center_lon = sum(center[0]
for center in grid_centers) / len(grid_centers)
center_lat = sum(center[1]
for center in grid_centers) / len(grid_centers)
self.logger.info(f"模型整体中心点经纬度: ({center_lon}, {center_lat})")
# 计算整个区域的边界框
bounding_box = [global_min_lon, global_min_lat, global_max_lon, global_max_lat]
self.logger.info(
f"模型整体边界框: ({bounding_box[0]}, {bounding_box[1]}) - ({bounding_box[2]}, {bounding_box[3]})")
return center_lon, center_lat
return center_lon, center_lat, bounding_box
except Exception as e:
self.logger.error(f"合并过程中发生错误: {str(e)}", exc_info=True)
raise
def get_center_coordinates(self, vertices: List[List[float]]) -> Tuple[float, float]:
def get_center_coordinates(self, vertices: List[List[float]]) -> Tuple[float, float, Dict[str, float]]:
"""计算顶点的中心点UTM坐标并转换为WGS84经纬度。
注意顶点坐标是相对于整体最小UTM坐标的偏移值需要加回最小UTM坐标
Args:
vertices: 顶点列表每个顶点是[x, y, z]格式x和y是相对于最小UTM坐标的偏移
Returns:
Tuple[float, float]: (longitude, latitude)经纬度坐标
Tuple[float, float, Dict[str, float]]: (longitude, latitude, bounding_box)
"""
# 计算相对坐标的边界框
x_coords = [v[0] for v in vertices]
@ -272,8 +299,16 @@ class MergeObj:
# 转换为WGS84经纬度
lon, lat = self.transformer.transform(center_x_utm, center_y_utm)
# 计算边界框并转换为经纬度
bounding_box = {
'LB_lon': self.transformer.transform(min(x_coords) + self.min_east, min(y_coords) + self.min_north)[0],
'LB_lat': self.transformer.transform(min(x_coords) + self.min_east, min(y_coords) + self.min_north)[1],
'RU_lon': self.transformer.transform(max(x_coords) + self.min_east, max(y_coords) + self.min_north)[0],
'RU_lat': self.transformer.transform(max(x_coords) + self.min_east, max(y_coords) + self.min_north)[1]
}
self.logger.info(f"模型UTM中心点: ({center_x_utm}, {center_y_utm})")
return lon, lat
return lon, lat, bounding_box
def read_mtl(self, mtl_path: str) -> dict:
"""读取MTL文件内容

View File

@ -1,7 +1,7 @@
import os
import logging
import subprocess
from typing import Tuple
from typing import Tuple, Dict
class ObjPostProcessor:
@ -9,7 +9,7 @@ class ObjPostProcessor:
self.output_dir = output_dir
self.logger = logging.getLogger('UAV_Preprocess.ObjPostProcessor')
def create_metadata_xml(self, osgb_dir: str, lon: float, lat: float):
def create_metadata_xml(self, osgb_dir: str, lon: float, lat: float, bounding_box):
"""创建metadata.xml文件包含地理参考信息
Args:
osgb_dir: osgb输出目录
@ -18,15 +18,29 @@ class ObjPostProcessor:
"""
try:
metadata_content = f'''<?xml version="1.0" encoding="utf-8"?>
<ModelMetadata version="1">
<!--Spatial Reference System-->
<SRS>EPSG:4326</SRS>
<!--Origin in Spatial Reference System-->
<SRSOrigin>{lon},{lat},0.000000</SRSOrigin>
<Texture>
<ColorSource>Visible</ColorSource>
</Texture>
</ModelMetadata>'''
<ModelMetadata version="1">
<!-- Spatial Reference System -->
<SRS>EPSG:4326</SRS>
<!-- Center point in Spatial Reference System (in Longitude, Latitude, Height) -->
<SRSOrigin>{lon},{lat},0.000000</SRSOrigin>
<!-- Bounding Box with Two Points -->
<BoundingBox>
<!-- Left-Bottom Corner (Longitude, Latitude) -->
<LB_lon>{bounding_box[0]}</LB_lon>
<LB_lat>{bounding_box[1]}</LB_lat>
<!-- Right-Top Corner (Longitude, Latitude) -->
<RU_lon>{bounding_box[2]}</RU_lon>
<RU_lat>{bounding_box[3]}</RU_lat>
</BoundingBox>
<Texture>
<ColorSource>Visible</ColorSource>
</Texture>
</ModelMetadata>
'''
# metadata.xml 放在根目录
metadata_path = os.path.join(osgb_dir, 'metadata.xml')
@ -39,7 +53,7 @@ class ObjPostProcessor:
self.logger.error(f"创建metadata.xml时发生错误: {str(e)}")
raise
def convert_to_osgb(self, center_coords: Tuple[float, float]):
def convert_to_osgb(self, center_lon, center_lat, bounding_box):
"""将obj转换为osgb并创建metadata.xml
Args:
center_coords: (longitude, latitude)中心点经纬度坐标
@ -76,12 +90,11 @@ class ObjPostProcessor:
if result.returncode != 0:
raise Exception(f"osgb格式转换失败: {result.stderr}")
self.logger.info(f"转换完成: {output_osgb}")
# 创建metadata.xml
lon, lat = center_coords
self.create_metadata_xml(osgb_dir, lon, lat)
self.create_metadata_xml(osgb_dir, center_lon, center_lat, bounding_box)
self.logger.info(f"转换完成: {output_osgb}")
return True
except Exception as e: