合并ply和obj代码
This commit is contained in:
parent
28126bc3be
commit
f08584d13a
@ -18,6 +18,8 @@ from utils.logger import setup_logger
|
|||||||
from utils.visualizer import FilterVisualizer
|
from utils.visualizer import FilterVisualizer
|
||||||
from post_pro.merge_tif import MergeTif
|
from post_pro.merge_tif import MergeTif
|
||||||
from tools.test_docker_run import run_docker_command
|
from tools.test_docker_run import run_docker_command
|
||||||
|
from post_pro.merge_obj import MergeObj
|
||||||
|
from post_pro.merge_ply import MergePly
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -228,63 +230,22 @@ class ImagePreprocessor:
|
|||||||
self.logger.info(f"网格 {grid_idx + 1} 包含 {len(points)} 张图像")
|
self.logger.info(f"网格 {grid_idx + 1} 包含 {len(points)} 张图像")
|
||||||
|
|
||||||
def merge_tif(self, grid_points: Dict[int, pd.DataFrame]):
|
def merge_tif(self, grid_points: Dict[int, pd.DataFrame]):
|
||||||
"""合并所有网格的TIF影像"""
|
"""合并所有网格的影像产品"""
|
||||||
self.logger.info("开始合并TIF影像")
|
self.logger.info("开始合并所有影像产品")
|
||||||
|
merger = MergeTif(self.config.output_dir)
|
||||||
|
merger.merge_all_tifs(grid_points)
|
||||||
|
|
||||||
# 检查是否有多个网格需要合并
|
def merge_obj(self, grid_points: Dict[int, pd.DataFrame]):
|
||||||
if len(grid_points) < 2:
|
"""合并所有网格的OBJ模型"""
|
||||||
self.logger.info("只有一个网格,无需合并TIF影像")
|
self.logger.info("开始合并OBJ模型")
|
||||||
return
|
merger = MergeObj(self.config.output_dir)
|
||||||
|
merger.merge_grid_obj(grid_points)
|
||||||
|
|
||||||
input_tif1, input_tif2 = None, None
|
def merge_ply(self, grid_points: Dict[int, pd.DataFrame]):
|
||||||
merge_count = 0
|
"""合并所有网格的PLY点云"""
|
||||||
|
self.logger.info("开始合并PLY点云")
|
||||||
try:
|
merger = MergePly(self.config.output_dir)
|
||||||
for grid_idx, points in grid_points.items():
|
merger.merge_grid_ply(grid_points)
|
||||||
grid_tif = os.path.join(
|
|
||||||
self.config.output_dir,
|
|
||||||
f"grid_{grid_idx + 1}",
|
|
||||||
"project",
|
|
||||||
"odm_orthophoto",
|
|
||||||
"odm_orthophoto.original.tif"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 检查TIF文件是否存在
|
|
||||||
if not os.path.exists(grid_tif):
|
|
||||||
self.logger.error(
|
|
||||||
f"网格 {grid_idx + 1} 的TIF文件不存在: {grid_tif}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
if input_tif1 is None:
|
|
||||||
input_tif1 = grid_tif
|
|
||||||
self.logger.info(f"设置第一个输入TIF: {input_tif1}")
|
|
||||||
else:
|
|
||||||
input_tif2 = grid_tif
|
|
||||||
output_tif = os.path.join(
|
|
||||||
self.config.output_dir, "merged_orthophoto.tif")
|
|
||||||
|
|
||||||
self.logger.info(
|
|
||||||
f"开始合并第 {merge_count + 1} 次:\n"
|
|
||||||
f"输入1: {input_tif1}\n"
|
|
||||||
f"输入2: {input_tif2}\n"
|
|
||||||
f"输出: {output_tif}"
|
|
||||||
)
|
|
||||||
|
|
||||||
merge_tif = MergeTif(input_tif1, input_tif2, output_tif)
|
|
||||||
merge_tif.merge()
|
|
||||||
merge_count += 1
|
|
||||||
|
|
||||||
input_tif1 = output_tif
|
|
||||||
input_tif2 = None
|
|
||||||
|
|
||||||
self.logger.info(
|
|
||||||
f"TIF影像合并完成,共执行 {merge_count} 次合并,"
|
|
||||||
f"最终输出文件: {input_tif1}"
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(f"TIF影像合并过程中发生错误: {str(e)}", exc_info=True)
|
|
||||||
raise
|
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
"""执行完整的预处理流程"""
|
"""执行完整的预处理流程"""
|
||||||
@ -297,19 +258,10 @@ class ImagePreprocessor:
|
|||||||
self.copy_images(grid_points)
|
self.copy_images(grid_points)
|
||||||
self.logger.info("预处理任务完成")
|
self.logger.info("预处理任务完成")
|
||||||
|
|
||||||
# for grid_idx in grid_points.keys():
|
|
||||||
# grid_dir = os.path.abspath(os.path.join(
|
|
||||||
# self.config.output_dir, f'grid_{grid_idx + 1}'
|
|
||||||
# ))
|
|
||||||
# grid_dir = grid_dir[0].lower() + grid_dir[1:].replace("\\", "/")
|
|
||||||
# command = f"docker run -ti --rm -v {grid_dir}:/datasets opendronemap/odm --project-path /datasets project --max-concurrency 10 --force-gps --feature-quality lowest --orthophoto-resolution 10 --fast-orthophoto --skip-3dmodel --rerun-all"
|
|
||||||
# print(command)
|
|
||||||
# stdout, stderr = run_docker_command(command)
|
|
||||||
# print(stdout)
|
|
||||||
# print(stderr)
|
|
||||||
|
|
||||||
self.odm_monitor.process_all_grids(grid_points)
|
self.odm_monitor.process_all_grids(grid_points)
|
||||||
self.merge_tif(grid_points)
|
self.merge_tif(grid_points)
|
||||||
|
self.merge_obj(grid_points)
|
||||||
|
self.merge_ply(grid_points)
|
||||||
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
|
||||||
@ -318,8 +270,8 @@ class ImagePreprocessor:
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# 创建配置
|
# 创建配置
|
||||||
config = PreprocessConfig(
|
config = PreprocessConfig(
|
||||||
image_dir=r"G:\error_data\20241104140457\code\images",
|
image_dir=r"E:\datasets\UAV\1009\project\images",
|
||||||
output_dir=r"G:\ODM_output\20241104140457",
|
output_dir=r"G:\ODM_output\1009",
|
||||||
|
|
||||||
cluster_eps=0.01,
|
cluster_eps=0.01,
|
||||||
cluster_min_samples=5,
|
cluster_min_samples=5,
|
||||||
@ -335,11 +287,11 @@ if __name__ == "__main__":
|
|||||||
filter_dense_distance_threshold=10,
|
filter_dense_distance_threshold=10,
|
||||||
filter_time_threshold=timedelta(minutes=5),
|
filter_time_threshold=timedelta(minutes=5),
|
||||||
|
|
||||||
grid_size=1000,
|
grid_size=300,
|
||||||
grid_overlap=0.03,
|
grid_overlap=0.03,
|
||||||
|
|
||||||
|
|
||||||
mode="快拼模式",
|
mode="重建模式",
|
||||||
)
|
)
|
||||||
|
|
||||||
# 创建处理器并执行
|
# 创建处理器并执行
|
||||||
|
109
post_pro/merge_obj.py
Normal file
109
post_pro/merge_obj.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import numpy as np
|
||||||
|
from typing import Dict
|
||||||
|
import pandas as pd
|
||||||
|
import open3d as o3d
|
||||||
|
|
||||||
|
|
||||||
|
class MergeObj:
|
||||||
|
def __init__(self, output_dir: str):
|
||||||
|
self.output_dir = output_dir
|
||||||
|
self.logger = logging.getLogger('UAV_Preprocess.MergeObj')
|
||||||
|
|
||||||
|
def merge_two_objs(self, obj1_path: str, obj2_path: str, output_path: str):
|
||||||
|
"""使用Open3D合并两个OBJ文件"""
|
||||||
|
try:
|
||||||
|
self.logger.info("开始合并OBJ模型")
|
||||||
|
self.logger.info(f"输入模型1: {obj1_path}")
|
||||||
|
self.logger.info(f"输入模型2: {obj2_path}")
|
||||||
|
self.logger.info(f"输出模型: {output_path}")
|
||||||
|
|
||||||
|
# 检查输入文件是否存在
|
||||||
|
if not os.path.exists(obj1_path) or not os.path.exists(obj2_path):
|
||||||
|
raise FileNotFoundError("输入模型文件不存在")
|
||||||
|
|
||||||
|
# 读取OBJ文件
|
||||||
|
mesh1 = o3d.io.read_triangle_mesh(obj1_path)
|
||||||
|
mesh2 = o3d.io.read_triangle_mesh(obj2_path)
|
||||||
|
|
||||||
|
if mesh1.is_empty() or mesh2.is_empty():
|
||||||
|
raise ValueError("无法读取OBJ文件或文件为空")
|
||||||
|
|
||||||
|
# # 计算并对齐中心点
|
||||||
|
# center1 = mesh1.get_center()
|
||||||
|
# center2 = mesh2.get_center()
|
||||||
|
# translation_vector = center2 - center1
|
||||||
|
# mesh2.translate(translation_vector)
|
||||||
|
|
||||||
|
# 不对齐,直接合并网格
|
||||||
|
combined_mesh = mesh1 + mesh2
|
||||||
|
|
||||||
|
# 优化合并后的网格
|
||||||
|
combined_mesh.remove_duplicated_vertices()
|
||||||
|
combined_mesh.remove_duplicated_triangles()
|
||||||
|
combined_mesh.compute_vertex_normals()
|
||||||
|
|
||||||
|
# 保存合并后的模型
|
||||||
|
if not o3d.io.write_triangle_mesh(output_path, combined_mesh):
|
||||||
|
raise RuntimeError("保存合并后的模型失败")
|
||||||
|
|
||||||
|
self.logger.info(f"模型合并成功,已保存至: {output_path}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"合并OBJ模型时发生错误: {str(e)}", exc_info=True)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def merge_grid_obj(self, grid_points: Dict[int, pd.DataFrame]):
|
||||||
|
"""合并所有网格的OBJ模型"""
|
||||||
|
self.logger.info("开始合并所有网格的OBJ模型")
|
||||||
|
|
||||||
|
if len(grid_points) < 2:
|
||||||
|
self.logger.info("只有一个网格,无需合并")
|
||||||
|
return
|
||||||
|
|
||||||
|
input_obj1, input_obj2 = None, None
|
||||||
|
merge_count = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
for grid_idx, points in grid_points.items():
|
||||||
|
grid_obj = os.path.join(
|
||||||
|
self.output_dir,
|
||||||
|
f"grid_{grid_idx + 1}",
|
||||||
|
"project",
|
||||||
|
"odm_texturing",
|
||||||
|
"odm_textured_model_geo.obj"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not os.path.exists(grid_obj):
|
||||||
|
self.logger.warning(f"网格 {grid_idx + 1} 的OBJ文件不存在: {grid_obj}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if input_obj1 is None:
|
||||||
|
input_obj1 = grid_obj
|
||||||
|
self.logger.info(f"设置第一个输入OBJ: {input_obj1}")
|
||||||
|
else:
|
||||||
|
input_obj2 = grid_obj
|
||||||
|
output_obj = os.path.join(self.output_dir, "merged_model.obj")
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"开始合并第 {merge_count + 1} 次:\n"
|
||||||
|
f"输入1: {input_obj1}\n"
|
||||||
|
f"输入2: {input_obj2}\n"
|
||||||
|
f"输出: {output_obj}"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.merge_two_objs(input_obj1, input_obj2, output_obj)
|
||||||
|
merge_count += 1
|
||||||
|
|
||||||
|
input_obj1 = output_obj
|
||||||
|
input_obj2 = None
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"OBJ模型合并完成,共执行 {merge_count} 次合并,"
|
||||||
|
f"最终输出文件: {input_obj1}"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"OBJ模型合并过程中发生错误: {str(e)}", exc_info=True)
|
||||||
|
raise
|
108
post_pro/merge_ply.py
Normal file
108
post_pro/merge_ply.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import numpy as np
|
||||||
|
from typing import Dict
|
||||||
|
import pandas as pd
|
||||||
|
import open3d as o3d
|
||||||
|
|
||||||
|
|
||||||
|
class MergePly:
|
||||||
|
def __init__(self, output_dir: str):
|
||||||
|
self.output_dir = output_dir
|
||||||
|
self.logger = logging.getLogger('UAV_Preprocess.MergePly')
|
||||||
|
|
||||||
|
def merge_two_plys(self, ply1_path: str, ply2_path: str, output_path: str):
|
||||||
|
"""合并两个PLY文件"""
|
||||||
|
try:
|
||||||
|
self.logger.info("开始合并PLY点云")
|
||||||
|
self.logger.info(f"输入点云1: {ply1_path}")
|
||||||
|
self.logger.info(f"输入点云2: {ply2_path}")
|
||||||
|
self.logger.info(f"输出点云: {output_path}")
|
||||||
|
|
||||||
|
# 检查输入文件是否存在
|
||||||
|
if not os.path.exists(ply1_path) or not os.path.exists(ply2_path):
|
||||||
|
raise FileNotFoundError("输入点云文件不存在")
|
||||||
|
|
||||||
|
# 读取点云
|
||||||
|
pcd1 = o3d.io.read_point_cloud(ply1_path)
|
||||||
|
pcd2 = o3d.io.read_point_cloud(ply2_path)
|
||||||
|
|
||||||
|
if pcd1 is None or pcd2 is None:
|
||||||
|
raise ValueError("无法读取点云文件")
|
||||||
|
|
||||||
|
# 获取点云中心
|
||||||
|
center1 = pcd1.get_center()
|
||||||
|
center2 = pcd2.get_center()
|
||||||
|
|
||||||
|
# 计算平移向量
|
||||||
|
translation_vector = center2 - center1
|
||||||
|
|
||||||
|
# 对齐点云
|
||||||
|
pcd2.translate(translation_vector)
|
||||||
|
|
||||||
|
# 合并点云
|
||||||
|
combined_pcd = pcd1 + pcd2
|
||||||
|
|
||||||
|
# 保存合并后的点云
|
||||||
|
if not o3d.io.write_point_cloud(output_path, combined_pcd):
|
||||||
|
raise RuntimeError("保存合并后的点云失败")
|
||||||
|
|
||||||
|
self.logger.info(f"点云合并成功,已保存至: {output_path}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"合并PLY点云时发生错误: {str(e)}", exc_info=True)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def merge_grid_ply(self, grid_points: Dict[int, pd.DataFrame]):
|
||||||
|
"""合并所有网格的PLY点云"""
|
||||||
|
self.logger.info("开始合并所有网格的PLY点云")
|
||||||
|
|
||||||
|
if len(grid_points) < 2:
|
||||||
|
self.logger.info("只有一个网格,无需合并")
|
||||||
|
return
|
||||||
|
|
||||||
|
input_ply1, input_ply2 = None, None
|
||||||
|
merge_count = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
for grid_idx, points in grid_points.items():
|
||||||
|
grid_ply = os.path.join(
|
||||||
|
self.output_dir,
|
||||||
|
f"grid_{grid_idx + 1}",
|
||||||
|
"project",
|
||||||
|
"odm_georeferencing",
|
||||||
|
"odm_georeferenced_model.ply"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not os.path.exists(grid_ply):
|
||||||
|
self.logger.warning(f"网格 {grid_idx + 1} 的PLY文件不存在: {grid_ply}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if input_ply1 is None:
|
||||||
|
input_ply1 = grid_ply
|
||||||
|
self.logger.info(f"设置第一个输入PLY: {input_ply1}")
|
||||||
|
else:
|
||||||
|
input_ply2 = grid_ply
|
||||||
|
output_ply = os.path.join(self.output_dir, "merged_pointcloud.ply")
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"开始合并第 {merge_count + 1} 次:\n"
|
||||||
|
f"输入1: {input_ply1}\n"
|
||||||
|
f"输入2: {input_ply2}\n"
|
||||||
|
f"输出: {output_ply}"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.merge_two_plys(input_ply1, input_ply2, output_ply)
|
||||||
|
merge_count += 1
|
||||||
|
|
||||||
|
input_ply1 = output_ply
|
||||||
|
input_ply2 = None
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"PLY点云合并完成,共执行 {merge_count} 次合并,"
|
||||||
|
f"最终输出文件: {input_ply1}"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"PLY点云合并过程中发生错误: {str(e)}", exc_info=True)
|
||||||
|
raise
|
@ -1,34 +1,33 @@
|
|||||||
from osgeo import gdal
|
from osgeo import gdal
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from typing import Dict
|
||||||
|
import pandas as pd
|
||||||
import sys
|
import sys
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
class MergeTif:
|
class MergeTif:
|
||||||
def __init__(self, input_tif1, input_tif2, output_tif):
|
def __init__(self, output_dir: str):
|
||||||
self.input_tif1 = input_tif1
|
self.output_dir = output_dir
|
||||||
self.input_tif2 = input_tif2
|
|
||||||
self.output_tif = output_tif
|
|
||||||
self.logger = logging.getLogger('UAV_Preprocess.MergeTif')
|
self.logger = logging.getLogger('UAV_Preprocess.MergeTif')
|
||||||
|
|
||||||
def merge(self):
|
def merge_two_tifs(self, input_tif1: str, input_tif2: str, output_tif: str):
|
||||||
"""合并两张TIF影像"""
|
"""合并两张TIF影像"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("开始合并TIF影像")
|
self.logger.info("开始合并TIF影像")
|
||||||
self.logger.info(f"输入影像1: {self.input_tif1}")
|
self.logger.info(f"输入影像1: {input_tif1}")
|
||||||
self.logger.info(f"输入影像2: {self.input_tif2}")
|
self.logger.info(f"输入影像2: {input_tif2}")
|
||||||
self.logger.info(f"输出影像: {self.output_tif}")
|
self.logger.info(f"输出影像: {output_tif}")
|
||||||
|
|
||||||
# 检查输入文件是否存在
|
# 检查输入文件是否存在
|
||||||
if not os.path.exists(self.input_tif1) or not os.path.exists(self.input_tif2):
|
if not os.path.exists(input_tif1) or not os.path.exists(input_tif2):
|
||||||
error_msg = "输入影像文件不存在"
|
error_msg = "输入影像文件不存在"
|
||||||
self.logger.error(error_msg)
|
self.logger.error(error_msg)
|
||||||
raise FileNotFoundError(error_msg)
|
raise FileNotFoundError(error_msg)
|
||||||
|
|
||||||
# 打开影像,检查投影是否一致
|
# 打开影像,检查投影是否一致
|
||||||
datasets = [gdal.Open(tif)
|
datasets = [gdal.Open(tif) for tif in [input_tif1, input_tif2]]
|
||||||
for tif in [self.input_tif1, self.input_tif2]]
|
|
||||||
if None in datasets:
|
if None in datasets:
|
||||||
error_msg = "无法打开输入影像文件"
|
error_msg = "无法打开输入影像文件"
|
||||||
self.logger.error(error_msg)
|
self.logger.error(error_msg)
|
||||||
@ -47,20 +46,14 @@ class MergeTif:
|
|||||||
# 创建 GDAL Warp 选项
|
# 创建 GDAL Warp 选项
|
||||||
warp_options = gdal.WarpOptions(
|
warp_options = gdal.WarpOptions(
|
||||||
format="GTiff",
|
format="GTiff",
|
||||||
resampleAlg="average", # 设置重采样方法为平均值
|
resampleAlg="average",
|
||||||
srcNodata=0, # 输入影像中的无效值
|
srcNodata=0,
|
||||||
dstNodata=0, # 输出影像中的无效值
|
dstNodata=0,
|
||||||
multithread=True # 启用多线程优化
|
multithread=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self.logger.info("开始执行影像拼接...")
|
self.logger.info("开始执行影像拼接...")
|
||||||
|
result = gdal.Warp(output_tif, [input_tif1, input_tif2], options=warp_options)
|
||||||
# 使用 GDAL 的 Warp 方法进行拼接
|
|
||||||
result = gdal.Warp(
|
|
||||||
self.output_tif,
|
|
||||||
[self.input_tif1, self.input_tif2], # 输入多张影像
|
|
||||||
options=warp_options
|
|
||||||
)
|
|
||||||
|
|
||||||
if result is None:
|
if result is None:
|
||||||
error_msg = "影像拼接失败"
|
error_msg = "影像拼接失败"
|
||||||
@ -68,19 +61,109 @@ class MergeTif:
|
|||||||
raise RuntimeError(error_msg)
|
raise RuntimeError(error_msg)
|
||||||
|
|
||||||
# 获取输出影像的基本信息
|
# 获取输出影像的基本信息
|
||||||
output_dataset = gdal.Open(self.output_tif)
|
output_dataset = gdal.Open(output_tif)
|
||||||
if output_dataset:
|
if output_dataset:
|
||||||
width = output_dataset.RasterXSize
|
width = output_dataset.RasterXSize
|
||||||
height = output_dataset.RasterYSize
|
height = output_dataset.RasterYSize
|
||||||
bands = output_dataset.RasterCount
|
bands = output_dataset.RasterCount
|
||||||
self.logger.info(f"拼接完成,输出影像大小: {width}x{height},波段数: {bands}")
|
self.logger.info(f"拼接完成,输出影像大小: {width}x{height},波段数: {bands}")
|
||||||
|
|
||||||
self.logger.info(f"影像拼接成功,输出文件保存至: {self.output_tif}")
|
self.logger.info(f"影像拼接成功,输出文件保存至: {output_tif}")
|
||||||
|
|
||||||
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 merge_grid_tif(self, grid_points: Dict[int, pd.DataFrame], product_info: dict):
|
||||||
|
"""合并指定产品的所有网格"""
|
||||||
|
product_name = product_info['name']
|
||||||
|
product_path = product_info['path']
|
||||||
|
filename = product_info['filename']
|
||||||
|
|
||||||
|
self.logger.info(f"开始合并{product_name}")
|
||||||
|
|
||||||
|
if len(grid_points) < 2:
|
||||||
|
self.logger.info("只有一个网格,无需合并")
|
||||||
|
return
|
||||||
|
|
||||||
|
input_tif1, input_tif2 = None, None
|
||||||
|
merge_count = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
for grid_idx, points in grid_points.items():
|
||||||
|
grid_tif = os.path.join(
|
||||||
|
self.output_dir,
|
||||||
|
f"grid_{grid_idx + 1}",
|
||||||
|
"project",
|
||||||
|
product_path,
|
||||||
|
filename
|
||||||
|
)
|
||||||
|
|
||||||
|
if not os.path.exists(grid_tif):
|
||||||
|
self.logger.warning(f"网格 {grid_idx + 1} 的{product_name}不存在: {grid_tif}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if input_tif1 is None:
|
||||||
|
input_tif1 = grid_tif
|
||||||
|
self.logger.info(f"设置第一个输入{product_name}: {input_tif1}")
|
||||||
|
else:
|
||||||
|
input_tif2 = grid_tif
|
||||||
|
output_tif = os.path.join(self.output_dir, f"merged_{product_info['output']}")
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"开始合并{product_name}第 {merge_count + 1} 次:\n"
|
||||||
|
f"输入1: {input_tif1}\n"
|
||||||
|
f"输入2: {input_tif2}\n"
|
||||||
|
f"输出: {output_tif}"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.merge_two_tifs(input_tif1, input_tif2, output_tif)
|
||||||
|
merge_count += 1
|
||||||
|
|
||||||
|
input_tif1 = output_tif
|
||||||
|
input_tif2 = None
|
||||||
|
|
||||||
|
self.logger.info(
|
||||||
|
f"{product_name}合并完成,共执行 {merge_count} 次合并,"
|
||||||
|
f"最终输出文件: {input_tif1}"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"{product_name}合并过程中发生错误: {str(e)}", exc_info=True)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def merge_all_tifs(self, grid_points: Dict[int, pd.DataFrame]):
|
||||||
|
"""合并所有产品(正射影像、DSM和DTM)"""
|
||||||
|
try:
|
||||||
|
products = [
|
||||||
|
{
|
||||||
|
'name': '正射影像',
|
||||||
|
'path': 'odm_orthophoto',
|
||||||
|
'filename': 'odm_orthophoto.original.tif',
|
||||||
|
'output': 'orthophoto.tif'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'DSM',
|
||||||
|
'path': 'odm_dem',
|
||||||
|
'filename': 'dsm.original.tif',
|
||||||
|
'output': 'dsm.tif'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'DTM',
|
||||||
|
'path': 'odm_dem',
|
||||||
|
'filename': 'dtm.original.tif',
|
||||||
|
'output': 'dtm.tif'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
for product in products:
|
||||||
|
self.merge_grid_product(grid_points, product)
|
||||||
|
|
||||||
|
self.logger.info("所有产品合并完成")
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"产品合并过程中发生错误: {str(e)}", exc_info=True)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from utils.logger import setup_logger
|
from utils.logger import setup_logger
|
||||||
@ -95,5 +178,5 @@ if __name__ == "__main__":
|
|||||||
setup_logger(output_dir)
|
setup_logger(output_dir)
|
||||||
|
|
||||||
# 执行拼接
|
# 执行拼接
|
||||||
merge_tif = MergeTif(input_tif1, input_tif2, output_tif)
|
merge_tif = MergeTif(output_dir)
|
||||||
merge_tif.merge()
|
merge_tif.merge_two_tifs(input_tif1, input_tif2, output_tif)
|
||||||
|
@ -6,3 +6,4 @@ piexif
|
|||||||
geopy
|
geopy
|
||||||
psutil
|
psutil
|
||||||
docker>=6.1.3
|
docker>=6.1.3
|
||||||
|
open3d
|
||||||
|
34
tools/merge_obj.py
Normal file
34
tools/merge_obj.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import open3d as o3d
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# 读取 .obj 文件
|
||||||
|
def load_obj(file_path):
|
||||||
|
mesh = o3d.io.read_triangle_mesh(file_path)
|
||||||
|
if not mesh.is_empty():
|
||||||
|
return mesh
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Failed to load {file_path}")
|
||||||
|
|
||||||
|
# 合并两个网格
|
||||||
|
def merge_meshes(mesh1, mesh2):
|
||||||
|
# 直接合并网格
|
||||||
|
combined_mesh = mesh1 + mesh2
|
||||||
|
return combined_mesh
|
||||||
|
|
||||||
|
# 保存合并后的网格
|
||||||
|
def save_merged_mesh(mesh, output_path):
|
||||||
|
o3d.io.write_triangle_mesh(output_path, mesh)
|
||||||
|
print(f"Saved merged mesh to {output_path}")
|
||||||
|
|
||||||
|
# 示例用法
|
||||||
|
mesh1 = load_obj("model1.obj")
|
||||||
|
mesh2 = load_obj("model2.obj")
|
||||||
|
|
||||||
|
# 合并两个网格
|
||||||
|
merged_mesh = merge_meshes(mesh1, mesh2)
|
||||||
|
|
||||||
|
# 保存合并后的网格
|
||||||
|
save_merged_mesh(merged_mesh, "merged_model.obj")
|
||||||
|
|
||||||
|
# 可视化合并后的网格
|
||||||
|
o3d.visualization.draw_geometries([merged_mesh])
|
22
tools/merge_ply.py
Normal file
22
tools/merge_ply.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import open3d as o3d
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# 读取第一个PLY文件
|
||||||
|
pcd1 = o3d.io.read_point_cloud("path_to_first_file.ply")
|
||||||
|
|
||||||
|
# 读取第二个PLY文件
|
||||||
|
pcd2 = o3d.io.read_point_cloud("path_to_second_file.ply")
|
||||||
|
|
||||||
|
# 可选:如果需要调整坐标系,可以通过平移、旋转来对齐点云
|
||||||
|
# 例如,平移第二个点云
|
||||||
|
offset = np.array([1000, 2000, 3000])
|
||||||
|
pcd2.translate(offset)
|
||||||
|
|
||||||
|
# 合并点云
|
||||||
|
combined_pcd = pcd1 + pcd2
|
||||||
|
|
||||||
|
# 保存合并后的点云为PLY文件
|
||||||
|
o3d.io.write_point_cloud("merged_output.ply", combined_pcd)
|
||||||
|
|
||||||
|
# 可视化
|
||||||
|
o3d.visualization.draw_geometries([combined_pcd])
|
Loading…
Reference in New Issue
Block a user