fullseye

照明むら・ハイライト・遮蔽に強いテンプレート照合

できること

明るさの値ではなく変化の向きを符号にして比べる照合の族(codematch、6 op)。学習した特徴を使わず、式と閾値だけで、 どこまで残りどこで壊れるかを自分で言えます。

平坦なテンプレート(符号が雑音で決まる)には値を返さず ValueError。NCC は同じテンプレートでも高い相関でどこかを返します (PoC: 空を切った 11 枚で NCC は 10 枚を外し、相関の中央値は 0.82。符号系 3 種の誤答は 0)。

What it does

Six ops (codematch) match on the direction of brightness change instead of its value: orientation code matching (OCM), increment sign correlation (ISC, exactly invariant to any strictly monotone brightness map), the selective correlation coefficient (SCC, with the extended mask) and the Radial Reach Filter for background comparison. Templates whose codes cannot fix a position are refused with ValueError, where NCC still returns a confident wrong answer. On real CC0 photographs with 40 templates per level, NCC drops below half its hits at 10 % occlusion and 6 % saturated highlight; OCM and ISC hold until 63-67 % occlusion and 44-53 % highlight. None of the four is rotation invariant (half the hits are lost at 7-9 degrees).

向くところ / 向かないところ

推奨パイプライン

isc_match → ocm_match

まず isc_match で探し(単調な明るさの変化に厳密に不変、最も速い)、margin(次点との差)が小さい場面は ocm_match で 確かめる。背景画像があるなら、物の有無の判定は radial_reach_filter で照明の変化と影を切り離す。

代替

scc_match(値の相関を残したいとき。OCM・ISC よりは遮蔽に弱い)、ncc_locate(照明が一様なら最も素直)、 radial_reach_filter(テンプレートではなく背景と比べる)。

限界

回転は探しません(PoC で 4 種とも 7〜9° で当たりが半分を割る)。SCC は符号の合った画素だけを選ぶので、無関係な位置でも相関が 高めに出ます(選択の偏り)。既定では無相関の位置で期待される使用率(基本 1/2、拡張 5/16)+ 4 標準偏差より使用率の低い位置を 採点しません —— これは文献の式には無い、こちらで足した拒否です。平坦な所の多いテンプレートでは正解の位置でも使用率がこの床を 割ることがあります。RRF は背景が平坦な画素(空など)を判定しません(PoC の camera で判定できたのは 65 %)。

実寸校正

座標は画素。閾値は [0, 1] の明るさで書きます(8 ビットの画像なら 255 で割った値)。

最初の 1 本

import numpy as np
from scipy import ndimage
import fullseye as fs

rng = np.random.default_rng(0)
scene = ndimage.gaussian_filter(rng.random((96, 96)), 1.5)
scene = (scene - scene.min()) / (scene.max() - scene.min())
tpl = scene[30:62, 40:72].copy()
lit = scene ** 0.4                       # 露出が変わった
lit[30:46, 40:56] = 1.0                  # テンプレートの 1/4 が飽和
r = fs.ledger.isc_match(lit, tpl)
print(r["row"], r["col"])                # 46 56(テンプレート中心)

裏づけ