"""
blackhat
案A: Black-hat 中心型の線検出
Black-hat 変換で背景より暗い構造を直接抽出し,
固定閾値 + 距離変換 + 行ごと中心抽出で検出する
"""
import cv2
import numpy as np
from pc.vision.line_detector import ImageParams, LineDetectResult
from pc.vision.line_detector import fit_row_centers
from pc.vision.morphology import (
apply_dist_mask,
apply_iso_closing,
apply_width_filter,
)
def detect_blackhat(
frame: np.ndarray, params: ImageParams,
) -> LineDetectResult:
"""案A: Black-hat 中心型"""
# 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,
)
# ガウシアンブラー
blur_k = params.blur_size | 1
blurred = cv2.GaussianBlur(
blackhat, (blur_k, blur_k), 0,
)
# 固定閾値(Black-hat 後は線が白)
_, binary = cv2.threshold(
blurred, params.binary_thresh, 255,
cv2.THRESH_BINARY,
)
# 等方クロージング + 距離変換マスク + 幅フィルタ
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,
)
# 行ごと中心抽出 + フィッティング
return fit_row_centers(
binary, params.min_line_width,
median_ksize=params.median_ksize,
neighbor_thresh=params.neighbor_thresh,
residual_thresh=params.residual_thresh,
)