基於NCC的多目標多角度快速模板匹配演算法詳見:https://www.cnblogs.com/Imageshop/p/14559685.html
乘著研究NCC的熱情,順便也研究了下基於邊緣梯度的匹配。
基於邊緣梯度方面的匹配,最為出名的莫過於CodeProject上一篇多年前的印度小哥的文章,連結為:Edge Based Template Matching。
這篇文章的核心計算公式為:
(1)
在國內的中文有關網站上卻常常看到下述公式(分母第二項不同),這明顯是個錯誤的式子,也不知道哪位是原始創造者。
這個核心計算式和基於NCC的看上去相似又有著很多不同。注意式子中的大寫字母G表示影像的梯度資訊,這個是可正亦可負的。即計算式已經脫離原有的畫素資訊,而使用了梯度相關資訊,常用的獲取X和Y方向梯度的方式有:
即Sobel邊緣檢測運算元。
在印度小哥的文章裡,採用了Canny檢測來檢測出邊緣,然後只對模板圖和搜尋圖中對應的邊緣位置計算上述得分公式(以模板圖中的邊緣處為依據), 這樣起到減少取樣點,提高速度的作用。
我實際測試這種方法如果直接對模板和搜尋圖做,很多情況下是可以的,但是還是存在著一些問題,主要有:
1、雖然Canny的使用減少了很多計算量,但是他完全剔除了其他弱邊緣處的資訊,就好像把考試中那些不及格的學生都定型為差生一樣,是不科學的。這些弱邊緣在一定程度上也有著相當的資訊量。
2、Canny本身是有著很多引數來控制最終的效果的,不是一個固定的引數對每一副影像都能獲取穩定的效果,因此,這就很難成為一個穩定的演算法了。
3、如果採用了金字塔等技術,在金字塔層數增加時,Canny所對應的邊緣會越來越不穩定,這會影響最終的精度。
所以,我覺得不應該使用Canny獲其他的類似技術實現這個過程,我的想法還是對全圖實現上述公式的計算。
但是,這又會遇到幾個問題。
1、計算量飆升,這個可以通過金字塔的技術來解決。
2、我們仔細的觀察公式(1),如果做一個全域性的匹配計算,在計算過程中,必然會遇到不少地方的X和Y方向的梯度都為0或者很小,而且這種畫素佔的比例還相當高,畢竟影像中真正屬於邊緣的地方很少。那麼這樣的一個事實就回到導致很多累加項的值為0或很小(X和Y梯度都為0時,式子的分母為0,程式需要做判斷,但輸出的結果必然也會是0),這樣整體累加後再求平均數我們將獲得一個很小的得分(哪怕和模板圖一模一樣的地方)。
一種改進的方法就是把模板圖的整體的幅值資訊作為一個因子放入到上述計算公式的分母中,這樣,模板圖中梯度較小的位置,對整體的幅值貢獻就小,從而不會對最後的得分造成影響。
在實際的編碼中,我們還會遇到很多的其他方面的困難,列舉一些如下:
1、對於角度的檢測,類似的,我們也建立多個離散的模板,我們需要旋轉模板,然後計算模板的邊緣梯度,但是,旋轉本身產生了新的邊緣,而且是強邊緣,如下所示:
如果把這邊緣帶入式中計算,非常明顯不會得到可靠的結果,我們需要把這個邊緣剔除。
2、無論採用何種邊緣梯度檢測運算元,最小的都會涉及到3*3的區域性範圍,那麼對於未旋轉或者旋轉後的模板圖,都存在一個明顯問題,最外一圈畫素的梯度如何處理,如果使用重複邊緣畫素的方式,那麼就會獲得一個較小的梯度,但是實際在在搜尋圖中是不存在這個問題的,只要模板不在搜尋圖的邊緣處。因此,如果這樣處理,哪怕模板就是從搜尋圖中直接扣取出來的,依據(1)式計算出的結果也不會等於1,而是小於1。
如何解決這個問題,我目前想到的也只有忽略最外圈的梯度值,即他們不參與相似性計算。這樣就要求在做模板圖時,需要可以在實際需要的模板的基礎上,中心對稱的長和寬每邊各增加一個畫素。但是,這樣實際上還是沒有完美解決問題,因為當有金字塔存在時,這可以增加的1個畫素經過下采樣後已經沒有一個畫素了,還是有點頭大,暫時沒有想到什麼好辦法。、
IM_Rotate(Template, Rotate, RTI.Mask, Angle, 1, Amount); // 旋轉影像,獲取Mask值
IM_Edge_Erode_3X3(RTI.Mask, RTI.Mask);
想到的另外一個方法就是旋轉時不是旋轉影像然後再計算梯度,而是直接旋轉X和Y方向的梯度,但是新的難處是梯度值是有正有負的,這種資料的旋轉在使用雙線性插值時,由於四個取樣點的極性不同,是否能直接處理呢,我感覺好像有問題,比如四個數,2正2負,有可能插值後結果就為0了。
目前,採用了一些非常規的手段,還是基本有一定的成果了,一些不是特別情況的圖,使用基於邊緣梯度的方式也能獲取到較為準確的結果,比如基於NCC那個幾個測試圖,也是可以的。
進一步測試表明,這個演算法相對於NCC,在某些情況下確實是有更靠譜的識別結果,而且是對強邊緣的識別效果很不錯。
基於NCC的結果 基於邊緣梯度的結果
由上面的測試圖也可看出,兩種演算法對於光照的影響都有一定的抵抗能力。
再看一個比較有意思的圖:
這裡的MaxOverlap設定為0.7,MinScore也設定為0.7.
對於下面這種複雜的邊緣重疊的物件也有一定的免疫力。
基於NCC的結果 基於邊緣梯度的結果
上述測試圖,基於邊緣的成功的鎖定了20個待檢測的目標,而基於NCC的則丟失了一個,當然這並不是說基於NCC的就比基於邊緣的差。
本演算法待進一步改進後可能會整合到國產視覺軟體Malcon中,詳情請看 中國的Malcon跟德國的Halcon的相比的優缺點 。
Malcon官方部落格:https://www.cnblogs.com/Malcon
或者點選: https://blog.csdn.net/lindrs/article/details/114113280?spm=1001.2014.3001.5502
目前可通過下面連結獲取一個視覺化的Demo: https://files.cnblogs.com/files/Imageshop/TemplateMatching.rar
同樣宣告,這個Demo本身是有Bug的(不影響測試使用),請不要將其直接應用到工業環境中,以免造成不必要的損失。
如果您覺得本博文對您有所幫助,也可慷慨解囊。