明るさの値ではなく変化の向きを符号にして比べる照合の族(codematch、6 op)。学習した特徴を使わず、式と閾値だけで、
どこまで残りどこで壊れるかを自分で言えます。
ocm_match: 方向符号照合(勾配の向きを 16 段に。巡回差の平均。Ullah・Kaneko・Igarashi 2001)。isc_match: 増分符号相関(隣の画素との増分の符号の一致率。Kaneko・Murase・Igarashi 2002)。狭義単調な明るさの変換で点数地図が 1 ビットも変わらない。scc_match: 選択的相関係数(符号の一致した画素の組だけで正規化相関、拡張マスクつき。Kaneko・Satoh・Igarashi 2003)。orientation_code / increment_sign: 符号だけを取り出す口。radial_reach_filter: 背景との比較(8 方向の reach の符号。Satoh・Kaneko・Niwa・Yamamoto 2004)。照明が全体に変わっても、影の内側でも前景にしない。平坦なテンプレート(符号が雑音で決まる)には値を返さず ValueError。NCC は同じテンプレートでも高い相関でどこかを返します
(PoC: 空を切った 11 枚で NCC は 10 枚を外し、相関の中央値は 0.82。符号系 3 種の誤答は 0)。
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).
shape_locate / 形状モデル)。質感の乏しいテンプレート(拒否される)。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 で割った値)。
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(テンプレート中心)
ocm_match / isc_match / scc_match / orientation_code / increment_sign / radial_reach_filterpoc_code_matching_breakdown —— 公開の実写 5 枚(CC0)から切った 40 テンプレートに
遮蔽・ハイライト・減光・回転を段階的に掛けた破綻点の曲線、照明を振る GIF、平坦なテンプレートの拒否、背景との比較。