硬幣系列三 | 硬幣自動分類的一個論文復現
書接上回,經過自動檢測和裁剪之後,已經有很多切割整齊的硬幣照片了,再來看看相似檢測的方法。
一開始的思路極其簡單,既然前面做了邊緣提取,而對於硬幣的種類,人眼最關心的也是和輪廓、花紋相關的資訊。那就利用邊緣資訊來檢測,怎麼檢測呢?
拿待檢測的圖的邊緣,和所有標準圖的邊緣一個一個疊起來比較,和誰重合的面積越大,就和誰最像。雖然這個思路簡單到小學二年級的同學都會笑出聲,但這個方法在使用得當的時候,準確率可以高達40%(不行還是太弱了)
設待檢測的影象的邊緣資訊為,n個標準影象的邊緣資訊為,這裡要求和影象尺寸均一致。這樣,與待測影象最接近的標準影象為。
說人話:就是看看標準圖和測試圖重合區域的面積,哪個面積越接近測試影象的面積,就是最相像的標準影象(為了防止混亂,這裡強調一下,“面積”指的是圖片裡白色區域的面積,或者說白色畫素塊的數量。這裡涉及的圖都是隻有黑色和白色兩個顏色的)。
老潘用手工方式標註了200個硬幣配對,在這上面做點簡單測試,這種方法準確率只有8%,經過觀察大部分硬幣圖片都被識別成了這兩個
這時候我有一個猜測,如果某個標準影象非常極端的全部為白色,那麼待測影象和標準影象的重合範圍肯定是非常大的(重合範圍就是100%的待測影象),所以上面的方法需要改一下。必須同時考慮測試圖和標準圖。這裡將的判別方法改寫為
說人話,就是看看標準圖測試圖重合面積、測試圖面積以及標準圖的面積情況,只有同時和兩者都接近的才能被選作相似的圖片配對。
這個方法的準確率迅猛提升到了40%,但是該方法有一個致命的bug,就是一旦硬幣的角度稍有旋轉(實際這個情況卻很容易發生),識別率顯然會受到影響。而且資料量增大也會使準確率和速度逐漸降低。速度降低很顯然,至於準確率下降,老潘在測試的時候確實發現有這個現象,如果想想為什麼這樣,個人猜測
所以有沒有哪種方法可以在旋轉或者光照發生變化時,對同一個硬幣圖案的描述比較穩定,對不同硬幣的描述差別較大呢?顯然這馬上使我們想到了使用LBP方法來嘗試。LBP(Local Binary Patterns)
演算法本身並不困難,總體思路如圖
首先把硬幣圖片切割好(這我們早已做好了),然後求硬幣的梯度圖Gradient Magnitudes(公式2),之後用蜘蛛網狀分割槽,分幾個環和幾個扇(取值多少屬於調參時要考慮的,呼喚調參俠),對每個小塊裡的值,都有特別的計算方法(一個是求區域裡的均值,一個是公式4),再變換到intra RBP和inter RBP(公式6和7)。看每一個環,他的各個扇區一圈就代表了一個二值模式,上面的圓有3圈,所以有3個二值模式,下面的圓同理。
對於每個二值模式編碼編成多少?在同一個作者的《Rotation andflipping robust region binary patterns for video copy detection》[2]裡介紹了。對於所有可以通過翻轉和旋轉重合的模式,就算為一組,如圖
比如說RFR是②的那一排,一圈上只有一個黑點的,都是一樣的模式(可以旋轉和翻轉互相重合)所以作為一組。這裡面的組順序沒什麼特別要求,只要相同模式歸為一組並且編個號就行。
對於評判兩類模式之間的距離,作者用的方法是,計算兩個組之間每組所有模式兩兩的漢明距離(Hamming Distance),取最小的為兩類之間距離。
思路已經捋清楚了,我們甚至可以當堂完成這個作業。這一次老潘用了MATLAB,沒有用python(不知道為什麼涉及到這種純影象的問題我更習慣先開啟MATLAB)。寫程式很快,一晚上就可以寫完甚至不需要熬夜,但是優化這個東西卻耗了老潘一下午。
先來簡單的。第一步求影象的梯度影象,太簡單了不解釋。(我突然覺得這裡也可以優化的)(我寫推送的時候意識到好像可以用sobel運算元)
M = zeros(I_size - 2);
for x = 2:I_size - 1
for y = 2:I_size - 1
M(x-1, y-1) = sqrt((I(x+1, y) - I(x-1, y))^2 + (I(x, y+1) - I(x,y-1))^2);
end
end
然後做影象的扇區,求出每個扇區下的平均值。這裡稍稍有點繞,我選擇先計算環,再計算角度,再取交集,就像下圖所示。
r = (I_size - 2) / 2;
center_point = r;
axis_x = zeros(I_size - 2);
for row = 1:I_size - 2
axis_x(row,:) = [1:I_size - 2];
end
axis_y = zeros(I_size - 2);
for column = 1:I_size - 2
axis_y(:,column) = [1:I_size - 2];
end
condition_r = abs(sqrt((axis_x-center_point).^2+ (axis_y-center_point).^2));
condition_angle =atan2(axis_y-center_point, axis_x-center_point)/pi*180+180;
pic_num = 1;
m = zeros(rings, sub_regions);
for ring = 1:rings
for region = 1:sub_regions
area_r = condition_r < ring*(r/rings) & condition_r >=(ring-1)*(r/rings);
area_angle = condition_angle < region*(360/sub_regions) &condition_angle >= (region-1)*(360/sub_regions);
area_need = area_r .* area_angle;
area_gradient = M .* area_need;
插個嘴做一些解釋:這裡的area_r和area_angle相當於蒙版,我們只要直接和圖片點乘就可以選出要的區域(1乘一個數還是這個數,0乘一個數一直是0)
取兩個蒙版的交集也是同理,直接互相點乘即可,得到的矩陣就是交集area_need。
註釋掉的地方可以生成一個動態的GIF圖片,展示了每圈每個扇區下的梯度影象情況。
之後計算每個區域下的均值,存下來即可。
% % save a gif to observe
% imshow(area_gradient, [], 'border','tight', 'initialmagnification','fit');
% F=getframe(gcf);
% I=frame2im(F);
% [I,map]=rgb2ind(I,256);
% if pic_num == 1
% imwrite(I,map,'RFR_log/area.gif','gif','Loopcount',inf,'DelayTime',0.1);
% else
% imwrite(I,map,'RFR_log/area.gif','gif','WriteMode','append','DelayTime',0.1);
% end
% pic_num = pic_num + 1;
m(ring, region) = sum(area_gradient(:)) / sum(area_need(:));
end
end
之後的公式3至7的計算略,沒什麼好解釋的。貼出來也只會令人頭暈。
好了,就差構造一個查詢表IND和一個距離矩陣了,但是具體做的時候就沒那麼簡單了。
1
先說構造IND,這個表用來把一個010101這樣的模式換成他所在類的號碼。因為組比較多,所以用一次算一次比較慢,不如用空間換時間。於是第一天晚上掛機一宿,發現這個表還沒羅列好。遂優化。一開始的想法是用一個表格當做查詢表,行數就是類別號,每行儲存這類的二值模式0101碼。但是問題一,表裡會有很多冗餘資料,比如全0的這類,由於陣列尺寸必須一樣,需要把後面空缺的都填滿。就存了20個全0的模式。問題二,時間很慢而且會越來越慢。因為每一個模式都要去表裡查詢是否出現過,表越大查的越慢。
於是想了一招,採用Map格式儲存,首先要宣告一下變數
IND = containers.Map;
代表我們要用Map儲存IND表格,之後,為了提高查詢效率,不用類號做索引,用二值模式做索引,這樣一來可以很快查到表裡有沒有出現過這個二值模式,二來在使用的時候,把圖的二值模式轉成類別號也會快。這時候遍歷所有的二值模式,對於這一組二值模式,如果有一個沒在之前出現過,那就把這一組全存下,並且給一個統一的組號(這一組是用某一個二值模式經過迴圈移位和翻轉出來的所有結果)。如果在之前出現過,就代表這一組的二值模式都已經在這個表裡有過了(通過旋轉和移位終究會變成一樣的)。判斷和儲存的方法為
if ~isKey(IND, dec2bin(CP_FP_dec(1),sub_regions))
for index_map = 1:length
IND(dec2bin(CP_FP_dec(index_map), sub_regions)) = ind;
end
ind = ind + 1;
end
(只記錄了判斷鍵值是否出現過,整體程式碼見“閱讀原文”)
於是一宿未完的問題,10分鐘就可以解決了。其中5分鐘用來把資料儲存到磁碟上用來下次直接查詢該換固態硬碟了。
2
下一個問題是計算兩類之間的距離,原論文仍然是做了一個矩陣,可以直接在裡面查兩類的距離,但是我做的時候發現這個矩陣太大,記憶體會爆(計算一下這個矩陣只佔729Mb,MATLAB居然放不下)。咱也不知道作者用了什麼黑科技(也許是轉了C語言),我想了想,乾脆在判斷圖片的時候直接計算,也差不了多長時間。
還是挺佔時間的,實際用的時候發現只判斷兩個圖片就要將近半分鐘。這要是再一個一個比對過去,天荒地老。遂優化。最開始就是粗暴的兩個for迴圈,然後一個一個的取兩個類別號,然後計算。發現不行,有點慢,於是改用矩陣計算。先做兩個類別號(其實是兩組,一個圖片會有一組類別號)的排列組合矩陣
% reference:https://www.ilovematlab.cn/thread-321138-1-1.html
[m, n] = meshgrid(RFR_i_list_dec,RFR_j_list_dec');
[res(:,1), res(:,2)] = deal(reshape(m, [],1), reshape(n, [], 1));
然後計算這個矩陣按行的漢明距離,取這個矩陣的min就是兩個類的距離。
DH = dec2bin(bitxor(res(:,1), res(:,2)));
[length, ~] = size(DH);
DH2 = uint8(zeros(length, 1));
for i = 1:length
DH2(i) = sum(DH(i,:)=='1');
end
min_Hamming = min(DH2);
之後發現還是很佔時間,偶然瞥到,在每一輪迴圈裡都有這麼個操作
key = keys(IND);
value = uint32(cell2mat(values(IND)));
把類號和二值模式從Map格式裡面拿出來,這個拿的動作很耗時。所以就一開始取出,直接作為引數傳給後面的一系列函式。原本兩個圖片對比時間要大概半分鐘,現在只需半秒。速度提升了60倍。
不過速度還是比較慢,不知道那個線上識別硬幣的網站用的到底是什麼方法。如果選擇做出來距離對照表的話,拿空間換時間,應該速度就會很快了。但是我估算目前的小需求下,做查詢表的時間和直接做計算的時間,好像做表不是太划算。
話說回來,用這個方法的檢測準確率可以達到45.5%,遠不及論文中所達到的準確率(89.1%)。我使用了和作者一致的引數,但是資料集不一樣。作者使用的是遠古版本的MUSCLE-CIS資料集,這是在2006年辦的一個硬幣識別比賽用的資料集,原連結已經失效,在網上也很難搜尋到相關的資料,只有在偶爾一些論文裡有零星展示,在論文[3]裡給了兩個資料集內的圖片。
可以看到這個影象和直接用手機拍的畫面差別挺大的,這個花紋的邊緣非常清晰,有可能是用了特殊的光源和相機拍攝的。在這種優良乾淨的資料上,我相信小學生方法也能有不錯的效果。但是在具體生活場景上,如何在光照不佳,資料量小的情況下提高檢測效率,還是一個有待研究的問題。
經過簡單的進一步調研,在文章[4]中提到,MUSCLE-CIS解析度低並且經過了很強的預處理,實際場景很難得到這樣的圖片。但是硬幣資料集還有很多,例如文章中給出的這個例子,可以看到實際生活中主要面對的還是後面這幾類影象。這個文章著眼於提取硬幣表面的文字,更深刻的分析了硬幣識別裡面的各種技術問題,而且作者他們也自己建立了一個數據集。論文線上網址:
https://www.frontiersin.org/articles/10.3389/fict.2017.00009/full
(這個作者也研究過硬幣分類的問題,用的貌似是類似SIFT那種方法,看起來好像很吊的樣子,這篇文章[5]的方法作為作業下節課找同學上臺講解)
這次老潘用的自建資料集也會放在GitHub上,想研究的同學可以點選閱讀原文拿去玩一玩。
參考文獻:
[1] Kim S, Lee S H, Ro Y M, et al.Image-based coin recognition using rotation-invariant region binary patternsbased on gradient magnitudes[J]. Journal of Visual Communication and Image Representation, 2015: 217-223. [2] Kim S, Lee S H, Ro Y M, et al. Rotationand flipping robust region binary patterns for video copy detection[J]. Journalof Visual Communication and Image Representation, 2014, 25(2): 373-383. [3] Zaharieva M, Hubermoerk R, Noelle M, etal. On ancient coin classification[C]. ieee virtual reality conference, 2007:55-62. [4] Pan X, Tougne L. A New Database of Digits Extracted from Coins with Hard-to-Segment Foreground for Optical CharacterRecognition Evaluation[J]. Frontiers in ICT, 2017. [5] Pan X, Puritat K, Tougne L, et al. ANew Coin Segmentation and Graph-Based Identification Method for Numismatic Application[C]. international symposium on visual computing, 2014: 185-195.
微信掃一掃
關注老潘的公眾號,第一時間獲取新文章