diff --git a/odm_preprocess.py b/odm_preprocess.py index af9643b..dd8cd1a 100644 --- a/odm_preprocess.py +++ b/odm_preprocess.py @@ -245,7 +245,7 @@ class ImagePreprocessor: f"grid_{grid_idx + 1}", "project", "odm_orthophoto", - "odm_orthophoto.original.tif" + "odm_orthophoto.tif" ) # 检查TIF文件是否存在 @@ -298,8 +298,7 @@ class ImagePreprocessor: self.command_runner.run_grid_commands( grid_points, ) - # 添加TIF合并步骤 - self.merge_tif(grid_points) + # self.merge_tif(grid_points) except Exception as e: self.logger.error(f"处理过程中发生错误: {str(e)}", exc_info=True) raise diff --git a/post_pro/merge_tif.py b/post_pro/merge_tif.py index f9a1ce6..d4c64a0 100644 --- a/post_pro/merge_tif.py +++ b/post_pro/merge_tif.py @@ -86,9 +86,9 @@ if __name__ == "__main__": from utils.logger import setup_logger # 定义影像路径 - input_tif1 = r"G:\20240930091614\output\grid_1\project\odm_orthophoto\odm_orthophoto.tif" - input_tif2 = r"G:\20240930091614\output\grid_2\project\odm_orthophoto\odm_orthophoto.tif" - output_tif = r"G:\20240930091614\output\merged_orthophoto.tif" + input_tif1 = r"G:\ODM_output\20241024100834\output\grid_1\project\odm_orthophoto\odm_orthophoto.tif" + input_tif2 = r"G:\ODM_output\20241024100834\output\grid_2\project\odm_orthophoto\odm_orthophoto.tif" + output_tif = r"G:\ODM_output\20241024100834\output\merged_orthophoto.tif" # 设置日志 output_dir = r"E:\studio2\ODM_pro\test" diff --git a/tools/convert_jpg.py b/tools/convert_jpg.py new file mode 100644 index 0000000..402a8cb --- /dev/null +++ b/tools/convert_jpg.py @@ -0,0 +1,14 @@ +from PIL import Image +import os + +convert_format = "tif" +img_dir = r"E:\datasets\UAV\134\project\images" +output_dir = r"E:\datasets\UAV\134_tif\project\images" + +for file_name in os.listdir(img_dir): + img = Image.open(os.path.join(img_dir, file_name)) + if convert_format == "png": + img.save(os.path.join(output_dir, file_name.replace(".jpg", ".png"))) + elif convert_format == "tif": + img.save(os.path.join(output_dir, file_name.replace(".jpg", ".tif")), "TIFF") + diff --git a/tools/show_GPS.py b/tools/show_GPS.py index f4690a6..8ea9664 100644 --- a/tools/show_GPS.py +++ b/tools/show_GPS.py @@ -3,9 +3,9 @@ import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import matplotlib.pyplot as plt -from preprocess.gps_extractor import GPSExtractor +from utils.gps_extractor import GPSExtractor -DATASET = r'F:\error_data\20240930091614\project\images' +DATASET = r'E:\datasets\UAV\1009\project\images' if __name__ == '__main__': extractor = GPSExtractor(DATASET) diff --git a/utils/command_runner.py b/utils/command_runner.py index 280e8d8..0daf5cd 100644 --- a/utils/command_runner.py +++ b/utils/command_runner.py @@ -37,10 +37,31 @@ i try: grid_dir = os.path.join(self.output_dir, f'grid_{grid_idx + 1}') grid_dir = grid_dir[0].lower() + grid_dir[1:].replace('\\', '/') + if self.mode == "快拼模式": - 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 8 --fast-orthophoto --skip-3dmodel" + command = ( + f"docker run -i --rm " + f"-v {grid_dir}:/datasets " + f"opendronemap/odm " + f"--project-path /datasets project " + f"--max-concurrency 10 " + f"--force-gps " + f"--feature-quality lowest " + f"--orthophoto-resolution 8 " + f"--fast-orthophoto " + f"--skip-3dmodel " + f"--rerun-all" + ) else: - command = f"docker run -ti --rm -v {grid_dir}:/datasets opendronemap/odm --project-path /datasets project --max-concurrency 10 --force-gps" + command = ( + f"docker run -i --rm " + f"-v {grid_dir}:/datasets " + f"opendronemap/odm " + f"--project-path /datasets project " + f"--max-concurrency 10 " + f"--force-gps " + f"--rerun-all" + ) self.logger.info(f"开始执行命令: {command}") success, error_msg = self.monitor.run_odm_with_monitor( diff --git a/utils/odm_monitor.py b/utils/odm_monitor.py index edaad8f..831d0d0 100644 --- a/utils/odm_monitor.py +++ b/utils/odm_monitor.py @@ -47,9 +47,7 @@ class ODMProcessMonitor: return all(os.path.exists(os.path.join(grid_dir, 'project', marker)) for marker in success_markers) def run_odm_with_monitor(self, command: str, grid_dir: str, grid_idx: int) -> Tuple[bool, str]: - """ - 运行ODM命令并监控进程 - """ + """运行ODM命令并监控进程""" attempt = 0 while attempt < self.max_retries: try: @@ -57,83 +55,58 @@ class ODMProcessMonitor: # 创建日志文件 log_file = os.path.join(grid_dir, f'odm_attempt_{attempt + 1}.log') - with open(log_file, 'w', encoding='utf-8') as f: - f.write(f"=== ODM处理日志 ===\n开始时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n") - # 启动ODM进程,实时获取输出 + # 使用 subprocess.Popen 启动进程,并设置适当的参数 process = subprocess.Popen( command, shell=True, - cwd=grid_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=True, - bufsize=1, # 行缓冲 - universal_newlines=True + bufsize=1, # 使用行缓冲 + text=True, # 使用文本模式 + universal_newlines=True # 统一换行符处理 ) - self.logger.info("ODM进程已启动,开始监控Docker容器") - - # 等待进程启动 - time.sleep(10) - - # 实时读取输出并写入日志 - def log_output(pipe, log_file, prefix=""): - with open(log_file, 'a', encoding='utf-8') as f: - for line in pipe: - f.write(f"{prefix}{line}") - f.flush() # 确保立即写入 - - # 创建线程读取输出 - from threading import Thread - stdout_thread = Thread(target=log_output, - args=(process.stdout, log_file)) - stderr_thread = Thread(target=log_output, - args=(process.stderr, log_file, "ERROR: ")) - - stdout_thread.daemon = True - stderr_thread.daemon = True - stdout_thread.start() - stderr_thread.start() - - # 监控Docker容器 + # 使用非阻塞方式读取输出 while True: - if not self._check_docker_container(): - # Docker容器已结束 - process.wait() # 等待进程完全结束 - - # 等待输出线程结束 - stdout_thread.join(timeout=5) - stderr_thread.join(timeout=5) - - # 记录结束时间 + # 读取输出 + output = process.stdout.readline() + if output: with open(log_file, 'a', encoding='utf-8') as f: - f.write(f"\n=== 处理结束 ===\n结束时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n") - - # 检查是否成功完成 - if self._check_success(grid_dir): - self.logger.info(f"网格 {grid_idx + 1} ODM处理成功") - return True, "" - else: - self.logger.warning( - f"网格 {grid_idx + 1} 第 {attempt + 1} 次尝试失败") - break + f.write(output) + self.logger.info(f"网格 {grid_idx + 1}: {output.strip()}") - time.sleep(self.check_interval) + # 检查进程是否结束 + if process.poll() is not None: + break + + # 检查Docker容器状态 + if not self._check_docker_container(): + break + + time.sleep(0.1) # 短暂休眠,避免CPU过度使用 - # 如果不是最后一次尝试,等待后重试 - if attempt < self.max_retries - 1: - wait_time = (attempt + 1) * 30 - self.logger.info(f"等待 {wait_time} 秒后重试...") - time.sleep(wait_time) + # 获取最终返回码 + return_code = process.wait() - attempt += 1 + # 检查是否成功完成 + if return_code == 0 and self._check_success(grid_dir): + self.logger.info(f"网格 {grid_idx + 1} ODM处理成功") + return True, "" + + self.logger.warning(f"网格 {grid_idx + 1} 第 {attempt + 1} 次尝试失败") except Exception as e: error_msg = f"监控进程发生异常: {str(e)}" self.logger.error(error_msg) return False, error_msg - - error_msg = f"网格 {grid_idx + 1} 在 {self.max_retries} 次尝试后仍然失败,需要人工查看" + + attempt += 1 + if attempt < self.max_retries: + wait_time = (attempt + 1) * 30 + self.logger.info(f"等待 {wait_time} 秒后重试...") + time.sleep(wait_time) + + error_msg = f"网格 {grid_idx + 1} 在 {self.max_retries} 次尝试后仍然失败" self.logger.error(error_msg) return False, error_msg