Newer
Older
RobotCar / src / common / vision / detectors / robust.py
"""
robust
案C: 最高ロバスト型の線検出
Black-hat + 適応的閾値の二重正規化に加え,
RANSAC で外れ値を除去する最もロバストな構成
"""

import cv2
import numpy as np

from common.vision.line_detector import (
    ImageParams,
    LineDetectResult,
    fit_row_centers,
)
from common.vision.morphology import (
    apply_dist_mask,
    apply_iso_closing,
    apply_width_filter,
)


def detect_robust(
    frame: np.ndarray, params: ImageParams,
) -> LineDetectResult:
    """案C: 最高ロバスト型"""
    # Black-hat 変換
    bh_k = params.blackhat_ksize | 1
    bh_kernel = cv2.getStructuringElement(
        cv2.MORPH_ELLIPSE, (bh_k, bh_k),
    )
    blackhat = cv2.morphologyEx(
        frame, cv2.MORPH_BLACKHAT, bh_kernel,
    )

    # 適応的閾値(BINARY: Black-hat 後は線が白)
    block = max(params.adaptive_block | 1, 3)
    binary = cv2.adaptiveThreshold(
        blackhat, 255,
        cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
        cv2.THRESH_BINARY,
        block, -params.adaptive_c,
    )

    # 等方クロージング + 距離変換マスク + 幅フィルタ
    binary = apply_iso_closing(
        binary, params.iso_close_size,
    )
    binary = apply_dist_mask(
        binary, params.dist_thresh,
    )
    if params.width_near > 0 and params.width_far > 0:
        binary = apply_width_filter(
            binary,
            params.width_near,
            params.width_far,
            params.width_tolerance,
        )

    # 行ごと中央値抽出 + RANSAC フィッティング
    return fit_row_centers(
        binary, params.min_line_width,
        use_median=True,
        ransac_thresh=params.ransac_thresh,
        ransac_iter=params.ransac_iter,
        median_ksize=params.median_ksize,
        neighbor_thresh=params.neighbor_thresh,
        residual_thresh=params.residual_thresh,
    )