From cd36dcb6e9f896264e31012a5617ebea7e25fe14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BE=99=E6=BE=B3?= Date: Thu, 9 Jan 2025 11:45:55 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=93=E6=9E=9C=E5=90=8E=E5=A4=84=E7=90=86?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 50 +++++++++++++++++++++++++++++++++ odm_preprocess.py | 65 ++++++++++++++++++++++++++++++++++++++----- post_pro/merge_laz.py | 2 +- post_pro/merge_obj.py | 12 ++++---- utils/odm_monitor.py | 17 ++++++----- 5 files changed, 125 insertions(+), 21 deletions(-) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..2e9f20b --- /dev/null +++ b/main.py @@ -0,0 +1,50 @@ +import argparse +from datetime import timedelta +from odm_preprocess import PreprocessConfig, ImagePreprocessor + +def parse_args(): + parser = argparse.ArgumentParser(description='ODM预处理工具') + + # 必需参数 + parser.add_argument('--image_dir', required=True, help='输入图片目录路径') + parser.add_argument('--output_dir', required=True, help='输出目录路径') + + # 可选参数 + parser.add_argument('--mode', default='重建模式', choices=['快拼模式', '三维模式', '重建模式'], help='处理模式') + parser.add_argument('--grid_size', type=float, default=1000, help='网格大小(米)') + parser.add_argument('--grid_overlap', type=float, default=0.05, help='网格重叠率') + parser.add_argument('--produce_dem', action='store_true', help='是否生成DEM') + + args = parser.parse_args() + return args + +def main(): + args = parse_args() + + # 创建配置 + config = PreprocessConfig( + image_dir=args.image_dir, + output_dir=args.output_dir, + mode=args.mode, + grid_size=args.grid_size, + grid_overlap=args.grid_overlap, + produce_dem=args.produce_dem, + + # 其他参数使用默认值 + cluster_eps=0.01, + cluster_min_samples=5, + time_group_overlap_threshold=0.7, + time_group_interval=timedelta(minutes=5), + filter_distance_threshold=0.001, + filter_min_neighbors=6, + filter_grid_size=0.001, + filter_dense_distance_threshold=10, + filter_time_threshold=timedelta(minutes=5), + ) + + # 创建处理器并执行 + processor = ImagePreprocessor(config) + processor.process() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/odm_preprocess.py b/odm_preprocess.py index 23323b7..717236f 100644 --- a/odm_preprocess.py +++ b/odm_preprocess.py @@ -247,17 +247,68 @@ class ImagePreprocessor: merger.merge_grid_obj(grid_points, translations) def post_process(self, successful_grid_points: Dict[tuple, pd.DataFrame], grid_points: Dict[tuple, pd.DataFrame], translations: Dict[tuple, tuple]): + """后处理:合并或复制处理结果""" if len(successful_grid_points) == 1: - self.logger.info(f"只有一个网格{successful_grid_points.keys()},无需合并") - self.logger.info(f"生产结果请在{successful_grid_points.keys()[0]}目录下查看") + # 获取唯一成功的网格ID + grid_id = list(successful_grid_points.keys())[0] + self.logger.info(f"只有一个网格 {grid_id} 成功处理,直接复制结果") + + # 构建源目录路径(成功网格的输出目录) + src_dir = os.path.join( + self.config.output_dir, f"grid_{grid_id[0]}_{grid_id[1]}", "project") + + # 复制正射影像 + if self.config.mode == "快拼模式": + shutil.copy2(os.path.join(src_dir, "odm_orthophoto", "odm_orthophoto.original.tif"), + os.path.join(self.config.output_dir, + "orthophoto.tif") + ) + elif self.config.mode == "三维模式": + shutil.copy2(os.path.join(src_dir, "odm_georeferencing", "odm_georeferenced_model.laz"), + os.path.join(self.config.output_dir, + "pointcloud.laz") + ) + shutil.copytree(os.path.join(src_dir, "odm_texturing"), + os.path.join(self.config.output_dir, "texturing")) + elif self.config.mode == "重建模式": + shutil.copy2(os.path.join(src_dir, "odm_orthophoto", "odm_orthophoto.tif"), + os.path.join(self.config.output_dir, + "orthophoto.tif") + ) + shutil.copy2(os.path.join(src_dir, "odm_georeferencing", "odm_georeferenced_model.laz"), + os.path.join(self.config.output_dir, + "odm_georeferenced_model.laz") + ) + shutil.copytree(os.path.join(src_dir, "odm_texturing"), + os.path.join(self.config.output_dir, "texturing")) + if self.config.produce_dem: + shutil.copy2( + os.path.join(src_dir, "odm_dem", "dsm.tif"), + os.path.join(self.config.output_dir, "dsm.tif") + ) + shutil.copy2( + os.path.join(src_dir, "odm_dem", "dtm.tif"), + os.path.join(self.config.output_dir, "dtm.tif") + ) + + self.logger.info("单网格结果复制完成") + return + + # 如果有多个网格,执行合并操作 elif len(successful_grid_points) < len(grid_points): self.logger.warning( f"有 {len(grid_points) - len(successful_grid_points)} 个网格处理失败," f"将只合并成功处理的 {len(successful_grid_points)} 个网格" ) - self.merge_tif(successful_grid_points, self.config.produce_dem) - if self.config.mode != "快拼模式": + + if self.config.mode == "快拼模式": + self.merge_tif(successful_grid_points, self.config.produce_dem) + elif self.config.mode == "三维模式": + self.merge_ply(successful_grid_points) + self.merge_obj(successful_grid_points, translations) + else: + self.merge_tif(successful_grid_points, self.config.produce_dem) self.merge_ply(successful_grid_points) self.merge_obj(successful_grid_points, translations) @@ -286,8 +337,8 @@ class ImagePreprocessor: if __name__ == "__main__": # 创建配置 config = PreprocessConfig( - image_dir=r"G:\test_data\error1_L", - output_dir=r"G:\ODM_output\error1_L", + image_dir=r"E:\datasets\UAV\134\project\images", + output_dir=r"G:\ODM_output\134", cluster_eps=0.01, cluster_min_samples=5, @@ -307,7 +358,7 @@ if __name__ == "__main__": grid_overlap=0.05, - mode="重建模式", + mode="快拼模式", produce_dem=False, ) diff --git a/post_pro/merge_laz.py b/post_pro/merge_laz.py index c101614..b4ff770 100644 --- a/post_pro/merge_laz.py +++ b/post_pro/merge_laz.py @@ -35,7 +35,7 @@ class MergePly: kwargs = { 'all_inputs': " ".join(laz_files), - 'output': os.path.join(self.output_dir, 'merged_pointcloud.laz') + 'output': os.path.join(self.output_dir, 'pointcloud.laz') } subprocess.run('D:\\software\\LAStools\\bin\\lasmerge64.exe -i {all_inputs} -o "{output}"'.format(**kwargs)) diff --git a/post_pro/merge_obj.py b/post_pro/merge_obj.py index 59cf43b..0f4c70a 100644 --- a/post_pro/merge_obj.py +++ b/post_pro/merge_obj.py @@ -175,7 +175,7 @@ class MergeObj: all_face_materials.append(material_map2.get(material)) # 写入合并后的obj文件,使用与MTL文件相同的名称 - mtl_filename = "merged_model.mtl" # 使用固定的MTL文件名 + mtl_filename = "textured_model.mtl" # 使用固定的MTL文件名 self.write_obj(output_path, all_vertices, all_tex_coords, all_normals, all_faces, all_face_materials, mtl_filename) self.logger.info(f"模型合并成功,已保存至: {output_path}") @@ -273,7 +273,7 @@ class MergeObj: try: # 创建输出目录 - output_model_dir = os.path.join(self.output_dir, "merged_model") + output_model_dir = os.path.join(self.output_dir, "texturing") os.makedirs(output_model_dir, exist_ok=True) # 获取所有有效的网格文件 @@ -323,7 +323,7 @@ class MergeObj: all_materials.update(updated_materials) # 写入合并后的MTL文件 - final_mtl = os.path.join(output_model_dir, "merged_model.mtl") + final_mtl = os.path.join(output_model_dir, "textured_model.mtl") with open(final_mtl, 'w') as f: for mat_name, content in all_materials.items(): f.write(f"newmtl {mat_name}\n") @@ -353,7 +353,7 @@ class MergeObj: merged_obj = temp_output # 最终结果 - final_obj = os.path.join(output_model_dir, "merged_model.obj") + final_obj = os.path.join(output_model_dir, "textured_model.obj") try: if os.path.exists(final_obj): os.remove(final_obj) @@ -377,8 +377,8 @@ class MergeObj: self.logger.info( f"模型合并完成,输出目录: {output_model_dir}\n" - f"- OBJ文件: merged_model.obj\n" - f"- MTL文件: merged_model.mtl\n" + f"- OBJ文件: textured_model.obj\n" + f"- MTL文件: textured_model.mtl\n" f"- 纹理文件: {len(os.listdir(output_model_dir)) - 2}个" ) diff --git a/utils/odm_monitor.py b/utils/odm_monitor.py index 8887ee9..0eabeb4 100644 --- a/utils/odm_monitor.py +++ b/utils/odm_monitor.py @@ -94,11 +94,11 @@ class ODMProcessMonitor: self.logger.error(f"检查正射影像时发生错误: {str(e)}") return False - def run_odm_with_monitor(self, grid_dir: str, grid_id: tuple, fast_mode: bool = True, produce_dem: bool = False) -> Tuple[bool, str]: + def run_odm_with_monitor(self, grid_dir: str, grid_id: tuple, produce_dem: bool = False) -> Tuple[bool, str]: """运行ODM命令""" - if produce_dem and fast_mode: - self.logger.error("快拼模式下无法生成DEM,请调整生产参数") - return False, "快拼模式下无法生成DEM,请调整生产参数" + # if produce_dem and self.mode == "快拼模式": + # self.logger.error("快拼模式下无法生成DEM,请调整生产参数") + # return False, "快拼模式下无法生成DEM,请调整生产参数" self.logger.info(f"开始处理网格 ({grid_id[0]},{grid_id[1]})") success = False @@ -136,11 +136,15 @@ class ODMProcessMonitor: f"--dtm " ) - if fast_mode: + if self.mode == "快拼模式": docker_command += ( - f"--fast-orthophoto " + #f"--fast-orthophoto " f"--skip-3dmodel " ) + elif self.mode == "三维模式": + docker_command += ( + f"--skip-orthophoto " + ) docker_command += "--rerun-all" self.logger.info(docker_command) @@ -224,7 +228,6 @@ class ODMProcessMonitor: success, error_msg = self.run_odm_with_monitor( grid_dir=grid_dir, grid_id=grid_id, - fast_mode=(self.mode == "快拼模式"), produce_dem=produce_dem )