diff --git a/odm_preprocess.py b/odm_preprocess.py index 45066e9..9513441 100644 --- a/odm_preprocess.py +++ b/odm_preprocess.py @@ -218,7 +218,7 @@ class ImagePreprocessor: if __name__ == "__main__": # 创建配置 config = PreprocessConfig( - image_dir=r"E:\datasets\UAV\502", + image_dir=r"E:\datasets\UAV\502\project\images", output_dir=r"E:\studio2\ODM_pro\test", cluster_eps=0.01, @@ -232,7 +232,7 @@ if __name__ == "__main__": filter_time_threshold=timedelta(minutes=5), grid_overlap=0.03, - grid_size=500, + grid_size=1000, enable_filter=True, enable_grid_division=True, diff --git a/preprocess/odm_monitor.py b/preprocess/odm_monitor.py index 4b2cb76..edaad8f 100644 --- a/preprocess/odm_monitor.py +++ b/preprocess/odm_monitor.py @@ -49,49 +49,67 @@ class ODMProcessMonitor: def run_odm_with_monitor(self, command: str, grid_dir: str, grid_idx: int) -> Tuple[bool, str]: """ 运行ODM命令并监控进程 - - Args: - command: ODM命令 - grid_dir: 网格目录 - grid_idx: 网格索引 - Returns: - Tuple[bool, str]: (是否成功, 错误信息) """ - # TODO 加入rerun信息 attempt = 0 while attempt < self.max_retries: try: self.logger.info(f"网格 {grid_idx + 1} 第 {attempt + 1} 次尝试执行ODM") - - # 启动ODM进程 + + # 创建日志文件 + 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进程,实时获取输出 process = subprocess.Popen( command, shell=True, cwd=grid_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=True + text=True, + bufsize=1, # 行缓冲 + 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容器已结束,获取进程输出 - stdout, stderr = process.communicate() - - time.sleep(10) - # 保存日志 - 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"=== 标准输出 ===\n{stdout}\n\n=== 错误输出 ===\n{stderr}") - + # Docker容器已结束 + process.wait() # 等待进程完全结束 + + # 等待输出线程结束 + stdout_thread.join(timeout=5) + stderr_thread.join(timeout=5) + + # 记录结束时间 + 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处理成功") @@ -100,17 +118,17 @@ class ODMProcessMonitor: self.logger.warning( f"网格 {grid_idx + 1} 第 {attempt + 1} 次尝试失败") break - + time.sleep(self.check_interval) - + # 如果不是最后一次尝试,等待后重试 if attempt < self.max_retries - 1: wait_time = (attempt + 1) * 30 self.logger.info(f"等待 {wait_time} 秒后重试...") time.sleep(wait_time) - + attempt += 1 - + except Exception as e: error_msg = f"监控进程发生异常: {str(e)}" self.logger.error(error_msg)