修改metadata.xml,添加boundingbox
This commit is contained in:
parent
9b151d0768
commit
3df39f76d2
2
main.py
2
main.py
@ -1,6 +1,6 @@
|
|||||||
import argparse
|
import argparse
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from odm_preprocess import PreprocessConfig, ImagePreprocessor
|
from odm_preprocess_fast import PreprocessConfig, ImagePreprocessor
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = argparse.ArgumentParser(description='ODM预处理工具')
|
parser = argparse.ArgumentParser(description='ODM预处理工具')
|
||||||
|
@ -259,12 +259,12 @@ class ImagePreprocessor:
|
|||||||
"""合并所有网格的OBJ模型并转换为OSGB格式"""
|
"""合并所有网格的OBJ模型并转换为OSGB格式"""
|
||||||
self.logger.info("开始合并OBJ模型")
|
self.logger.info("开始合并OBJ模型")
|
||||||
merger = MergeObj(self.config.output_dir)
|
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格式
|
# 转换为OSGB格式
|
||||||
self.logger.info("开始转换为OSGB格式")
|
self.logger.info("开始转换为OSGB格式")
|
||||||
processor = ObjPostProcessor(self.config.output_dir)
|
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转换失败")
|
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]):
|
def post_process(self, successful_grid_points: Dict[tuple, pd.DataFrame], grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]):
|
||||||
|
@ -259,12 +259,12 @@ class ImagePreprocessor:
|
|||||||
"""合并所有网格的OBJ模型并转换为OSGB格式"""
|
"""合并所有网格的OBJ模型并转换为OSGB格式"""
|
||||||
self.logger.info("开始合并OBJ模型")
|
self.logger.info("开始合并OBJ模型")
|
||||||
merger = MergeObj(self.config.output_dir)
|
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格式
|
# 转换为OSGB格式
|
||||||
self.logger.info("开始转换为OSGB格式")
|
self.logger.info("开始转换为OSGB格式")
|
||||||
processor = ObjPostProcessor(self.config.output_dir)
|
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转换失败")
|
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]):
|
def post_process(self, successful_grid_points: Dict[tuple, pd.DataFrame], grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]):
|
||||||
|
@ -124,6 +124,12 @@ class MergeObj:
|
|||||||
output_model_dir = os.path.join(self.output_dir, "texturing")
|
output_model_dir = os.path.join(self.output_dir, "texturing")
|
||||||
os.makedirs(output_model_dir, exist_ok=True)
|
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范围
|
# 第一次遍历:获取所有grid的UTM范围
|
||||||
for grid_id, points in grid_points.items():
|
for grid_id, points in grid_points.items():
|
||||||
base_dir = os.path.join(
|
base_dir = os.path.join(
|
||||||
@ -170,16 +176,28 @@ class MergeObj:
|
|||||||
log_file = os.path.join(
|
log_file = os.path.join(
|
||||||
base_dir, "..", "odm_orthophoto", "odm_orthophoto_log.txt")
|
base_dir, "..", "odm_orthophoto", "odm_orthophoto_log.txt")
|
||||||
utm_offset = self.read_utm_offset(log_file)
|
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文件内容
|
# 读取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的中心点
|
||||||
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))
|
grid_centers.append((grid_center_lon, grid_center_lat))
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
f"网格 ({grid_id[0]},{grid_id[1]}) 中心点经纬度: ({grid_center_lon}, {grid_center_lat})")
|
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(
|
texture_map = self.copy_and_rename_texture(
|
||||||
@ -211,13 +229,16 @@ class MergeObj:
|
|||||||
for face, material in zip(faces, face_materials):
|
for face, material in zip(faces, face_materials):
|
||||||
# 调整面的索引
|
# 调整面的索引
|
||||||
new_face_v = [f + v_offset for f in face[0]]
|
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_vt = [
|
||||||
new_face_vn = [f + vn_offset for f in face[2]] if face[2] else []
|
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))
|
all_faces.append((new_face_v, new_face_vt, new_face_vn))
|
||||||
|
|
||||||
# 添加材质前缀
|
# 添加材质前缀
|
||||||
if material:
|
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:
|
else:
|
||||||
all_face_materials.append(material)
|
all_face_materials.append(material)
|
||||||
|
|
||||||
@ -240,23 +261,29 @@ class MergeObj:
|
|||||||
all_faces, all_face_materials, "textured_model.mtl")
|
all_faces, all_face_materials, "textured_model.mtl")
|
||||||
|
|
||||||
# 计算整体中心点
|
# 计算整体中心点
|
||||||
center_lon = sum(center[0] for center in grid_centers) / len(grid_centers)
|
center_lon = sum(center[0]
|
||||||
center_lat = sum(center[1] for center in grid_centers) / len(grid_centers)
|
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})")
|
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:
|
except Exception as e:
|
||||||
self.logger.error(f"合并过程中发生错误: {str(e)}", exc_info=True)
|
self.logger.error(f"合并过程中发生错误: {str(e)}", exc_info=True)
|
||||||
raise
|
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坐标,并转换为WGS84经纬度。
|
||||||
注意:顶点坐标是相对于整体最小UTM坐标的偏移值,需要加回最小UTM坐标。
|
注意:顶点坐标是相对于整体最小UTM坐标的偏移值,需要加回最小UTM坐标。
|
||||||
Args:
|
Args:
|
||||||
vertices: 顶点列表,每个顶点是[x, y, z]格式,x和y是相对于最小UTM坐标的偏移
|
vertices: 顶点列表,每个顶点是[x, y, z]格式,x和y是相对于最小UTM坐标的偏移
|
||||||
Returns:
|
Returns:
|
||||||
Tuple[float, float]: (longitude, latitude)经纬度坐标
|
Tuple[float, float, Dict[str, float]]: (longitude, latitude, bounding_box)
|
||||||
"""
|
"""
|
||||||
# 计算相对坐标的边界框
|
# 计算相对坐标的边界框
|
||||||
x_coords = [v[0] for v in vertices]
|
x_coords = [v[0] for v in vertices]
|
||||||
@ -272,8 +299,16 @@ class MergeObj:
|
|||||||
|
|
||||||
# 转换为WGS84经纬度
|
# 转换为WGS84经纬度
|
||||||
lon, lat = self.transformer.transform(center_x_utm, center_y_utm)
|
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})")
|
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:
|
def read_mtl(self, mtl_path: str) -> dict:
|
||||||
"""读取MTL文件内容
|
"""读取MTL文件内容
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
from typing import Tuple
|
from typing import Tuple, Dict
|
||||||
|
|
||||||
|
|
||||||
class ObjPostProcessor:
|
class ObjPostProcessor:
|
||||||
@ -9,7 +9,7 @@ class ObjPostProcessor:
|
|||||||
self.output_dir = output_dir
|
self.output_dir = output_dir
|
||||||
self.logger = logging.getLogger('UAV_Preprocess.ObjPostProcessor')
|
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文件,包含地理参考信息
|
"""创建metadata.xml文件,包含地理参考信息
|
||||||
Args:
|
Args:
|
||||||
osgb_dir: osgb输出目录
|
osgb_dir: osgb输出目录
|
||||||
@ -18,15 +18,29 @@ class ObjPostProcessor:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
metadata_content = f'''<?xml version="1.0" encoding="utf-8"?>
|
metadata_content = f'''<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ModelMetadata version="1">
|
<ModelMetadata version="1">
|
||||||
<!--Spatial Reference System-->
|
<!-- Spatial Reference System -->
|
||||||
<SRS>EPSG:4326</SRS>
|
<SRS>EPSG:4326</SRS>
|
||||||
<!--Origin in Spatial Reference System-->
|
|
||||||
<SRSOrigin>{lon},{lat},0.000000</SRSOrigin>
|
<!-- Center point in Spatial Reference System (in Longitude, Latitude, Height) -->
|
||||||
<Texture>
|
<SRSOrigin>{lon},{lat},0.000000</SRSOrigin>
|
||||||
<ColorSource>Visible</ColorSource>
|
|
||||||
</Texture>
|
<!-- Bounding Box with Two Points -->
|
||||||
</ModelMetadata>'''
|
<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.xml 放在根目录
|
||||||
metadata_path = os.path.join(osgb_dir, '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)}")
|
self.logger.error(f"创建metadata.xml时发生错误: {str(e)}")
|
||||||
raise
|
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
|
"""将obj转换为osgb,并创建metadata.xml
|
||||||
Args:
|
Args:
|
||||||
center_coords: (longitude, latitude)中心点经纬度坐标
|
center_coords: (longitude, latitude)中心点经纬度坐标
|
||||||
@ -76,12 +90,11 @@ class ObjPostProcessor:
|
|||||||
|
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
raise Exception(f"osgb格式转换失败: {result.stderr}")
|
raise Exception(f"osgb格式转换失败: {result.stderr}")
|
||||||
|
self.logger.info(f"转换完成: {output_osgb}")
|
||||||
|
|
||||||
# 创建metadata.xml
|
# 创建metadata.xml
|
||||||
lon, lat = center_coords
|
self.create_metadata_xml(osgb_dir, center_lon, center_lat, bounding_box)
|
||||||
self.create_metadata_xml(osgb_dir, lon, lat)
|
|
||||||
|
|
||||||
self.logger.info(f"转换完成: {output_osgb}")
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
Loading…
Reference in New Issue
Block a user