diff --git a/src/common/vision/detectors/dual_norm.py b/src/common/vision/detectors/dual_norm.py index c772ebe..9bd92af 100644 --- a/src/common/vision/detectors/dual_norm.py +++ b/src/common/vision/detectors/dual_norm.py @@ -5,6 +5,8 @@ 適応的閾値で局所ムラにも対応する二重防壁構成 """ +import time + import cv2 import numpy as np @@ -20,12 +22,56 @@ apply_width_filter, ) +# 内訳計測用の累積値 +_profile_count: int = 0 +_profile_sums: dict[str, float] = {} +_profile_start: float = 0.0 +_PROFILE_INTERVAL: float = 3.0 + + +def _profile_reset() -> None: + """計測値をリセットする""" + global _profile_count, _profile_sums, _profile_start + _profile_count = 0 + _profile_sums = {} + _profile_start = time.time() + + +def _profile_record(label: str, elapsed: float) -> None: + """計測値を記録する""" + _profile_sums[label] = ( + _profile_sums.get(label, 0.0) + elapsed + ) + + +def _profile_print() -> None: + """計測結果を出力する""" + global _profile_count, _profile_start + if _profile_count == 0: + return + elapsed = time.time() - _profile_start + if elapsed < _PROFILE_INTERVAL: + return + parts = [] + for label, total in _profile_sums.items(): + avg = total / _profile_count * 1000.0 + parts.append(f"{label}={avg:.1f}ms") + print(f"Pi: dual_norm内訳({_profile_count}f) " + + " ".join(parts)) + _profile_reset() + def detect_dual_norm( frame: np.ndarray, params: ImageParams, ) -> LineDetectResult: """案B: 二重正規化型""" + global _profile_count + + if _profile_count == 0 and not _profile_sums: + _profile_reset() + # 背景除算正規化 + t0 = time.time() bg_k = params.bg_blur_ksize | 1 bg = cv2.GaussianBlur( frame, (bg_k, bg_k), 0, @@ -37,6 +83,8 @@ normalized = np.clip( normalized, 0, 255, ).astype(np.uint8) + t1 = time.time() + _profile_record("背景除算", t1 - t0) # 適応的閾値(ガウシアン,BINARY_INV) block = max(params.adaptive_block | 1, 3) @@ -54,6 +102,8 @@ 255, cv2.THRESH_BINARY_INV, ) binary = cv2.bitwise_and(binary, global_mask) + t2 = time.time() + _profile_record("閾値処理", t2 - t1) # 段階クロージング or 等方クロージング if params.stage_min_area > 0: @@ -79,11 +129,20 @@ params.width_far, params.width_tolerance, ) + t3 = time.time() + _profile_record("後処理", t3 - t2) # 行ごと中心抽出 + フィッティング - return fit_row_centers( + result = fit_row_centers( binary, params.min_line_width, median_ksize=params.median_ksize, neighbor_thresh=params.neighbor_thresh, residual_thresh=params.residual_thresh, ) + t4 = time.time() + _profile_record("fitting", t4 - t3) + + _profile_count += 1 + _profile_print() + + return result