图像相似算法

  1. 直方图计算法

比如有图像A和图像B,分别计算两幅图像的直方图,HistA,HistB,然后计算两个直方图的归一化相关系数(巴氏距离,直方图相交距离)等等。

这种思想是基于简单的数学上的向量之间的差异来进行图像相似程度的度量,这种方法是目前用的比较多的一种方法,第一,直方图能够很好的归一化,比如通常的256个bin条的。那么两幅分辨率不同的图像可以直接通过计算直方图来计算相似度很方便。而且计算量比较小。

这种方法的缺点:

(1)直方图反映的是图像像素灰度值的概率分布,比如灰度值为200的像素有多少个,但是对于这些像素原来的位置在直方图中并没有体现,所以图像的骨架,也就是图像内部到底存在什么样的物体,形状是什么,每一块的灰度分布式什么样的这些在直方图信息中是被省略掉得。那么造成的一个问题就是,比如一个上黑下白的图像和上白下黑的图像其直方图分布是一模一样的,其相似度为100%。

(2)两幅图像之间的距离度量,采用的是巴氏距离或者归一化相关系数,这种用分析数学向量的方法去分析图像本身就是一个很不好的办法。

(3)就信息量的道理来说,采用一个数值来判断两幅图像的相似程度本身就是一个信息压缩的过程,那么两个256个元素的向量(假定直方图有256个bin条)的距离用一个数值表示那么肯定就会存在不准确性。

1)单通道直方图(灰度直方图)

def calculate(image1, image2):# 灰度直方图算法# 计算单通道的直方图的相似值hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])# 计算直方图的重合度degree = 0for i in range(len(hist1)):if hist1[i] != hist2[i]:degree = degree + \(1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))else:degree = degree + 1degree = degree / len(hist1)return degree

2)三通道直方图

def classify_hist_with_split(image1, image2, size=(256, 256)):# RGB每个通道的直方图相似度# 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值image1 = cv2.resize(image1, size)image2 = cv2.resize(image2, size)sub_image1 = cv2.split(image1)sub_image2 = cv2.split(image2)sub_data = 0for im1, im2 in zip(sub_image1, sub_image2):sub_data += calculate(im1, im2)sub_data = sub_data / 3return sub_data

2.哈希算法

图像指纹:图像指纹和人的指纹一样,是身份的象征,而图像指纹简单点来讲,就是将图像按照一定的哈希算法,经过运算后得出的一组二进制数字。

汉明距离:假如一组二进制数据为101,另外一组为111,那么显然把第一组的第二位数据0改成1就可以变成第二组数据111,所以两组数据的汉明距离就为1;简单点说,汉明距离就是一组二进制数据变成另一组数据所需的步骤数,显然,这个数值可以衡量两张图片的差异,汉明距离越小,则代表相似度越高。汉明距离为0,即代表两张图片完全一样。

如何计算得到汉明距离,请看下面三种哈希算法:

1)平均哈希法(aHash)

此算法是基于比较灰度图每个像素与平均值来实现的

一般步骤:

1.缩放图片,一般大小为8*8,64个像素值。

2.转化为灰度图

3.计算平均值:计算进行灰度处理后图片的所有像素点的平均值,直接用numpy中的mean()计算即可。

4.比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0.

5.得到信息指纹:组合64个bit位,顺序随意保持一致性。

6.最后比对两张图片的指纹,获得汉明距离即可。

代码实现:

#均值哈希算法def aHash(img):#缩放为8*8img=cv2.resize(img,(8,8),interpolation=cv2.INTER_CUBIC)#转换为灰度图gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#s为像素和初值为0,hash_str为hash值初值为''s=0hash_str=''#遍历累加求像素和for i in range(8):for j in range(8):s=s+gray[i,j]#求平均灰度avg=s/64#灰度大于平均值为1相反为0生成图片的hash值for i in range(8):for j in range(8):if  gray[i,j]>avg:hash_str=hash_str+'1'else:hash_str=hash_str+'0'            return hash_str

2)感知哈希算法(pHash)

