如何使用结构相似性指数(SSIM)将两个图像与Python进行比较。
使用这种方法,我们能够轻松确定两个图像是否相同或由于轻微的图像处理,压缩伪像或有目的的篡改而产生差异。
今天我们将扩展SSIM方法,以便我们可以使用OpenCV和Python可视化图像之间的差异。具体来说,我们将在两个不同的输入图像中的区域周围绘制边界框。
与OpenCV和Python的图像差异
为了计算两个图像之间的差异,我们将利用结构相似性指数,由Wang等人首先介绍。在2004年的论文中,图像质量评估:从错误可见性到结构相似性。此方法已在scikit-image 库中实现以进行图像处理。
诀窍是学习如何根据(x,y) -坐标位置精确确定图像差异的位置。
为此,我们首先需要确保我们的系统具有Python,OpenCV,scikit-image和imutils。
您可以使用我的OpenCV安装教程学习如何在系统上配置和安装Python和OpenCV 。
如果您还没有 scikit - 已安装/升级映像,请通过以下方式升级:
$ pip install --upgrade scikit-image
当你在这里时,继续安装/升级 imutils :
$ pip install --upgrade imutils
现在我们的系统已经准备好了先决条件,让我们继续。
计算图像差异
你能发现这两个图像之间的区别吗?
图1:手动检查两个输入图像(源)之间的差异
如果您花一秒钟研究这两张信用卡,您会注意到MasterCard徽标出现在 左侧图像上,但已从右侧图像中删除 。
您可能已经立即注意到这种差异,或者可能已经花了几秒钟。无论哪种方式,这都证明了比较图像差异的一个重要方面 - 有时图像差异是微妙的 - 如此微妙以至于肉眼难以立即理解差异(我们将在本博文后面看到这样一个图像的例子)。
那么为什么计算图像差异如此重要呢?
一个例子是 网络钓鱼。攻击者可以稍微操纵图像,以欺骗不验证URL的毫无戒心的用户,使他们认为他们正在登录他们的银行网站 - 后来发现这是一个骗局。
将网页上的徽标和已知用户界面(UI)元素与现有数据集进行比较有助于减少网络钓鱼攻击(非常感谢Chris Cleveland传递 PhishZoo:通过查看网络钓鱼网站作为应用计算机视觉预防的示例来检测网络钓鱼网站网络钓鱼)。
开发网络钓鱼检测系统显然比简单的图像差异复杂得多,但我们仍然可以应用这些技术来确定是否已经操纵了给定的图像。
现在,让我们计算两个图像之间的差异,并使用OpenCV,scikit-image和Python并排查看差异。
打开一个新文件并将其命名为 image_diff .py ,并插入以下代码:
# import the necessary packages from skimage.measure import compare_ssim import argparse import imutils import cv2 # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-f", "--first", required=True, help="first input image") ap.add_argument("-s", "--second", required=True, help="second") args = vars(ap.parse_args()) # load the two input images imageA = cv2.imread(args["first"]) imageB = cv2.imread(args["second"]) # convert the images to grayscale grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY) grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY) # compute the Structural Similarity Index (SSIM) between the two # images, ensuring that the difference image is returned (score, diff) = compare_ssim(grayA, grayB, full=True) diff = (diff * 255).astype("uint8") print("SSIM: {}".format(score)) # threshold the difference image, followed by finding contours to # obtain the regions of the two input images that differ thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) # loop over the contours for c in cnts: # compute the bounding box of the contour and then draw the # bounding box on both input images to represent where the two # images differ (x, y, w, h) = cv2.boundingRect(c) cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2) # show the output images cv2.imshow("Original", imageA) cv2.imshow("Modified", imageB) cv2.imshow("Diff", diff) cv2.imshow("Thresh", thresh) cv2.waitKey(0)
第2-5行显示我们的进口。我们将使用 compare_ssim (来自scikit-image), argparse , imutils 和 cv2 (OpenCV)。
我们建立两个命令行参数, - first 和 - second ,它们是我们希望比较的两个相应输入图像的路径(第8-13行)。
接下来,我们将从磁盘加载每个图像并将其转换为灰度:
我们载入我们的第一和第二图像, - 第一 和 - 第二 ,上 线16和17,它们存储为 imageA 和 imageB 分别。
然后我们在第20行和第21行将每个转换为灰度。
接下来,让我们计算两个灰度图像之间的结构相似性指数(SSIM)。
使用 scikit-image中的 compare_ssim函数,我们计算 得分 和差异图像 diff (第25行)。
所述 得分 表示两个输入图像之间的结构相似性指数。该值可以落在[-1,1]范围内 ,值为1是“完美匹配”。
该 差异 的图像包含实际 图像的差异 ,我们希望以可视化的两个输入图像之间。差异图像当前表示为[0,1]范围内的浮点数据类型, 因此我们首先将数组转换为[0,255](第26行)范围内的8位无符号整数, 然后我们才能进一步处理它使用OpenCV。
现在,让我们找到轮廓,以便我们可以在标识为“不同”的区域周围放置矩形:
在 第31行和第32行,我们 使用cv2对我们的差异图像进行 阈值 处理。THRESH_BINARY_INV 和 cv2 。THRESH_OTSU - 使用垂直条'或'符号,|同时应用这两个设置 。有关Otsu双峰阈值设置的详细信息,请参阅此OpenCV文档。
随后我们 在 第33-35行找到了thresh的轮廓 。第35行的三元运算符 简单地适应了各种版本的OpenCV中cv2.findContours返回签名之间的差异。郑州妇科医院哪家好:https://yyk.familydoctor.com.cn/21521/
下面图4中的图像清楚地显示了已被操纵的图像的ROI:
图4:使用阈值处理使用OpenCV和Python突出显示图像差异。
从第38行开始 ,我们遍布我们的轮廓, cnts 。首先,我们使用cv2计算轮廓周围的边界框 。boundingRect 函数。我们将相关的 (x,y )坐标存储为 x 和 y 以及矩形的宽度/高度为 w 和 h 。
然后我们使用这些值在每个图像上用cv2绘制一个红色矩形 。矩形 (第43和44行)。
最后,我们用差异图像,差异图像和阈值图像显示比较图像(第47-50行)。
我们打电话给 cv2 。waitKey 上 50线,直到按下一个键,这使得程序等待(此时脚本将退出)。
接下来,让我们运行脚本并可视化一些图像差异。
可视化图像差异
使用此脚本和以下命令,我们可以快速轻松地突出显示两个图像之间的差异:
$ python image_diff.py --first images/original_02.png --second images/modified_02.png
正如您在图6中看到的那样,安全芯片和帐户持有者的名称都被删除了:
让我们尝试另一个计算图像差异的例子,这次是由杰拉尔德·R·福特总统(来源)撰写的支票。
通过运行下面的命令并提供相关图像,我们可以看到这里的差异更加微妙:
$ python image_diff.py --first images/original_03.png --second images/modified_03.png
请注意图7中的以下更改:
在像检查这样的复杂图像上,通常很难用肉眼找到 所有差异。幸运的是,我们现在可以使用Python,OpenCV和scikit-image制作的这个方便的脚本轻松计算差异并可视化结果。
摘要
我们学习了如何使用OpenCV,Python和scikit-image的结构相似性指数(SSIM)来计算图像差异。基于图像差异,我们还学习了如何在两个图像中标记和可视化不同区域