基于Python的图片比较

感觉文章通俗易懂,根据个人理解整理成中文,并不逐句翻译,因未找到原文图片,文末个人试验图片来自网络。

原文主要使用MSE(均方差)和SSIM(结构化相似度指数)来进行图片的比较,环境python3/opencv3原文效果图

python3 图片对比 python图像对比处理_opencv

1.图片样本

python3 图片对比 python图像对比处理_MSE_02


观察上述三幅图,左边为原始图片,中间为原图对比度调整后的图片,右边为带有logo的原始图片。通过观察,我们可以知道左边和中间的图片几乎一模一样,仅仅是颜色更暗了点,但是通过计算得到的MSE显示左边和右边的图像更相似。下面来仔细介绍。

2.MSE和SSIM

python3 图片对比 python图像对比处理_python3 图片对比_03


计算两幅图片的均方差,参考代码如下:

def mse(imageA, imageB):
	err = np.sum((imageA.astype("float") - imageB.astype("float"))**2)
	err /= float(imageA.shape[0] * imageA.shape[1])
	return err

当然也可以直接使用skimage封装好的函数:

from skimage.measure import compare_mse as mse

MSE很简单就实现了,但是在图片相似度判别时有个问题,图片像素值之间的差异,不代表图片内容之间的差异,比如明暗。为了解决这个问题,早在2004年,Wang et al.提出了结构相似度指数SSIM。

计算公式:

python3 图片对比 python图像对比处理_图片差异化比较_04


显然SSIM要比MSE更加复杂,但最关键的地方是SSIM试图对图像结构信息中的感知变化进行建模,而MSE实际上是对感知误差的估计。

SSIM的值范围[-1, 1],1代表完全相同
MSE因为是均方差,值越小代表越相同,0代表完全相同

SSIM的计算方法skimage已经封装好,直接使用,原文时间较早,structural_similarity已更改为compare_ssim

from skimage.measure import compare_ssim as ssim
3.图像比较

新增了skimage中mse的计算,结果显示同自构函数mse结果完全一致。

def compareImages(imageA, imageB, title):
	m1 = mse(imageA, imageB)  # 构造函数
	m2 = mse_ski(imageA, imageB)  # skimage封装函数
	s = ssim(imageA, imageB)

	fig = plt.figure(title)
	plt.suptitle("MSE: %.2f, MSE With Ski: %.2f, SSIM: %.2f"%(m1, m2, 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.show()
4.比较结果

原文:
(1)将原始图片同自身进行MSE和SSIM结果对比;
(2)将原始图片调整对比度前后进行了MSE和SSIM结果对比;
(3)将原始图片添加logo前后进行了MSE和SSIM结果对比;

原图同自己比较,相似度100%,所以MSE:0,SSIM: 1.0;

python3 图片对比 python图像对比处理_MSE_05


调整对比度前后比较,明显图片不一样,MSE已经很大,SSIM给出了0.78的相似度,接下来继续比较;

python3 图片对比 python图像对比处理_图片差异化比较_06


添加logo前后,按道理MSE要比调整对比度要大,因为添加logo后图片内容发生了变化,我们看结果,MSE要比调整对比度前后小,SSIM则给出了更为合适的结果。

python3 图片对比 python图像对比处理_MSE_07

5.个人测试

测试图片和代码参考我的github。

python3 图片对比 python图像对比处理_图片差异化比较_08

6.总结

图片的比较,可以使用两种方法:MSE和SSIM

MSE计算速度快,但存在缺点(1)全图比较;(2)仅对图片的差异进行处理;
SSIM相对比较慢,相对于全图比较,它可以对图片局部信息结构进行比较。

那么到底使用哪种方法呢?
一般来说,SSIM会给出更好的结果,但会消耗更多的资源;
在原文作者看来,他更加追求精度的提升,因此他更青睐SSIM。
人各有异,根据需求选择自己需要的方法吧。