|
|
@@ -481,113 +481,6 @@ class GridRecovery:
|
|
|
|
|
|
bboxes.sort(key=lambda b: (int(b[1] / 10), b[0]))
|
|
|
|
|
|
- # 添加详细验证
|
|
|
- if len(bboxes) > 0:
|
|
|
- min_y = min(b[1] for b in bboxes)
|
|
|
- max_y = max(b[3] for b in bboxes)
|
|
|
- coverage_h = max_y - min_y
|
|
|
- expected_h = orig_h if orig_h else h / upscale
|
|
|
-
|
|
|
- logger.debug(
|
|
|
- f"📏 单元格Y轴覆盖验证:\n"
|
|
|
- f" - 最小Y: {min_y:.1f}\n"
|
|
|
- f" - 最大Y: {max_y:.1f}\n"
|
|
|
- f" - 覆盖高度: {coverage_h:.1f}\n"
|
|
|
- f" - 原图高度: {expected_h:.1f}\n"
|
|
|
- f" - 覆盖率: {coverage_h/expected_h*100:.1f}%\n"
|
|
|
- f" - 顶部空白: {min_y:.1f}px ({min_y/expected_h*100:.1f}%)\n"
|
|
|
- f" - 底部空白: {expected_h - max_y:.1f}px ({(expected_h-max_y)/expected_h*100:.1f}%)"
|
|
|
- )
|
|
|
-
|
|
|
- # 可视化验证:保存调试图像,显示上采样mask上的连通域bbox和转换后的原图坐标
|
|
|
- if debug_dir and len(bboxes) > 0:
|
|
|
- try:
|
|
|
- os.makedirs(debug_dir, exist_ok=True)
|
|
|
-
|
|
|
- # 创建可视化图像:上采样mask上的连通域bbox(绿色)
|
|
|
- vis_mask = np.zeros((h, w, 3), dtype=np.uint8)
|
|
|
- vis_mask[:, :, 0] = inv_grid # 背景用反转的grid
|
|
|
- vis_mask[:, :, 1] = inv_grid
|
|
|
- vis_mask[:, :, 2] = inv_grid
|
|
|
-
|
|
|
- # 在上采样mask上绘制连通域bbox(使用上采样坐标)
|
|
|
- for idx, bbox_orig in enumerate(bboxes[:min(20, len(bboxes))]): # 只绘制前20个,避免太密集
|
|
|
- # 反推上采样坐标
|
|
|
- x_up = int(bbox_orig[0] * scale_w)
|
|
|
- y_up = int(bbox_orig[1] * scale_h)
|
|
|
- x2_up = int(bbox_orig[2] * scale_w)
|
|
|
- y2_up = int(bbox_orig[3] * scale_h)
|
|
|
-
|
|
|
- # 确保坐标在范围内
|
|
|
- x_up = max(0, min(x_up, w - 1))
|
|
|
- y_up = max(0, min(y_up, h - 1))
|
|
|
- x2_up = max(0, min(x2_up, w - 1))
|
|
|
- y2_up = max(0, min(y2_up, h - 1))
|
|
|
-
|
|
|
- if x2_up > x_up and y2_up > y_up:
|
|
|
- cv2.rectangle(vis_mask, (x_up, y_up), (x2_up, y2_up), (0, 255, 0), 2)
|
|
|
- # 标注单元格索引
|
|
|
- cv2.putText(vis_mask, str(idx), (x_up + 2, y_up + 15),
|
|
|
- cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 0), 1)
|
|
|
-
|
|
|
- name = f"{debug_prefix}_coordinate_verification_mask.png" if debug_prefix else "coordinate_verification_mask.png"
|
|
|
- path = os.path.join(debug_dir, name)
|
|
|
- cv2.imwrite(path, vis_mask)
|
|
|
- logger.debug(f"保存坐标验证图像(上采样mask): {path}")
|
|
|
-
|
|
|
- except Exception as e:
|
|
|
- logger.warning(f"保存坐标验证图像失败: {e}")
|
|
|
-
|
|
|
- # 详细的坐标转换调试日志
|
|
|
- if len(bboxes) > 0:
|
|
|
- logger.debug(
|
|
|
- f"🔍 坐标转换验证:\n"
|
|
|
- f" - mask尺寸: [{h}, {w}]\n"
|
|
|
- f" - 原图尺寸: [{orig_h}, {orig_w}]\n"
|
|
|
- f" - 缩放比例: scale_h={scale_h:.6f}, scale_w={scale_w:.6f}\n"
|
|
|
- f" - 缩放比例差异: {abs(scale_h - scale_w):.6f}\n"
|
|
|
- f" - 提取到 {len(bboxes)} 个单元格"
|
|
|
- )
|
|
|
-
|
|
|
- # 记录前几个和后几个单元格的详细坐标转换过程
|
|
|
- sample_indices = [0, 1, 2] + [len(bboxes) - 3, len(bboxes) - 2, len(bboxes) - 1]
|
|
|
- sample_indices = [i for i in sample_indices if 0 <= i < len(bboxes)]
|
|
|
-
|
|
|
- logger.debug("🔍 样本单元格坐标转换详情:")
|
|
|
- for idx in sample_indices:
|
|
|
- bbox_orig = bboxes[idx]
|
|
|
- # 反推上采样坐标(用于验证)
|
|
|
- x_up = bbox_orig[0] * scale_w
|
|
|
- y_up = bbox_orig[1] * scale_h
|
|
|
- w_up = (bbox_orig[2] - bbox_orig[0]) * scale_w
|
|
|
- h_up = (bbox_orig[3] - bbox_orig[1]) * scale_h
|
|
|
-
|
|
|
- logger.debug(
|
|
|
- f" 单元格 {idx}: 原图坐标 [{bbox_orig[0]:.1f}, {bbox_orig[1]:.1f}, "
|
|
|
- f"{bbox_orig[2]:.1f}, {bbox_orig[3]:.1f}] "
|
|
|
- f"(尺寸: {bbox_orig[2]-bbox_orig[0]:.1f}x{bbox_orig[3]-bbox_orig[1]:.1f}) "
|
|
|
- f"-> 反推上采样坐标 [{x_up:.1f}, {y_up:.1f}, {x_up+w_up:.1f}, {y_up+h_up:.1f}] "
|
|
|
- f"(尺寸: {w_up:.1f}x{h_up:.1f})"
|
|
|
- )
|
|
|
-
|
|
|
- # 检查是否有系统性偏移
|
|
|
- if len(bboxes) >= 2:
|
|
|
- first_y = bboxes[0][1]
|
|
|
- last_y = bboxes[-1][3]
|
|
|
- expected_height = last_y - first_y
|
|
|
- actual_image_height = orig_h if orig_h else h / upscale
|
|
|
- logger.debug(
|
|
|
- f"🔍 系统性偏移检查:\n"
|
|
|
- f" - 第一个单元格y1: {first_y:.1f}\n"
|
|
|
- f" - 最后一个单元格y2: {last_y:.1f}\n"
|
|
|
- f" - 单元格覆盖高度: {expected_height:.1f}\n"
|
|
|
- f" - 原图实际高度: {actual_image_height:.1f}\n"
|
|
|
- f" - 高度差异: {abs(expected_height - actual_image_height):.1f}"
|
|
|
- )
|
|
|
-
|
|
|
- logger.debug(f"bbox 坐标范围: x=[{min(b[0] for b in bboxes):.1f}, {max(b[2] for b in bboxes):.1f}], "
|
|
|
- f"y=[{min(b[1] for b in bboxes):.1f}, {max(b[3] for b in bboxes):.1f}]")
|
|
|
-
|
|
|
if orig_h is not None and orig_w is not None:
|
|
|
logger.info(
|
|
|
f"矢量重构分析提取到 {len(bboxes)} 个单元格 "
|