修改容错代码

This commit is contained in:
龙澳 2025-01-06 19:48:27 +08:00
parent 9935d8f789
commit a3b03de856
4 changed files with 156 additions and 73 deletions

View File

@ -18,7 +18,6 @@ from utils.grid_divider import GridDivider
from utils.logger import setup_logger 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 post_pro.merge_obj import MergeObj from post_pro.merge_obj import MergeObj
from post_pro.merge_laz import MergePly from post_pro.merge_laz import MergePly
@ -69,6 +68,7 @@ class ImagePreprocessor:
config.output_dir, mode=config.mode) config.output_dir, mode=config.mode)
self.visualizer = FilterVisualizer(config.output_dir) self.visualizer = FilterVisualizer(config.output_dir)
# TODO 给出警告!
def _clean_output_dir(self): def _clean_output_dir(self):
"""清理输出目录""" """清理输出目录"""
try: try:
@ -303,7 +303,7 @@ 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=800,
grid_overlap=0.05, grid_overlap=0.05,

134
tools/gps_selector.py Normal file
View File

@ -0,0 +1,134 @@
import os
import sys
import shutil
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.widgets import RectangleSelector
import pandas as pd
# 添加项目根目录到系统路径
project_root = str(Path(__file__).parent.parent)
sys.path.append(project_root)
from utils.gps_extractor import GPSExtractor
class GPSSelector:
def __init__(self, image_dir: str, output_dir: str = None):
self.image_dir = image_dir
self.output_dir = output_dir
self.gps_points = None
self.selected_points = []
self.fig, self.ax = plt.subplots(figsize=(12, 8))
self.scatter = None
self.rs = None
self.setup_plot()
def extract_gps(self):
"""提取GPS数据"""
extractor = GPSExtractor(self.image_dir)
self.gps_points = extractor.extract_all_gps()
print(f"成功提取 {len(self.gps_points)} 个GPS点")
def setup_plot(self):
"""设置绘图"""
self.ax.set_title('GPS Points - 使用鼠标拖动选择要删除的点')
self.ax.set_xlabel('Longitude')
self.ax.set_ylabel('Latitude')
self.ax.grid(True)
# 设置矩形选择器
self.rs = RectangleSelector(
self.ax, self.on_select,
interactive=True,
useblit=True,
button=[1], # 只响应左键
props=dict(facecolor='red', alpha=0.3)
)
# 添加按钮回调
self.fig.canvas.mpl_connect('key_press_event', self.on_key_press)
def plot_gps_points(self):
"""绘制GPS点"""
if self.scatter is not None:
self.scatter.remove()
self.scatter = self.ax.scatter(
self.gps_points['lon'],
self.gps_points['lat'],
c='blue',
s=20,
alpha=0.6
)
self.fig.canvas.draw_idle()
def on_select(self, eclick, erelease):
"""矩形选择回调"""
x1, y1 = eclick.xdata, eclick.ydata
x2, y2 = erelease.xdata, erelease.ydata
# 获取选中区域内的点
mask = (
(self.gps_points['lon'] >= min(x1, x2)) &
(self.gps_points['lon'] <= max(x1, x2)) &
(self.gps_points['lat'] >= min(y1, y2)) &
(self.gps_points['lat'] <= max(y1, y2))
)
selected = self.gps_points[mask]
self.selected_points.extend(selected['file'].tolist())
# 从数据中移除选中的点
self.gps_points = self.gps_points[~mask]
# 更新绘图
self.plot_gps_points()
print(f"选中 {len(selected)} 个点,剩余 {len(self.gps_points)} 个点")
def on_key_press(self, event):
"""键盘事件回调"""
if event.key == 'enter':
self.save_results()
plt.close()
elif event.key == 'escape':
plt.close()
def save_results(self):
"""保存结果"""
if not self.output_dir:
return
# 创建输出目录
os.makedirs(self.output_dir, exist_ok=True)
removed_dir = os.path.join(self.output_dir, "removed_images")
os.makedirs(removed_dir, exist_ok=True)
# 移动被删除的图像
for img_name in self.selected_points:
src = os.path.join(self.image_dir, img_name)
dst = os.path.join(removed_dir, img_name)
shutil.move(src, dst)
# 保存剩余点的信息
self.gps_points.to_csv(
os.path.join(self.output_dir, "remaining_points.csv"),
index=False
)
print(f"已移动 {len(self.selected_points)} 张图片到 {removed_dir}")
print(f"保留 {len(self.gps_points)} 个点")
def run(self):
"""运行选择器"""
self.extract_gps()
self.plot_gps_points()
plt.show()
if __name__ == "__main__":
# 使用示例
selector = GPSSelector(
image_dir=r"E:\datasets\UAV\1619\project\images",
output_dir=r"E:\datasets\UAV\1619\filtered"
)
selector.run()

View File

@ -1,22 +0,0 @@
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])

View File

