feat: update algorithm integrations and point cloud overlays
This commit is contained in:
192
alg/train_measurement_system_v3.2_0629/src/measurement_logger.py
Normal file
192
alg/train_measurement_system_v3.2_0629/src/measurement_logger.py
Normal 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()
|
||||
Reference in New Issue
Block a user