平均哈希算法过于严格,不够精确,更适合搜索缩略图,为了获得更精确的结果可以选择感知哈希算法,它采用的是DCT(离散余弦变换)来降低频率的方法

一般步骤:

1.缩小图片:32 * 32是一个较好的大小,这样方便DCT计算

2.转化为灰度图

3.计算DCT:利用Opencv中提供的dct()方法,注意输入的图像必须是32位浮点型,所以先利用numpy中的float32进行转换

4.缩小DCT:DCT计算后的矩阵是32 * 32,保留左上角的8 * 8,这些代表的图片的最低频率

5.计算平均值:计算缩小DCT后的所有像素点的平均值。

6.进一步减小DCT:大于平均值记录为1,反之记录为0.

7.得到信息指纹:组合64个信息位,顺序随意保持一致性。

8.最后比对两张图片的指纹,获得汉明距离即可。

代码实现:

import cv2import numpy as npfrom compiler.ast import flattenimport sysdef pHash(imgfile):"""get image pHash value"""#加载并调整图片为32x32灰度图片img=cv2.imread(imgfile, 0)img=cv2.resize(img,(64,64),interpolation=cv2.INTER_CUBIC)#创建二维列表h, w = img.shape[:2]vis0 = np.zeros((h,w), np.float32)vis0[:h,:w] = img       #填充数据#二维Dct变换vis1 = cv2.dct(cv2.dct(vis0))#cv.SaveImage('a.jpg',cv.fromarray(vis0)) #保存图片vis1.resize(32,32)#把二维list变成一维listimg_list=flatten(vis1.tolist())#计算均值avg = sum(img_list)*1./len(img_list)avg_list = ['0' if i<avg else '1' for i in img_list]#得到哈希值return ''.join(['%x' % int(''.join(avg_list[x:x+4]),2) for x in range(0,32*32,4)])'''cv2.imreadflags>0时表示以彩色方式读入图片flags=0时表示以灰度图方式读入图片flags<0时表示以图片的本来的格式读入图片interpolation - 插值方法。共有5种:1)INTER_NEAREST - 最近邻插值法2)INTER_LINEAR - 双线性插值法(默认)3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。4)INTER_CUBIC - 基于4x4像素邻域的3次插值法5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值

3)差值哈希算法(dHash)

相比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。

步骤:

1.缩小图片:收缩到9*8的大小,以便它有72的像素点

2.转化为灰度图

3.计算差异值:dHash算法工作在相邻像素之间,这样每行9个像素之间产生了8个不同的差异,一共8行,则产生了64个差异值

4.获得指纹:如果左边的像素比右边的更亮,则记录为1,否则为0.

5.最后比对两张图片的指纹,获得汉明距离即可。

代码实现:

def dHash(img):#缩放8*8img=cv2.resize(img,(9,8),interpolation=cv2.INTER_CUBIC)#转换灰度图gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)hash_str=''#每行前一个像素大于后一个像素为1,相反为0,生成哈希for i in range(8):for j in range(8):if   gray[i,j]>gray[i,j+1]:hash_str=hash_str+'1'else:hash_str=hash_str+'0'return hash_str

3.数学上的矩阵分解

图像本身就是一个矩阵,可以依靠数学上矩阵分解的一些知识来获取矩阵中一些代表这个矩阵元素值和分布的一些鲁棒性特征来对图像的相似度进行计算。

最常用的一般是SVD分解和NMF分解。

下面简单介绍下SVD分解的一些性质

(1)奇异值的稳定性;

(2)奇异值的比例不变性;

(3)奇异值的旋转不变性;

(4) 奇异值的压缩性。

综上所述,可以看出奇异值分解是基于整体的表示。图像奇异值特征向量不但具有正交变换、旋转、位移、镜像映射等代数和几何上的不变性,而且具有良好的稳定性和抗噪性,广泛应用于模式识别与图像分析中。对图像进行奇异值分解的目的是:得到唯一、稳定的特征描述;降低特征空间的维数;提高抵抗干扰和噪声的能力。但是由于奇异值分解得到的奇异矢量中有负数存在所以不能很好的解释其物理意义。

