From 3df39f76d2b3f23ec323f70e548e39df2db1c3c8 Mon Sep 17 00:00:00 2001 From: weixin_46229132 Date: Fri, 14 Feb 2025 17:31:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9metadata.xml=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0boundingbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 2 +- odm_preprocess.py | 4 +-- odm_preprocess_fast.py | 4 +-- post_pro/merge_obj.py | 63 +++++++++++++++++++++++++++++++--------- post_pro/obj_post_pro.py | 43 +++++++++++++++++---------- 5 files changed, 82 insertions(+), 34 deletions(-) diff --git a/main.py b/main.py index a51cd62..526a90f 100644 --- a/main.py +++ b/main.py @@ -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预处理工具') diff --git a/odm_preprocess.py b/odm_preprocess.py index 7aebb6c..69339bf 100644 --- a/odm_preprocess.py +++ b/odm_preprocess.py @@ -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]): diff --git a/odm_preprocess_fast.py b/odm_preprocess_fast.py index 0d09d76..32237db 100644 --- a/odm_preprocess_fast.py +++ b/odm_preprocess_fast.py @@ -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]): diff --git a/post_pro/merge_obj.py b/post_pro/merge_obj.py index df87ca5..f5408ef 100644 --- a/post_pro/merge_obj.py +++ b/post_pro/merge_obj.py @@ -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})") - - return 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, 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文件内容 diff --git a/post_pro/obj_post_pro.py b/post_pro/obj_post_pro.py index b5a95e6..af3d49c 100644 --- a/post_pro/obj_post_pro.py +++ b/post_pro/obj_post_pro.py @@ -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''' - - - EPSG:4326 - - {lon},{lat},0.000000 - - Visible - -''' + + + EPSG:4326 + + + {lon},{lat},0.000000 + + + + + {bounding_box[0]} + {bounding_box[1]} + + + {bounding_box[2]} + {bounding_box[3]} + + + + Visible + + + ''' # 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: