這幾天做了一道題目,要求在 5000 張圖片中找出 30 張與樣例相同但經過放大或縮小,高亮或變暗的圖片。
整體思路是把圖片hash成一段指紋,這個指紋和圖片的大小、格式、明暗均無關,只和圖片的內容本身有關。
1.先把彩色圖片轉為灰度圖
如果原本的一個像素點的rgb值為(r1,g1,b1),一個比較簡易的方法轉為灰度圖,
就是 gray1=(r1*299+g1*587+b1*114+500)/1000
那么該像素點的rgb顏色變為(gray1,gray1,gray1)。
而我用的是 Matlab 中的函數 imgray = rgb2gray(imdata);
2.將灰度圖轉化為黑白圖
先計算出該圖的平均灰度,一種比較簡易的做法是把所有像素點的灰度求和平均。 然后對於每個像素點,如果小於平均灰度,則rgb值為(0,0,0),否則為(255,255,255)。
經過這一步,圖片就變成黑白的了。我用的是 Matlab 中函數 lev = graythresh( imdata); 求平均灰度,再 bwimg = im2bw( imdata, lev); 求二值圖。
但這樣的函數對於一些高亮或灰暗的圖片的處理不是特別的好,會使整個圖片呈現全白或全黑的現象。
我對於這些圖片的處理是 自己設定 lev,根據需要設 lev 為 0~1 的值,而不是求圖片的平均值。(找到更好的方法再來更新)。
4 編碼
將之前的二值圖放大或縮小為 8*8 的一個矩陣 imdata = imresize(imdata, [8,8]);
白為 0,黑為 1 整合成 1 個 64 位的二進制, 轉化為 16 進制則是這個圖片的指紋了。
在這里,我並沒有轉換成 16 進制進行比較,而是直接對二進制串做的對比,完全相同的並不多,所以不同的字符在十個之內我都算成相似的,再進行進一步的比較。