feat: update algorithm integrations and point cloud overlays

This commit is contained in:
2026-06-30 16:46:36 +08:00
parent ddca7e5436
commit 7e2e56a50d
64 changed files with 4356 additions and 2781 deletions

View File

@@ -0,0 +1,192 @@
"""测量详细日志记录器 - 记录测量过程的所有详细信息"""
import sys
from pathlib import Path
from datetime import datetime
from typing import Optional
class MeasurementLogger:
"""测量过程详细日志记录器"""
def __init__(self, output_dir: str = "results"):
"""
初始化测量日志记录器
Args:
output_dir: 输出目录路径
"""
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
# 生成日志文件名
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
self.log_file = self.output_dir / f"measurement_detail_{timestamp}.log"
# 打开日志文件
self.file_handle = open(self.log_file, 'w', encoding='utf-8')
# 写入头部
self._write_header()
def _write_header(self):
"""写入日志头部"""
self.log("=" * 80)
self.log("点云测量系统 - 详细测量日志")
self.log("=" * 80)
self.log(f"开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
self.log("=" * 80)
self.log("")
def log(self, message: str, also_print: bool = True):
"""
记录日志信息
Args:
message: 日志消息
also_print: 是否同时输出到控制台
"""
# 写入文件
self.file_handle.write(message + "\n")
self.file_handle.flush() # 立即刷新到文件
# 输出到控制台
if also_print:
print(message)
def log_task_start(self, task_index: int, total_tasks: int, task_name: str):
"""记录任务开始"""
self.log("")
self.log("=" * 80)
self.log(f"[{task_index}/{total_tasks}] 开始执行任务: {task_name}")
self.log("=" * 80)
def log_roi_extraction(self, roi_name: str, point_count: int, bbox_min: list, bbox_max: list):
"""
记录ROI提取信息
Args:
roi_name: ROI名称(如"源平面ROI"、"目标平面ROI")
point_count: 提取到的点数
bbox_min: ROI最小边界 [x, y, z]
bbox_max: ROI最大边界 [x, y, z]
"""
self.log(f" {roi_name}:")
self.log(f" 边界: X[{bbox_min[0]:.2f}, {bbox_max[0]:.2f}], "
f"Y[{bbox_min[1]:.2f}, {bbox_max[1]:.2f}], "
f"Z[{bbox_min[2]:.2f}, {bbox_max[2]:.2f}]")
self.log(f" 提取点数: {point_count:,} 个点")
def log_ransac_fitting(self, plane_name: str, total_points: int,
inlier_count: int, inlier_ratio: float,
plane_equation: Optional[tuple] = None):
"""
记录RANSAC平面拟合信息
Args:
plane_name: 平面名称(如"源平面"、"目标平面")
total_points: 参与拟合的总点数
inlier_count: 内点数量
inlier_ratio: 内点率(0-1之间的浮点数)
plane_equation: 平面方程 (a, b, c, d),满足 ax + by + cz + d = 0
"""
self.log(f" {plane_name} RANSAC拟合:")
self.log(f" 拟合点数: {total_points:,} 个点")
self.log(f" 内点数量: {inlier_count:,} 个点")
self.log(f" 内点率: {inlier_ratio:.2%}")
if plane_equation:
a, b, c, d = plane_equation
self.log(f" 平面方程: {a:.6f}x + {b:.6f}y + {c:.6f}z + {d:.6f} = 0")
# 计算法向量
import numpy as np
normal = np.array([a, b, c])
norm = np.linalg.norm(normal)
if norm > 0:
normal = normal / norm
self.log(f" 法向量: ({normal[0]:.6f}, {normal[1]:.6f}, {normal[2]:.6f})")
def log_sampling(self, sample_count: int, method: str = "均匀采样"):
"""
记录采样信息
Args:
sample_count: 采样点数
method: 采样方法
"""
self.log(f" 采样策略: {method}")
self.log(f" 采样点数: {sample_count} 个点")
def log_distance_result(self, mean_distance: float, std_distance: float,
min_distance: float, max_distance: float):
"""
记录距离测量结果
Args:
mean_distance: 平均距离
std_distance: 标准差
min_distance: 最小距离
max_distance: 最大距离
"""
self.log(f" 测量结果:")
self.log(f" 平均距离: {mean_distance:.4f} mm")
self.log(f" 标准差: {std_distance:.4f} mm")
self.log(f" 最小距离: {min_distance:.4f} mm")
self.log(f" 最大距离: {max_distance:.4f} mm")
self.log(f" 距离范围: [{min_distance:.4f}, {max_distance:.4f}] mm")
def log_task_success(self, execution_time: float):
"""记录任务成功"""
self.log(f" 任务状态: ✅ 成功")
self.log(f" 执行时间: {execution_time:.2f} 秒")
def log_task_failure(self, error_message: str, execution_time: float):
"""记录任务失败"""
self.log(f" 任务状态: ❌ 失败")
self.log(f" 错误信息: {error_message}")
self.log(f" 执行时间: {execution_time:.2f} 秒")
def log_circle_fitting(self, circle_name: str, center: tuple, radius: float,
point_count: int):
"""
记录圆拟合信息
Args:
circle_name: 圆的名称
center: 圆心坐标 (x, y, z)
radius: 半径
point_count: 拟合点数
"""
self.log(f" {circle_name}:")
self.log(f" 圆心: ({center[0]:.4f}, {center[1]:.4f}, {center[2]:.4f})")
self.log(f" 半径: {radius:.4f} mm")
self.log(f" 拟合点数: {point_count:,} 个点")
def log_kdtree_optimization(self, original_points: int, filtered_points: int,
percentage: float):
"""
记录KDTree优化信息
Args:
original_points: 原始点数
filtered_points: 筛选后点数
percentage: 保留百分比
"""
self.log(f" KDTree优化:")
self.log(f" 原始点数: {original_points:,} 个点")
self.log(f" 筛选后: {filtered_points:,} 个点 ({percentage:.2f}%)")
def close(self):
"""关闭日志文件"""
self.log("")
self.log("=" * 80)
self.log(f"结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
self.log("=" * 80)
if self.file_handle:
self.file_handle.close()
print(f"\n详细测量日志已保存到: {self.log_file}")
def __del__(self):
"""析构函数,确保文件被关闭"""
if hasattr(self, 'file_handle') and self.file_handle:
self.file_handle.close()