非负矩阵分解(NMF):

NMF的主要思想是将非负矩阵分解为可以体现图像主要信息的基矩阵与系数矩阵,并且可以对基矩阵赋予很好的解释,比如对人脸的分割,得到的基向量正是人的“眼睛”,“鼻子”等主要概念特征,源图像表示为这些特征的加权组合。所以NMF算法也在人脸识别等场合中发挥着巨大的作用。

4.基于特征点的图像相似度计算

每一幅图像都有自己的特征点,这些特征点表征图像中比较重要的一些位置,比较类似函数的拐点那种,通常比较常用的有Harris角点和Sift特征点。那么将得到的图像角点进行比较,如果相似的角点数目较多,那么可以认为这两幅图像的相似程度较高。这里主要介绍基于Sift算子。

那么我们就可以通过找到匹配点的个数来判断两幅图像是否一致,这个算法的好处是对于一个物体,两个不同角度下得到的照片依然可以找到很多的匹配点,我也一直认为是一个综合来说结果相对较为准确的方法,但是由于每个特征点需要计算一个长度不小的特征值,也造成了该算法的时间消耗比较大。所以不常用于实时的视频处理。这个算法还有一个好处就是可以通过找到的匹配特征点进行图像校正。

5. SSIM(结构相似性度量)

这是一种全参考的图像质量评价指标,分别从亮度、对比度、结构三个方面度量图像相似性。

SSIM取值范围[0, 1],值越大,表示图像失真越小。

在实际应用中,可以利用滑动窗将图像分块,令分块总数为N,考虑到窗口形状对分块的影响,采用高斯加权计算每一窗口的均值、方差以及协方差,然后计算对应块的结构相似度SSIM,最后将平均值作为两图像的结构相似性度量,即平均结构相似性SSIM。

代码实现:

from skimage.measure import compare_ssimfrom scipy.misc import imreadimport numpy as npimg1 = imread('1.jpg')img2 = imread('2.jpg')img2 = np.resize(img2, (img1.shape[0], img1.shape[1], img1.shape[2]))print(img2.shape)print(img1.shape)ssim = compare_ssim(img1, img2, multichannel=True)print(ssim)

6. cosin相似度(余弦相似度)

把图片表示成一个向量,通过计算向量之间的余弦距离来表征两张图片的相似度。

代码实现:

from PIL import Imagefrom numpy import average, linalg, dotdef get_thumbnail(image, size=(1200, 750), greyscale=False):image = image.resize(size, Image.ANTIALIAS)if greyscale:image = image.convert('L')return imagedef image_similarity_vectors_via_numpy(image1, image2):image1 = get_thumbnail(image1)image2 = get_thumbnail(image2)images = [image1, image2]vectors = []norms = []for image in images:vector = []for pixel_tuple in image.getdata():vector.append(average(pixel_tuple))vectors.append(vector)norms.append(linalg.norm(vector, 2))a, b = vectorsa_norm, b_norm = normsres = dot(a / a_norm, b / b_norm)return resimage1 = Image.open('1.jpg')image2 = Image.open('2.jpg')cosin = image_similarity_vectors_via_numpy(image1, image2)print(cosin)

7.基于互信息(Mutual Information)

通过计算两个图片的互信息来表征他们之间的相似度。

代码实现:

from sklearn import metrics as mrfrom scipy.misc import imreadimport numpy as npimg1 = imread('1.jpg')img2 = imread('2.jpg')img2 = np.resize(img2, (img1.shape[0], img1.shape[1], img1.shape[2]))img1 = np.reshape(img1, -1)img2 = np.reshape(img2, -1)print(img2.shape)print(img1.shape)mutual_infor = mr.mutual_info_score(img1, img2)print(mutual_infor)

8.计算图像的“指纹信息”

将图像归一化成一定大小,计算 一个序列作为他的指纹信息,然后比较两张图片指纹信息序列相同的位数。如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。

9.MD5

粗暴的md5比较 返回是否完全相同

代码实现:


def md5_similarity(img1_path, img2_path):file1 = open(img1_path, "rb")file2 = open(img2_path, "rb")md = hashlib.md5()md.update(file1.read())res1 = md.hexdigest()md = hashlib.md5()md.update(file2.read())res2 = md.hexdigest()return res1 == res2

10.PSNR

代码实现:

def PSNR(img1, img2):mse = np.mean((img1/255. - img2/255.) ** 2)if mse == 0:return 100PIXEL_MAX = 1return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))

11.图片相似度算法(对像素求方差并比对)的学习

步骤:

1)缩放图片

将需要处理的图片所放到指定尺寸,缩放后图片大小由图片的信息量和复杂度决定。譬如,一些简单的图标之类图像包含的信息量少,复杂度低,可以缩放小一点。风景等复杂场景信息量大,复杂度高就不能缩放太小,容易丢失重要信息。根据自己需求,弹性的缩放。在效率和准确度之间维持平衡。

2)灰度处理

  通常对比图像相似度和颜色关系不是很大,所以处理为灰度图,减少后期计算的复杂度。如果有特殊需求则保留图像色彩。

3)计算平均值

  此处开始,与传统的哈希算法不同:分别依次计算图像每行像素点的平均值,记录每行像素点的平均值。每一个平均值对应着一行的特征。

4)计算方差

  对得到的所有平均值进行计算方差,得到的方差就是图像的特征值。方差可以很好的反应每行像素特征的波动,既记录了图片的主要信息。

5)比较方差

经过上面的计算之后,每张图都会生成一个特征值(方差)。到此,比较图像相似度就是比较图像生成方差的接近成程度。
  一组数据方差的大小可以判断稳定性,多组数据方差的接近程度可以反应数据波动的接近程度。我们不关注方差的大小,只关注两个方差的差值的大小。方差差值越小图像越相似!

代码实现:

import cv2import matplotlib.pyplot as plt#计算方差def getss(list):#计算平均值avg=sum(list)/len(list)#定义方差变量ss,初值为0ss=0#计算方差for l in list:ss+=(l-avg)*(l-avg)/len(list)#返回方差return ss#获取每行像素平均值def getdiff(img):#定义边长Sidelength=30#缩放图像img=cv2.resize(img,(Sidelength,Sidelength),interpolation=cv2.INTER_CUBIC)#灰度处理gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#avglist列表保存每行像素平均值avglist=[]#计算每行均值,保存到avglist列表for i in range(Sidelength):avg=sum(gray[i])/len(gray[i])avglist.append(avg)#返回avglist平均值return avglist#读取测试图片img1=cv2.imread("james.jpg")diff1=getdiff(img1)print('img1:',getss(diff1))#读取测试图片img11=cv2.imread("durant.jpg")diff11=getdiff(img11)print('img11:',getss(diff11))ss1=getss(diff1)ss2=getss(diff11)print("两张照片的方差为:%s"%(abs(ss1-ss2)))x=range(30)plt.figure("avg")plt.plot(x,diff1,marker="*",label="$jiames$")plt.plot(x,diff11,marker="*",label="$durant$")plt.title("avg")plt.legend()plt.show()cv2.waitKey(0)cv2.destroyAllWindows()

