还在用肉眼找不同吗?这个技术轻松搞定
点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
本文转自:AI算法与图像处理
我想应该很多人都玩过腾讯的这款游戏《大家来找茬》,想当年不知道多少人用鼠标对着美女图一顿输出,就是找不到哪里不一样。
今天我们要用到图像技术可以应用到这个上面。
今天,我们将使用扩展ssim(结构相似性索引)方法,以便使用OpenCV和python可视化图像之间的差异。具体来说,我们将在两个输入图片的不同处绘制边界框。
为了计算两张图片的不同,我们将使用结构相似性索引(由wang等人首次提出)。在他们的2004年论文中,图像质量评估:从可视化误差到结构相似性。该方法已经在scikit-image库中应用于图像处理。
https://ece.uwaterloo.ca/~z70wang/publications/ssim.pdf
要去学习的技巧是我们如何去准确确定图片不同点的坐标位置(x,y)。
要实现这一点,首先我们要确定系统已经安装好python、OpenCV、scikit-image和imutils。
你可以使用下面的OpenCV安装教程学习如何在系统上配置和安装python和OpenCV。
https://www.pyimagesearch.com/opencv-tutorials-resources-guides/
如果你还没安装或更新scikit-image包,你可以使用下面的操作:
pip3 install --upgrade scikit-image
同样的,如果你还为安装或更新imutils,你可以使用下面的操作:
pip3 install --upgrade imutils
现在我们的系统已经准备好了,可以继续往下操作了。
思考:你能分辨出下面这两幅图片的区别吗?
你可能会马上注意到这个差异,或者说花费一点时间。不管怎样,这都说明了比较图片的差异是一个重要的方面——有时图片的差异是微小的——这将导致肉眼难以立刻发现这些差异(文章的后面会有一个这样子的例子)。
为什么计算图片的差异如此重要?
http://www1.icsi.berkeley.edu/~sadia/papers/phishzoo-icsc_final.pdf
# 导入必要的包
from skimage.measure import compare_ssim
import argparse
import imutils
import cv2
# 构造解析参数
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())
# 导入图片
imageA = cv2.imread(args["--first"])
imageB = cv2.imread(args["--second"])
# 把图片转换为灰度图
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
然后我们将其转为灰度图(第6-7行)
接下来,开始计算两会在那个图片之间的结构相似性索引(SSIM)
# 计算两张图片的结构相似性索引
# 确保差分图片
(score, diff) = compare_ssim(grayA, grayB, full=True)
diff = (diff*255).astype("uint8")
print("SSIM:{}".format(score))
在第3行中使用scikit-image中的compare_ssim函数,我们计算得到一个score和差分图片diff
现在,找到这些轮廓,这样我们可以在被标识为“不同”的区域画出矩形。
# 阈值分割差分图像,然后查找轮廓以获得两个输入图片的不同区域
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)
在第2-3行中,我们使用cv2.THRESH_BINARY_INV 和 cv2.THRESH_OTSU来阈值处理我们的差分图片——这两个设置使用竖线或符号 “|” 来同时应用。
https://docs.opencv.org/trunk/d7/d4d/tutorial_py_thresholding.html
中文版的:cv2.threshold参数详细说明如下:
https://blog.csdn.net/sinat_21258931/article/details/61418681
# 遍历轮廓
for c in cnts:
# 计算轮廓的边界框,然后在两张输入图片中代表图片不同点的区域绘制边界框
(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)
# 显示输出图片
cv2.imshow("Original", imageA)
cv2.imshow("Modified", imageB)
cv2.imshow("Diff", diff)
cv2.imshow("Thresh", thresh)
cv2.waitKey(0)
python3 image_diff.py --first images/original_02.png --second images/modified_02.png
如下图所示,安全芯片和账户持有者的姓名都被删除。
再尝试另一个例子,一张支票。
python3 image_diff.py --first images/original_03.png --second images/modified_03.png
名字被删除 支票编号被删除 日期旁边的符号被删除 最后的名字被删除
今天的文章,我们学习了如何使用OpenCV、python和scikit-image的结构相似性所有(SSIM)来计算图片的不同点。基于图片的不同点,我们也学习了如何标记和可视化两张图片中的不同区域,后台回复“找不同”获取源码和示例图片
更多关于SSIM的内容,可以参考https://www.pyimagesearch.com/2014/09/15/python-compare-two-images/和scikit-image的文档https://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.compare_ssim
https://www.pyimagesearch.com/2017/06/19/image-difference-with-opencv-and-python/
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~