Spaces:
Sleeping
Sleeping
| import pytest | |
| import numpy as np | |
| import cv2 | |
| from src.engines import multiscale_template_match, soft_nms, refine_bbox_local_search | |
| def test_multiscale_template_match(dummy_grayscale_drawing, dummy_pattern): | |
| drawing_edge = cv2.Canny(dummy_grayscale_drawing, 30, 100) | |
| tmpl_edge = cv2.Canny(dummy_pattern, 30, 100) | |
| proposals = multiscale_template_match( | |
| drawing_edge, tmpl_edge, scale_range=(0.9, 1.1), scale_step=0.05, threshold=0.4 | |
| ) | |
| assert len(proposals) > 0 | |
| # Đảm bảo các đề xuất có định dạng hợp lệ | |
| assert all(len(p) == 6 for p in proposals) | |
| # Xác nhận đề xuất được chấm score chính xác | |
| assert proposals[0][4] >= 0.4 | |
| # Đảm bảo các đề xuất nằm gần tọa độ thực tế của nét vẽ chữ nhật | |
| assert any(abs(p[0] - 50) <= 5 and abs(p[1] - 50) <= 5 for p in proposals) | |
| assert any(abs(p[0] - 180) <= 5 and abs(p[1] - 180) <= 5 for p in proposals) | |
| def test_multiscale_template_match_oversize(dummy_grayscale_drawing): | |
| # Tạo template có kích thước 400x400 lớn hơn drawing 300x300 | |
| huge_tmpl = np.ones((400, 400), dtype=np.uint8) | |
| proposals = multiscale_template_match( | |
| dummy_grayscale_drawing, huge_tmpl, scale_range=(1.0, 1.2), scale_step=0.1 | |
| ) | |
| # Không được crash và phải bỏ qua gracefull các scale vượt quá | |
| assert proposals == [] | |
| def test_soft_nms_stable(): | |
| boxes = [ | |
| {"bbox": (10, 10, 50, 50), "confidence": 0.95}, | |
| {"bbox": (11, 11, 50, 50), "confidence": 0.90}, # Chồng lấp cực cao IoU > 0.9 | |
| {"bbox": (150, 150, 50, 50), "confidence": 0.80} # Tách biệt hoàn toàn | |
| ] | |
| nms_res = soft_nms(boxes, iou_threshold=0.3, sigma=0.5, score_threshold=0.5, method="gaussian") | |
| assert len(nms_res) == 2 | |
| assert nms_res[0]["bbox"] == (10, 10, 50, 50) | |
| assert nms_res[1]["bbox"] == (150, 150, 50, 50) | |
| def test_soft_nms_edge_cases(): | |
| # Input rỗng | |
| assert soft_nms([], method="linear") == [] | |
| # Thử nghiệm Linear Decay method | |
| boxes = [ | |
| {"bbox": (10, 10, 50, 50), "confidence": 0.95}, | |
| {"bbox": (12, 12, 50, 50), "confidence": 0.90} # Chồng lấp lớn | |
| ] | |
| res = soft_nms(boxes, iou_threshold=0.3, score_threshold=0.5, method="linear") | |
| # Với linear decay: 0.90 * (1 - IoU) ≈ 0.90 * (1 - 0.92) ≈ 0.07 -> Nhỏ hơn threshold -> Bị loại | |
| assert len(res) == 1 | |
| def test_refine_bbox_local_search(dummy_grayscale_drawing, dummy_pattern): | |
| # Giả lập drawing chứa nét tại (50, 50, 50, 50) | |
| # Ta truyền vào bbox bị lệch (48, 48, 50, 50) | |
| drawing_edge = cv2.Canny(dummy_grayscale_drawing, 30, 100) | |
| tmpl_edge = cv2.Canny(dummy_pattern, 30, 100) | |
| rx, ry, rw, rh, rscore = refine_bbox_local_search( | |
| drawing_edge, (48, 48, 50, 50), tmpl_edge, search_radius=5 | |
| ) | |
| # Tọa độ sau tinh chỉnh phải được hiệu chuẩn tiệm cận (50, 50) | |
| assert abs(rx - 50) <= 2 | |
| assert abs(ry - 50) <= 2 | |
| assert rscore > 0.5 | |
| def test_multiscale_template_match_cancellation(): | |
| from src.engines import multiscale_template_match | |
| from src.exceptions import CancellationState, DetectionCancelledException | |
| drawing = np.ones((100, 100), dtype=np.uint8) * 255 | |
| tmpl = np.ones((10, 10), dtype=np.uint8) * 255 | |
| state = CancellationState() | |
| state.cancel() # Immediately cancel | |
| with pytest.raises(DetectionCancelledException): | |
| multiscale_template_match( | |
| drawing, tmpl, scale_range=(0.8, 1.2), scale_step=0.1, cancellation_state=state | |
| ) | |