5.30. 範本比對¶
目前為止所介紹的偵測器回答的是關於單一影格內容的問題:色塊在哪裡、線條往哪裡走、印製的條碼說了什麼。另一類問題則是將一張影像與另一張影像相互比較。所擷取影格中的這塊區域,看起來像不像我在校正時所儲存的參考小圖? 比對方法回答的正是這個問題。
色調與統計分析一節為相關問題引入了 get_similarity()——這兩張相同大小的影像整體上有多相似?——並以 SSIM 作為底層度量。剩下的比對問題則是定位問題:不是「這兩張影像有多相似」,而是「那張較小的小圖出現在這張較大影像的哪個位置?」回答定位問題的正確工具是範本比對。
5.30.1. 基本呼叫¶
find_template() 會在所擷取的影格中尋找一張小型範本影像首次出現的位置。其實作使用正規化互相關(NCC):範本在影格上滑動,每個位置的比對分數由範本像素與其下方影格像素之間的相關性計算而得(會針對局部均值與變異數進行正規化,使增益變化不致干擾比對),而第一個分數超過 threshold 的位置會以邊界框的形式回傳:
template = image.Image("/sdcard/template.bmp", copy_to_fb=False)
template.to_grayscale()
match = img.find_template(template, threshold=0.7,
search=image.SEARCH_DS)
if match is not None:
img.draw_rectangle(match, color=(255, 0, 0))
此方法只適用於灰階影像。請以灰階擷取(對於任何不具色彩感測器的相機而言皆為自然選擇),或在呼叫前透過 to_grayscale() 就地轉換。從磁碟載入的範本亦同:彩色範本會以相同方法轉換,其結果正是比對器所預期的。
threshold 是介於 0.0 至 1.0 之間的浮點數。1.0 要求逐像素完全相符(在實際擷取的影像中絕不會發生),0.0 則接受任何結果,而 0.6 至 0.8 之間的值涵蓋了常見情況:範本在相似光照下擷取,且場景未發生劇烈變化。提高閾值可抑制誤判;降低閾值則可接受較雜訊的比對,但代價是更多虛假命中。
5.30.2. 搜尋策略¶
search 用於在兩種策略之間做選擇。image.SEARCH_EX 是窮舉搜尋:範本逐一滑過影格中每個間隔 step 像素的位置,並回傳第一個超過閾值的命中。image.SEARCH_DS 是菱形搜尋:比對器先進行粗略取樣,再圍繞最佳分數進行細化,速度大幅提升,但若粗略階段恰好落在某個勝過全域最大值的局部最大值附近,則可能錯過真正的比對。對於範本定義明確且不易混淆的即時管線而言,SEARCH_DS 是恰當的預設值;對於漏失成本高於掃描變慢成本的一次性校正而言,SEARCH_EX 則較為安全。
step 控制窮舉階段中的像素跳過量(菱形搜尋自行管理其步進量)。較大的 step 值可加快掃描,但代價是次像素精度。roi 將搜尋限制在影格的某個區域內,既縮小比對器所考量的範圍,又減少運算量。
回傳值是一個 (x, y, w, h) 邊界框元組,標示最佳比對位置;若無任何位置超過閾值則回傳 None。此邊界框可直接代入 draw_rectangle() 或 crop(),供下一階段處理使用。
5.30.3. 縮放與旋轉的陷阱¶
範本比對的經典陷阱在於縮放與旋轉的敏感性。比對器逐像素將範本與影格相互比較;在某一距離擷取的範本無法比對在不同距離擷取的同一物體,而正面擷取的範本也無法比對自偏軸視角觀看的同一物體。即使物體在人眼看來顯而易見,閾值仍會悄悄降至比對水準以下,使該方法回傳 None。
對於簡單情況,存在幾種變通做法。應用程式可在不同縮放比例下擷取多張範本,並依序對每張執行 find_template(),接受第一個超過閾值者;其成本隨範本數量而增加。應用程式也可在比對執行前,先以 rotation_corr() 或極座標變換(幾何變換)對影格進行預處理,以消除造成問題的旋轉;經比對的範本仍須符合校正後的幾何形狀。
一種適用於品保檢驗管線的實用慣用法,是將範本比對器與色調及統計分析一節所引入的相似度評分器搭配使用:find_template() 在所擷取的影格中定位部件,所回傳的邊界框被裁切出來,並針對參考小圖傳遞給 get_similarity()。範本比對步驟決定部件在哪裡;相似度評分步驟決定部件是否合格。這兩個步驟每一影格皆會執行,mean 上的閾值即為合格/不合格的判定門檻,而繪回影格中的比對邊界框則是操作員所觀看的 IDE 預覽。