基于Python的图片比较
原文地址 -How-To: Python Compare Two Images-
通过阅读作者原文,感觉文章通俗易懂,根据个人理解整理成中文,并不逐句翻译,因未找到原文图片,文末个人试验图片来自网络。
原文主要使用MSE(均方差)和SSIM(结构化相似度指数)来进行图片的比较,环境python3/opencv3
原文效果图
1.图片样本
观察上述三幅图,左边为原始图片,中间为原图对比度调整后的图片,右边为带有logo的原始图片。通过观察,我们可以知道左边和中间的图片几乎一模一样,仅仅是颜色更暗了点,但是通过计算得到的MSE显示左边和右边的图像更相似。下面来仔细介绍。
2.MSE和SSIM
计算两幅图片的均方差,参考代码如下:
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。
计算公式:
显然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;
调整对比度前后比较,明显图片不一样,MSE已经很大,SSIM给出了0.78的相似度,接下来继续比较;
添加logo前后,按道理MSE要比调整对比度要大,因为添加logo后图片内容发生了变化,我们看结果,MSE要比调整对比度前后小,SSIM则给出了更为合适的结果。
5.个人测试
测试图片和代码参考我的github。
6.总结
图片的比较,可以使用两种方法:MSE和SSIM。
MSE计算速度快,但存在缺点(1)全图比较;(2)仅对图片的差异进行处理;
SSIM相对比较慢,相对于全图比较,它可以对图片局部信息结构进行比较。
那么到底使用哪种方法呢?
一般来说,SSIM会给出更好的结果,但会消耗更多的资源;
在原文作者看来,他更加追求精度的提升,因此他更青睐SSIM。
人各有异,根据需求选择自己需要的方法吧。