傳統的基於邊緣資訊的模板匹配其計算得分的公式如下所示:
這是一個累加公式,對於原圖的每一個有效畫素位置,以其為中心或左上角起點(影像中的座標一般是X方向從左向右,Y方向從上到下),在原圖中覆蓋模板寬度和高度大小的範圍內,按照模板有效特徵點的位置和梯度資訊,逐點和原圖對應位置的梯度資訊進行上述累加符號內的計算,在進行完累加後,再次求平均值得到有效畫素位置的實際得分。
我們拋開累加的過程,單獨看看逐點的計算式。
為了表述和繪圖方便,我們把上述公式用下面的符號簡化下:
即x1和y1模板圖的X和Y方向x2和y2梯度,x2和y2原圖對應的X和Y方向梯度。
我們把x1、y1、x2、y2繪製到一個二維平面圖中,如下圖所示:
上述圖中,紅色線條表示x1和y1對應的向量,其長度用a表示,綠色線條表示x2和y2對應的向量,其長度用b表示。兩個向量之間的夾角用θ表示。
另外,α表示紅色向量和X軸之間的夾角,β表示綠色向量和Y軸之間的夾角。c表示紅色和綠色向量終點之間的長度。
根據數學中的餘弦定理,a、b、c以及θ之間有如下關係:
再根據勾股定理,我們進一步展開有:
比較公式(4)和公式(3),我們可以看到兩者的結果完全相同,因此,求每個點的得分也等同於求對應的梯度向量的夾角餘弦。
注意到,要獲取θ,我們可以先獲得α和β值,然後透過
Θ = β - α
獲取,而α和β可以使用atan2函式獲取。
通常,模板的資訊都是離線計算的,因此,每個特徵點的α(模板)值可以提前計算。但是β值需要透過類似於atan2之類的函式實時計算。
得到Θ值後,可以直接使用cos函式計算餘弦值,即得到該點的得分。
實際上,無論是atan2函式也好,還是cos函式也好,其內部都是由很多浮點指令組合而成的,非常耗時,不利於程式的實現和效果。
這裡提出一個加速的方案,我們稱之為十六角度量化的夾角餘弦匹配,她的核心還是基於資訊理論中的夏農取樣定理。
我們先說一個簡單的事情。
在我們的匹配過程中,總得分是由m個特徵點各自得分累加後求平均值獲取的,因此,如果各自的得分有小幅度的偏差,對總得分的影響應該很小,這樣,我們可以先這樣想,如果我們把0到360角度分為360等份(cos是以360度一個週期震動的函式),即每等份的差距是1度,然後在計算α和β時,也把得到的角度四捨五入到最接近的等份,這樣,我們可以提前建立起一個360*360的查詢表,輸入α和β的值,就能查到對應cos值了。
這種查表的精度其實還是相當高的,但是這個表太大,查表時的cachemiss相對來說有點嚴重。
當我們以22.5度為每等份的差距時,可以把360度量化為16等份,此時,對應的表只有16*16=256個元素,查表的效率就非常高了,不過精度損失相對來說就嚴重一些,但是,實際的驗證表面這種損失對匹配的結果影響是完全在可接受範圍內的。
這個構成相當於把0到22.5度的向量就直接標記為索引0,22.5到45之間的角度標為1,45到67.5之間的角度標為2,67.5到90度之間的角度標為3,依次類推。
以22.5為間距進行標記的過程的另外一個優勢是,可以不用先使用耗時的atan2函式得到角度後再來計算索引值,而是可以根據有關x1和y1(影像資料中x1和y1通常是整數)的數值關係做直接的判斷,這種判斷也是整形的計算,效率相對來說比較高,具體的可以再程式碼裡看到。
那麼表格是如何建立的呢,比如α對應的索引是2,β對應的索引是4,那麼表中的內容是什麼呢?這個也很簡單,就是直接使用
cos(4 * 22.5 - 2 * 22.5) = 0.707117987607051 得到。
為了進一步提高速度,儘量減少浮點的計算,我們可以把這個表的得分設計為整形值,比如將表的得分統一乘以一個較大的整數,而後捨去成績得到的小數部分,僅僅保留整數部分,這樣表格資料就可以完全用整數來表示了,這個時候,只需要在最後計算得分的時候統一除以剛剛放大的整數就可以了,比如剛才的浮點就可以用下面的整數代替:
0.707117987607051 * 63 = 44.5484332192442 四捨五入取整45。
再仔細的考慮下,剛剛建立的是二維表,實際上,這個過程還可以使用一維表進行,因為如果把0到360度角度量化為16個等份,那麼模版和原圖匹配時的不同的角度差異值只會有31種可能(-15、-14、-13..........0、1、2.......13、14、15),每種取值都有固定的得分,因此,只需要構建一個31個元素的表格,然後根據差異的索引在查表就可以了。注意考慮到索引必須為正值,這個差異的索引應該等於β - α+15。、
使用一維表的方案還可以進一步進行推廣。因為二維表必須考慮表的維度,他和量化的等份數成平方關係,太大了這個表的元素太多,一方面佔用記憶體,另外還存在較為嚴重的cachemiss,但是如果僅僅是一維表,則這方面的顧慮就少了很多,比如我們就以1度為劃分間隔,把0到360度劃分為360份,這樣需要的一維表的大小為719個元素,這個大小無論從記憶體還是cachemiss角度來考慮都是可以接受的。這樣做帶來的好處就是計算出的每個位置的得分值和真正的得分是更為接近的。
當然,具體使用多少個等份量化,還和其他一些因素有關,比如使用8/16/32角度量化,在PC上可以使用某些特殊指令集加速查表的過程,而其他的角度則不行。使用二維表有的時候更易處理一些特殊情況,比如原圖中不需要參與匹配的一些特殊點。而使用一維表可能需要使用分支語句處理,從來帶來效能損傷。
關於餘弦相似性,正好昨天部落格園也有一篇文章有涉及,大家可以參考下:十分鐘搞懂機器學習中的餘弦相似性
如果想時刻關注本人的最新文章,也可關注公眾號: