Python计算两张图片的相似度

15 篇文章 7 订阅

一、场景需求解读

  在现实场景中,我们经常会遇到一个问题,即如何评价不同图片的好坏,或者如何比较两张图片的相似性。它在学术研究领域中具有的广泛的研究前景,例如当你提出来一种新的图像增强算法,算法最终会输出增强之后的结果,为了比较不同算法的性能,我们通常需要使用一个指标来解决这个问题,常用的思路是使用MSE或者SSIM来比较标签和不同算法预测的结果,然后根据指标的大小来判断不同算法的好坏。

二、Mean Squared Error (MSE)简介

  MSE,即均方误差,它是一个用来计算两张图片相似度的一个指标值,该值越小表示两张图像越相似,它在学术领域中得到了广泛的应用,它的计算公式为: M S E = 1 m n ∑ i = 0 m − 1 ∑ j = 0 n − 1 [ I ( i , j ) − K ( i , j ) ] 2 M S E=\frac{1}{m n} \sum_{i=0}^{m-1} \sum_{j=0}^{n-1}[I(i, j)-K(i, j)]^{2} MSE=mn1i=0m1j=0n1[I(i,j)K(i,j)]2,其中m和n分别表示图像的宽和高,I和K分别表示两张测试图片对应的像素值,即将两张测试图片对应的位置的像素值相减然后将结果累积起来即可。具体的代码实现如下所示:

def mse(imageA, imageB):
	# 计算两张图片的MSE相似度
	# 注意:两张图片必须具有相同的维度,因为是基于图像中的对应像素操作的
    # 对应像素相减并将结果累加起来
	err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
	# 进行误差归一化
	err /= float(imageA.shape[0] * imageA.shape[1])
	
	# 返回结果,该值越小越好,越小说明两张图像越相似
	return err

  MSE的实现起来非常简单,但是当使用它进行相似性判断时,我们可能会遇到一些问题。主要问题是,像素强度之间的差距比较大并不一定意味着图像的内容有很大的差异。需要注意的是,MSE值为0时表示两张图像完全相似,大于1时意味着两张图片相似度较低,并将随着像素强度之间的平均差异的增加而继续增长。

三、The Structural Similarity Index (SSIM)简介

  尽管MSE实现起来十分简单,但是该评价指标中存在着较大的问题。为了更好的判断两份图片的相似度,学者们提出了SSMI指标,该指标能够更好的反应出两张图片的相似度,该指标的范围是[-1,1],当SSIM=-1时表示两张图片完全不相似,当SSIM=1时表示两张图片非常相似。即该值越接近1说明两张图片越相似。该指标的计算公式如下所示: SSIM ⁡ ( x , y ) = ( 2 μ x μ y + c 1 ) ( 2 σ x y + c 2 ) ( μ x 2 + μ y 2 + c 1 ) ( σ x 2 + σ y 2 + c 2 ) \operatorname{SSIM}(x, y)=\frac{\left(2 \mu_{x} \mu_{y}+c_{1}\right)\left(2 \sigma_{x y}+c_{2}\right)}{\left(\mu_{x}^{2}+\mu_{y}^{2}+c_{1}\right)\left(\sigma_{x}^{2}+\sigma_{y}^{2}+c_{2}\right)} SSIM(x,y)=(μx2+μy2+c1)(σx2+σy2+c2)(2μxμy+c1)(2σxy+c2),其中 μ x \mu_{x} μx表示图像中NxN区域中x方向的均值, σ x \sigma_{x} σx表示NxN区域中x方向的方差,c1和c2分别表示两张测试图片的像素强度平均值 , σ x y \sigma_{x y} σxy表示x和y方向的协方差值。
  SSIM方法显然比MSE方法更为复杂,SSIM试图模拟图像结构信息中感知到的变化,而MSE实际上是估计感知到的误差。两者之间有着细微的差别,但结果上的差异还是比较大的。此外,上式中的公式用于比较两个窗口(即小的子样本),而不是像MSE那样比较整个图像。这种方法能够解释图像结构的变化,而不仅仅是感知到的变化Scikit-image中已经实现了该指标,本文将使用实现好的SSIM指标。

四、算法代码实现

# coding=utf-8
# 导入python包
from skimage.measure import compare_ssim as ssim
import matplotlib.pyplot as plt
import numpy as np
import cv2

def mse(imageA, imageB):
	# 计算两张图片的MSE指标
	err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
	err /= float(imageA.shape[0] * imageA.shape[1])
	
	# 返回结果,该值越小越好
	return err

def compare_images(imageA, imageB, title):
	# 分别计算输入图片的MSE和SSIM指标值的大小
	m = mse(imageA, imageB)
	s = ssim(imageA, imageB)

	# 创建figure
	fig = plt.figure(title)
	plt.suptitle("MSE: %.2f, SSIM: %.2f" % (m, s))

	# 显示第一张图片
	ax = fig.add_subplot(1, 2, 1)
	plt.imshow(imageA, cmap = plt.cm.gray)
	plt.axis("off")

	# 显示第二张图片
	ax = fig.add_subplot(1, 2, 2)
	plt.imshow(imageB, cmap = plt.cm.gray)
	plt.axis("off")
	plt.tight_layout()
	plt.show()



# 读取图片
original1 = cv2.imread("test3.jpg")
contrast1 = cv2.imread("test3_adjust1.jpg")
shopped1 = cv2.imread("test2.jpg")

# 将彩色图转换为灰度图
original = cv2.cvtColor(original1, cv2.COLOR_BGR2GRAY)
contrast = cv2.cvtColor(contrast1, cv2.COLOR_BGR2GRAY)
shopped = cv2.cvtColor(shopped1, cv2.COLOR_BGR2GRAY)

# 初始化figure对象
fig = plt.figure("Images")
images = ("Original", original), ("Enhance", contrast), ("Others", shopped)

# 遍历每张图片
for (i, (name, image)) in enumerate(images):
	# 显示图片
	ax = fig.add_subplot(1, 3, i + 1)
	ax.set_title(name)
	plt.imshow(image, cmap = plt.cm.gray)
	plt.axis("off")
plt.tight_layout()
plt.show()

# 比较图片
compare_images(original, original, "Original vs Original")
compare_images(original, contrast, "Original vs Enhance")
compare_images(original, shopped, "Original vs Others")

五、效果展示与分析

在这里插入图片描述
  上图展示了不同指标在不同测试图片上面的测试效果。每一行表示不同的测试样本,第1列表示的是第一个测试样例的三种情况,第1行第1列表示输入的两张图片都是同一张图片的情况;第2行第1列表示输入一张原图和一张经过变换的图片的情况;第3行第1列表示输入两张不同的测试图片的情况。每张图片的上方都展示了不同情况下两种不同指标的计算结果,即MSE:xxx,SSIM:xxx。通过观察上图,我们可以获得一些信息,即当输入两张相同的照片时,对应到图中的第一行,我们可以观察到不同指标的输出结果为MSE=0,SSIM=1,即两种评价指标都认为这两张图片很相似;当输入一张原图和一张变换后的图像后,对应到图中的第二行,我们可以观察到不同指标的输出结果为MSE对于不同的图片会有较大的差异,SSIM基本上都在0.9以上,即SSIM指标认为这两张图片仍然很相似;当输入两张不同的图片时,对应到图中的第三行,我们可以观察到不同指标输出的结果为MSE=6277.42,SSIM=0.50,即两种指标都认为这两张图片不相似。

六、思维扩展

  尽管MSE和SSIM在很多情况下可以很好的判断出两张图片的相似度,但是在某些情况下这两个指标都不能很好的去判断两张图片的相似性,主要的原因是因为这两个指标都是人为设计的,都是根据人的理解来定义两张图片的相似度的。随着深度学习技术的快速发展,诞生了一种判断两张图片相似度的网络,即孪生网络(Siamese Network),该网络的主要思路是分别在两个分支中获取不同测试图片的特征,然后使用欧氏距离等指标来比较这两个特征的相似性,该网络当前已经可以获得较高的精度,聪明的你不妨去仔细的了解一下它。

参考资料

[1] 参考资料

注意事项

[1] 如果您对AI、自动驾驶、AR、ChatGPT等技术感兴趣,欢迎关注我的微信公众号“AI产品汇”,有问题可以在公众号中私聊我!
[2] 该博客是本人原创博客,如果您对该博客感兴趣,想要转载该博客,请与我联系(qq邮箱:1575262785@qq.com),我会在第一时间回复大家,谢谢大家的关注.
[3] 由于个人能力有限,该博客可能存在很多的问题,希望大家能够提出改进意见。
[4] 如果您在阅读本博客时遇到不理解的地方,希望您可以联系我,我会及时的回复您,和您交流想法和意见,谢谢。
[5] 本文测试的图片可以通过关注微信公众号AI产品汇之后找我索取!
[6] 本人业余时间承接各种本科毕设设计和各种小项目,包括图像处理(数据挖掘、机器学习、深度学习等)、matlab仿真、python算法及仿真等,有需要的请加QQ:1575262785详聊!!!

  • 32
    点赞
  • 164
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: Python可以使用Image模块和OpenCV库来比较两张图片相似度。以下是一种常见的方法: 首先,使用Image模块将两张图片加载为Image对象: from PIL import Image image1 = Image.open("image1.jpg") image2 = Image.open("image2.jpg") 接下来,将图片转换为灰度图像,这样可以减少比较的复杂度: image1_gray = image1.convert("L") image2_gray = image2.convert("L") 然后,可以使用numpy库将图像转换为数组,并进行进一步的处理。使用OpenCV库计算图像的差异度量,例如均方差或结构相似性指数(SSIM): import cv2 import numpy as np array1 = np.array(image1_gray) array2 = np.array(image2_gray) # 计算均方差 mse = np.mean((array1 - array2) ** 2) # 计算结构相似性指数 ssim = cv2.SSIM(array1, array2) 最后,根据不同的应用需求,可以仅根据均方差或者结构相似性指数来判断图片相似度。均方差越小,说明图片越相似;而结构相似性指数越接近1,说明图片越相似。 这只是其中一种比较图片相似度的方法,Python还有其他库和方法可以实现类似功能。 ### 回答2: Python可以使用一些图像处理和计算机视觉库来比较两张图片相似度,下面我将介绍其中的几个库。 1. PIL库:Python Imaging Library(PIL)是一个用于图像处理的库,可以加载、处理和保存多种格式的图像。可以使用PIL库来计算两张图片的直方图,并通过比较直方图来判断相似度。 2. OpenCV库:OpenCV是一个开源计算机视觉库,提供了很多用于图像处理的函数和算法。可以使用OpenCV库来计算两张图片之间的结构相似性指数(SSIM),该指数可以评估两张图片在亮度、对比度和结构等方面的相似程度。 3. scikit-image库:scikit-image是一个用于图像处理的Python库,提供了很多图像处理和计算机视觉的功能。可以使用scikit-image库来计算两张图片之间的结构相似性指数(SSIM)和均方误差(MSE),从而评估图片相似度。 4. perceptual哈希算法:perceptual哈希算法是一种可以计算图片相似度的算法,它通过计算两张图片的哈希值并比较它们的相似程度来判断图片相似度Python中有一些开源的算法库可以使用,如DHash、AHash和PHash。 总之,Python提供了多种图像处理和计算机视觉库可以用来比较两张图片相似度。具体选择哪个库要根据实际需求和数据特点来决定,可以根据图片的特点、计算速度和准确度等因素来选择合适的方法。 ### 回答3: 在Python中,我们可以使用OpenCV库来比较两张图片相似度。OpenCV是一个开源的计算机视觉库,提供了一系列用于图像处理和计算机视觉任务的函数。下面是一个简单的例子来演示如何使用OpenCV比较两张图片相似度: ```python import cv2 # 读取两张图片 image1 = cv2.imread('image1.jpg') image2 = cv2.imread('image2.jpg') # 确保两张图片有相同的尺寸 image1 = cv2.resize(image1, (200, 200)) image2 = cv2.resize(image2, (200, 200)) # 将图片转换为灰度图像 gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) # 计算两张图片的结构相似度指数(Structural Similarity Index,SSIM) ssim = cv2.compareSSIM(gray1, gray2) # 打印相似度 print("The SSIM between image1 and image2 is", ssim) ``` 上述代码中,我们首先使用`cv2.imread`函数读取两张图片,并使用`cv2.resize`函数将它们的尺寸调整为相同大小。然后,我们使用`cv2.cvtColor`函数将其转换为灰度图像,因为相似度比较通常使用灰度图像而非彩色图像。 最后,我们使用`cv2.compareSSIM`函数计算两张图片的结构相似度指数(SSIM)。SSIM是一种用于比较两张图像相似度的指标,其值在0到1之间,值越接近1表示两张图片越相似。 需要注意的是,为了得到准确的相似度值,我们需要确保两张图片在尺寸上相同,以及选择合适的图像比较算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值