这几天做了一道题目,要求在 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 进制进行比较,而是直接对二进制串做的对比,完全相同的并不多,所以不同的字符在十个之内我都算成相似的,再进行进一步的比较。