图像相似算法最全总结相关推荐

  1. 58同城招聘|三维重建、图像图形学算法工程师(校招/社招)

    3D视觉工坊致力于推荐最棒的工作机会,精准地为其找到最佳求职者,做连接优质企业和优质人才的桥梁.如果你需要我们帮助你发布实习或全职岗位,请添加微信号「CV_LAB」. 58同城VR项目组招聘 公司介绍 ...

  2. 图像处理(十三)保刚性图像变形算法-Siggraph 2004

    图像变形可以说是很多图像.动画领域的一个非常常见的功能,就说ps.天天P图.美图秀秀.可牛等这些每个软件,有好多个功能都要用到图像变形,比如图像方向校正.图像全景.视频防抖等,在我的另外一篇博文全景矩 ...

  3. grads 相关系数_基于小波变换的多聚焦图像融合算法

    引用本文 孟强强, 杨桄, 童涛, 张俭峰. 基于小波变换的多聚焦图像融合算法[J]. 国土资源遥感, 2014,26(2): 38-42 MENG Qiangqiang, YANG Guang, T ...

  4. 图像降噪算法——低秩聚类:WNNM算法

    图像降噪算法--低秩聚类:WNNM算法 图像降噪算法--低秩聚类:WNNM算法 1. 基本原理 2. matlab代码 3. 结论 图像降噪算法--低秩聚类:WNNM算法 同样是为了完善自己知识版图的 ...

  5. 图像降噪算法——DnCNN / FFDNet / CBDNet / RIDNet / PMRID / SID

    图像降噪算法--DnCNN / FFDNet / CBDNet / RIDNet / PMRID / SID 图像降噪算法--DnCNN / FFDNet / CBDNet / RIDNet / PM ...

  6. 从编解码算法到全链路RTC架构,揭秘淘系直播技术演进之路

    从2016年直播元年至今,纯粹的直播已经逐渐失去竞争力,越来越多形式创新映入眼帘,而众多企业开始走向内容垂直化--秀场.游戏.电商.广电等内容特点深度结合.伴随2020年疫情爆发,电商为人们日常生活提 ...

  7. 2020前端最新面试题总结(js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)(3年前端菜鸟级开发师含泪总结)

    2020前端最新面试题总结(js.html.小程序.React.ES6.Vue.算法.全栈热门视频资源) 文档描述 (今年确实挺难 3年前端菜鸟级开发师含泪总结 希望能帮助大家) 本文是关注微信小程序 ...

  8. 一种快速简单而又有效的低照度图像恢复算法

                           一种快速简单而又有效的低照度图像恢复算法 <Adaptive Local Tone Mapping Based on Retinex for Hig ...

  9. 有效的亚像素图像配准算法

    比较了采用非线性优化和矩阵乘离散傅里叶变换的三种二维图像配准算法.这些算法的精度与传统的快速算法相当.傅里叶变换上采样方法在一小部分的计算时间和与大大减少内存要求.比较它们的精度和计算时间,以评估平移 ...

最新文章

  1. 用敏捷开发工具可视化的进行Sprint规划
  2. 准备篇--串口通信概述
  3. ITK:分段线性曲线的数据结构
  4. (Head First 设计模式)学习笔记(1)
  5. 计算机与人力资源管理论文,计算机专业毕业论文-人力资源管理系统的研究与实现...
  6. jQuery中的几个案例:隔行变色、复选框全选和全不选
  7. 华策影视:控股股东、实控人等拟合计减持不超4.01%股份
  8. 5)Thymeleaf 模板布局 th:fragment、th:replace、th:insert、th:remove
  9. jsp三大指令(总结)
  10. Java打印条码,使用热敏条码打印机
  11. 微信小程序列表项数据详情折叠效果
  12. WebMagic抓取阿里司法拍卖信息
  13. 分享一组制作游戏用的人物立绘/角色形象素材图片,共717张图片
  14. 发送短信验证码时触发天级流控Premit:10
  15. 全国地址数据库下载 mysql版更新共668389条记录 精确到村
  16. FUZ 1759 Super A^B mod C (指数循环节/模板)
  17. git push方法
  18. java机试题---2021(算法)
  19. 软件测试师具备的素质_软件测试工程师的所需要的职业素养是什么?
  20. Google Earth Engine(GEE)实例代码学习十一——影像全色波段融合提高分辨率(HSV Pan Sharpening)

热门文章

  1. JAVA_小小圣诞树
  2. Echarts的配置与使用
  3. 【转】世上万事,不过是一懒二拖三不读书
  4. Exchange 2016的MAPI over HTTP简介
  5. 双11|NetSuite SuiteCommerce助你一臂之力
  6. CentOS7 win7 双系统安装
  7. freeCodeCamp Slasher Flick
  8. Qt 错误 The process was ended forcefully(无法定位程序输入点 于动态链接库)
  9. 换了工作城市,社保和公积金的转移
  10. 【OpenCV3经典编程100例】(26)2D特征:Shi-Tomasi角点检测goodFeaturesToTrack()函数