@ -13,26 +13,6 @@ class NotOverlapError(Exception):
pass pass
class DockerNotRunError(Exception):
"""Docker未启动异常"""
pass
class DockerShareError(Exception):
"""Docker目录共享异常"""
pass
class OutOfMemoryError(Exception):
"""内存不足异常"""
pass
class StrangeValuesError(Exception):
"""异常值异常"""
pass
class ODMProcessMonitor: class ODMProcessMonitor:
"""ODM处理监控器""" """ODM处理监控器"""
@ -121,6 +101,8 @@ class ODMProcessMonitor:
return False, "快拼模式下无法生成DEM请调整生产参数" return False, "快拼模式下无法生成DEM请调整生产参数"
self.logger.info(f"开始处理网格 ({grid_id[0]},{grid_id[1]})") self.logger.info(f"开始处理网格 ({grid_id[0]},{grid_id[1]})")
success = False
error_msg = ""
max_retries = 3 max_retries = 3
current_try = 0 current_try = 0
use_lowest_quality = True # 初始使用lowest quality use_lowest_quality = True # 初始使用lowest quality
@ -146,7 +128,7 @@ class ODMProcessMonitor:
if use_lowest_quality: if use_lowest_quality:
docker_command += f"--feature-quality lowest " docker_command += f"--feature-quality lowest "
docker_command += f"--orthophoto-resolution 10 " docker_command += f"--orthophoto-resolution 8 "
if produce_dem: if produce_dem:
docker_command += ( docker_command += (
@ -177,11 +159,12 @@ class ODMProcessMonitor:
self.logger.error(f"docker run指令执行失败") self.logger.error(f"docker run指令执行失败")
self.logger.error(f"==========stderr==========: {stderr}") self.logger.error(f"==========stderr==========: {stderr}")
if "error during connect" in stderr or "The system cannot find the file specified" in stderr: if "error during connect" in stderr or "The system cannot find the file specified" in stderr:
raise DockerNotRunError error_msg = "Docker没有启动请启动Docker"
elif "user declined directory sharing" in stderr: elif "user declined directory sharing" in stderr:
raise DockerShareError error_msg = "Docker无法访问目录请检查目录权限和共享设置"
else: else:
raise Exception(f"Docker运行失败需要人工排查错误") error_msg = "Docker运行失败需要人工排查错误"
break
# TODO 处理时间组删除,删多了的情况 # TODO 处理时间组删除,删多了的情况
else: else:
self.logger.info("docker run指令执行成功") self.logger.info("docker run指令执行成功")
@ -190,49 +173,37 @@ class ODMProcessMonitor:
if self._check_success(grid_dir): if self._check_success(grid_dir):
self.logger.info( self.logger.info(
f"网格 ({grid_id[0]},{grid_id[1]}) 处理成功") f"网格 ({grid_id[0]},{grid_id[1]}) 处理成功")
return True, "" success = True
error_msg = ""
break
else: else:
self.logger.error( self.logger.error(
f"虽然ODM处理完成但是生产产品质量可能不合格需要人工检查") f"虽然ODM处理完成但是生产产品质量可能不合格需要人工检查")
raise Exception(f"虽然ODM处理完成但是生产产品质量可能不合格需要人工检查") raise NotOverlapError
# TODO 先写成这样,后面这三种情况可能处理不一样
elif "enough overlap" in last_lines: elif "enough overlap" in last_lines:
raise NotOverlapError raise NotOverlapError
elif "out of memory" in last_lines: elif "out of memory" in last_lines:
raise OutOfMemoryError raise NotOverlapError
elif "strange values" in last_lines: elif "strange values" in last_lines:
raise StrangeValuesError raise NotOverlapError
else: else:
raise Exception(f"ODM处理失败需要人工排查错误") raise NotOverlapError
except NotOverlapError: except NotOverlapError:
if use_lowest_quality: if use_lowest_quality:
self.logger.warning( self.logger.warning(
"检测到not overlap错误移除lowest quality参数后重试") "检测到not overlap错误移除lowest quality参数后重试")
use_lowest_quality = False use_lowest_quality = False
time.sleep(10)
continue continue
else: else:
self.logger.error( self.logger.error(
"即使移除lowest quality参数后仍然出现not overlap错误") "即使移除lowest quality参数后仍然出现错误")
return False, "图像重叠度不足,请检查数据集的采样间隔情况" error_msg = "图像重叠度不足,需要人工检查数据集的采样间隔情况"
break
except DockerNotRunError: return success, error_msg
self.logger.error("Docker服务未启动")
return False, "Docker没有启动请启动Docker"
except DockerShareError:
self.logger.error("Docker无法访问目录")
return False, "Docker无法访问数据目录或输出目录请检查目录权限和共享设置"
except OutOfMemoryError:
self.logger.error("内存不足,请减少输入图像的数量")
return False, "内存不足"
except StrangeValuesError:
self.logger.error("重建过程中出现异常值")
return False, "检测到异常值,请检查输入数据集的采样间隔情况"
time.sleep(10)
return False, f"网格 ({grid_id[0]},{grid_id[1]}) 处理失败"
def process_all_grids(self, grid_points: Dict[tuple, pd.DataFrame], produce_dem: bool) -> Dict[tuple, pd.DataFrame]: def process_all_grids(self, grid_points: Dict[tuple, pd.DataFrame], produce_dem: bool) -> Dict[tuple, pd.DataFrame]:
"""处理所有网格 """处理所有网格