研究好玩又有用的技术第 008 期

在学习中发现快乐,在应用找到价值。这是我第八期分享图像技术应用的文章。

前七期欢迎阅读和分享:

概述

作者:Thalles Silva 编译:AI算法与图像处理

图像拼接是计算机视觉中最成功的应用之一。如今,很难找到不包含此功能的手机或图像处理API。

在这篇文章中,我们将讨论如何使用Python和OpenCV执行图像拼接。鉴于一对共享一些共同区域的图像,我们的目标是“缝合”它们并创建全景图像场景。

在整篇文章中,我们将介绍一些最着名的计算机视觉技术。这些包括:关键点检测

局部不变描述符(SIFT,SURF等)

特征匹配

使用RANSAC进行的旋转估计(Homography estimation)

透视畸变(Perspective warping)

我们探索了许多特征提取算子,如SIFT,SURF,BRISK和ORB。你可以使用这款Colab笔记本,甚至可以用你的照片试试。[这里我已经调试好源码并上传到github上面]

特征检测和提取

给定一对像上面那样的图像,我们想要把它们拼接起来创建一个全景场景。值得注意的是,两个图像都需要共享一些共同的区域。

此外,即使图片在以下一个或多个方面存在差异,我们的解决方案也必须强大:Scaling

Angle

Spacial position

Capturing devices

朝这个方向迈出的第一步是提取一些感兴趣的关键点和特征。但是,这些功能需要具有一些特殊属性。

我们首先考虑一个简单的解决方案。

关键点检测

一开始可能使用简单些的方法,诸如使用Harris Corners之类的算法提取关键点。然后,我们可以尝试根据欧几里德距离之类的相似度量来匹配相应的关键点。我们知道,角点(corner)有一个很好的属性:它们对旋转是不变的。 这意味着,一旦我们检测到一个角点,如果我们旋转图像,那个角点仍将存在。

但是,如果我们旋转然后缩放图像怎么办?在这种情况下,我们会很难,因为角点不是规模不变的。也就是说,如果我们放大图像,先前检测到的角可能会变成一条线!

总之,我们需要对旋转和缩放不变的特征。这就是SIFT,SURF和ORB等更强大的方法的用武之地。

关键点和描述子

像SIFT和SURF这样的方法试图解决角点检测算法的局限性。

通常,角点检测器算法使用固定大小的内核来检测图像上的感兴趣区域(角点)。很容易看出,当我们缩放图像时,这个内核可能会变得太小或太大。

为了解决这个限制,像SIFT这样的方法使用高斯差分(DoD)。我们的想法是在同一图像的不同比例版本上应用DoD。它还使用相邻像素信息来查找和细化关键点和相应的描述子。

首先,我们需要加载2个图像,查询图片和训练图片。最初,我们首先从两者中提取关键点和描述符。我们可以通过使用OpenCV detectAndCompute()函数一步完成。请注意,为了使用detectAndCompute(),我们需要一个关键点检测器和描述符对象的实例。它可以是ORB,SIFT或SURF等。另外,在将图像馈送到detectAndCompute()之前,我们将它们转换为灰度。def detectAndDescribe(image, method=None):

"""

Compute key points and feature descriptors using an specific method

"""

assert method is not None, "You need to define a feature detection method. Values are: 'sift', 'surf'"

# detect and extract features from the image

if method == 'sift':

descriptor = cv2.xfeatures2d.SIFT_create()

elif method == 'surf':

descriptor = cv2.xfeatures2d.SURF_create()

elif method == 'brisk':

descriptor = cv2.BRISK_create()

elif method == 'orb':

descriptor = cv2.ORB_create()

# get keypoints and descriptors

(kps, features) = descriptor.detectAndCompute(image, None)

return (kps, features)

我们对查询和训练的图片都运行detectAndCompute()。此时,我们为这两个图像提供了一组关键点和描述子。如果我们使用SIFT作为特征提取器,它将为每个关键点返回128维特征向量。如果选择SURF,我们将获得64维特征向量。以下图像显示了使用SIFT,SURF,BRISK和ORB提取的一些功能。

使用SIFT检测关键点和描述子

使用SURF检测关键点和描述子

使用BRISK和汉明距离检测关键点和描述子

使用ORB和汉明距离检测关键点和描述子

特征匹配

我们可以看到,我们从两个图像中都有大量的特征。

现在,我们想比较两组特征并以线段相连的形式显示更多相似性的特征点对。

使用OpenCV,功能匹配需要Matcher对象。在这里,我们探索两种方法:Brute Force Matcher(暴力匹配法)

KNN(k-最近邻)

BruteForce(BF)Matcher正如其名称所表明的那样。给定2组特征(来自图片A和图片B),来自集合A的每个特征与集合B中的所有特征进行比较。默认情况下,BF匹配器计算两点之间的欧几里德距离。因此,对于集合A中的每个特征,它返回集合B中最接近的特征。对于SIFT和SURF,OpenCV建议使用欧几里德距离。对于其他特征提取器,如ORB和BRISK,建议使用汉明距离。

要使用OpenCV创建BruteForce Matcher,我们只需要指定2个参数。第一个是距离度量。第二个是crossCheck布尔参数。def createMatcher(method,crossCheck):

"Create and return a Matcher Object"

if method == 'sift' or method == 'surf':

bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=crossCheck)

elif method == 'orb' or method == 'brisk':

bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=crossCheck)

return bf

crossCheck bool参数指示两个特征是否必须相互匹配才能被视为有效。换句话说,对于被认为有效的一对特征(f1,f2),f1需要匹配f2,并且f2也必须匹配f1作为最接近的匹配。此过程可确保更强大的匹配功能集,并在原始SIFT文章中进行了描述。

但是,对于我们想要考虑多个候选匹配的情况,我们可以使用基于KNN的匹配过程。

KNN不返回给定特征的单个最佳匹配,而是返回k个最佳匹配

注意,k的值必须是由用户预先定义的。如我们预期的那样,KNN提供了一个更的的候选特征集合。但是,我们需要确保所有这些匹配对在进一步发展之前都是健壮的。

比率测试(Ratio Testing)

为了确保KNN返回的特征具有良好的可比性,SIFT论文的作者提出了一种称为比率测试(Ratio Testing)的技术。基本上,我们迭代KNN返回的每个对并执行距离测试。对于每对特征(f1,f2),如果f1和f2之间的距离在一定比例内,我们保留它,否则,我们将它丢弃。此外,必须手动选择比率值。

从本质上讲,比率测试与BruteForce Matcher的交叉检查选项完成相同的工作。两者都确保一对检测到的特征确实足够近以至于被认为是相似的。下面的2个数字显示了BF和KNN Matcher对SIFT特征的结果。我们选择仅显示100个匹配点以清除可视化。

使用KNN和RIFT测试对SIFT特征进行特征匹配

在SIFT功能上使用Brute Force Matcher进行特征匹配

请注意,即使在KNN中交叉验证——暴力匹配(Brute force)和比率测试之后,某些功能也无法正确匹配。

然而,Matcher算法将为我们提供两个图像中最好的(更相似的)特征集。现在,我们需要获取这些点并找到基于匹配点将2个图像拼接在一起的变换矩阵。

这种转换称为Homography matrix(单应性矩阵)。简而言之,如果Homography是3x3矩阵,可用于许多应用,例如相机姿态估计,透视校正和图像拼接。如果Homography是2D变换。它将点从一个平面(图像)映射到另一个平面。让我们看看我们是如何得到它的。

Estimating the Homograph

RANdom SAmple Consensus或RANSAC是一种适合线性模型的迭代算法。与其他线性回归器不同,RANSAC设计为对异常值具有鲁棒性。

像线性回归这样的模型使用最小二乘估计来使最佳模型适合数据。然而,普通最小二乘法对异常值非常敏感。因此,如果异常值的数量很大,它可能会失败。

RANSAC通过仅使用数据中的内部子集估计参数来解决此问题。下图显示了线性回归和RANSAC之间的比较。首先,请注意数据集包含相当多的异常值。

我们可以看到线性回归模型很容易受到异常值的影响。那是因为它试图减少平均误差。因此,它倾向于支持最小化从所有数据点到模型本身的总距离的模型。这包括异常值。

相反,RANSAC仅将模型拟合到被识别为内点的点子集上。

这个特性对我们的用例非常重要。在这里,我们将使用RANSAC来估计Homography矩阵。事实证明,Homography对我们传递给它的数据质量非常敏感。因此,重要的是有一个算法(RANSAC)可以过滤明显不属于数据分布的点。

最小二乘与RANSAC模型拟合的比较。请注意数据中的大量异常值

一旦我们得到 estimated Homography,我们需要将其中一个图像变换到一个共同的平面。

在这里,我们将对其中一个图像应用透视变换。基本上,透视变换可以组合一个或多个操作,例如旋转,缩放,平移或剪切。这个想法是转换其中一个图像,使两个图像合并为一个。为此,我们可以使用OpenCV warpPerspective()函数。它采用图像和homography作为输入。然后,它根据homography将源图像变换到目的平面上。# Apply panorama correction

width = trainImg.shape[1] + queryImg.shape[1]

height = trainImg.shape[0] + queryImg.shape[0]

result = cv2.warpPerspective(trainImg, H, (width, height))

result[0:queryImg.shape[0], 0:queryImg.shape[1]] = queryImg

plt.figure(figsize=(20,10))

plt.imshow(result)

plt.axis('off')

plt.show()

生成的全景图像如下所示。如我们所见,结果中有几个工件。更具体地说,我们可以看到与图像边界处的照明条件和边缘效应有关的一些问题。理想情况下,我们可以执行后处理技术来标准化直方图匹配等强度。这可能会使结果看起来更加真实。

谢谢阅读!

效果图

demo 2

可能遇到bug

可能存在的报错

(1)Qt 链接报错 version `Qt_5' not found]python3: relocation error: /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5: symbol _ZN20QPlatformIntegration11screenAddedEP15QPlatformScreenb version Qt_5_PRIVATE_API not defined in file libQt5Gui.so.5 with link time reference

解决方案:https://www.cnblogs.com/sunchaothu/p/9962675.html

(2)AttributeError: module 'cv2.cv2' has no attribute 'xfeatures2d'

需要回退版本到3.4.2.16,记得要先卸载之前安装好的opencv-python

解决方案:https://blog.csdn.net/weixin_43167047/article/details/82841750

代码:https://github.com/DWCTOD/AI_study

原文链接:

https://towardsdatascience.com/image-panorama-stitching-with-opencv-2402bde6b46c

python全景图像拼接_超详讲解图像拼接/全景图原理和应用 | 附源码相关推荐

  1. 超详讲解图像拼接/全景图原理和应用 | 附源码

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 概述 图像拼接是计算机视觉中最成功的应用之一.如今,很难找到不包含 ...

  2. java中batch基础_详解Spring batch 入门学习教程(附源码)

    详解Spring batch 入门学习教程(附源码) 发布时间:2020-09-08 00:28:40 来源:脚本之家 阅读:99 作者:achuo Spring batch 是一个开源的批处理框架. ...

  3. python抢购火车票源代码_Python动刷新抢12306火车票的代码(附源码)

    摘要:这篇Python开发技术栏目下的"Python动刷新抢12306火车票的代码(附源码)",介绍的技术点是"12306火车票.Python.12306.附源码.火车票 ...

  4. 【Python工具】Python实现一款支持各大平台的视频下载器 | 附源码

    相关文件 想学Python的小伙伴可以关注小编的公众号[Python日志] 有很多的资源可以白嫖的哈,不定时会更新一下Python的小知识的哈!! 需要源码的小伙伴可以在公众号回复视频下载器 简介 一 ...

  5. 【竞赛项目详解】二手车交易价格预测(附源码)

    文章目录 1 项目简介 2 项目分析 2.1 数据分析(EDA) 2.2 难点分析 2.3 可行性方案分析 3 方案设计 3.1 特征工程 3.2 模型构建与训练 4 结果分析 5 源码链接 1 项目 ...

  6. Python实战案例,PyQt5模块,实现疫情信息快速查看工具(附源码)

    前言 今天给大家介绍的是Python疫情信息快速查看工具,在这里给需要的小伙伴们代码,并且给出一点小心得. PyQt概述 PyQt5是Qt框架的Python语言实现,由Riverbank Comput ...

  7. python如何将图片打包进exe里_用python将图片切分为九宫格 并打包成exe可执行文件(附源码)...

    前言 经常在朋友圈或者微博看到九宫格显示的图片,虽然是九张图片,但是这是一张图片经过切割而成的,显示效果很震撼.今天,我们就用python将图片切分为九宫格,并打包成exe可执行文件,就算不需要代码也 ...

  8. java web开源项目源码_超赞!推荐一个专注于Java后端源码分析的Github项目!

    大家好,最近有小伙伴们建议我把源码分析文章及源码分析项目(带注释版)放到github上,这样小伙伴们就可以把带中文注释的源码项目下载到自己本地电脑,结合源码分析文章自己本地调试,总之对于学习开源项目源 ...

  9. C++入门教程:大白话讲解,新手基础篇(附源码及详解、视频课程资料推荐)

    C++ Tutorial C++教程 前言 视频教程 文字教程 集成开发环境(IDE) 编译器 工作原理 学习指南 入门书籍 进阶书籍 算法.竞赛书籍 教程 标准构建 程序解释 第一个C++程序--& ...

最新文章

  1. (转)OpenNLP进行中文命名实体识别(下:载入模型识别实体)
  2. [转帖]Report painter
  3. google账号解除游戏绑定_附方法!关于物联卡手机号的绑定与解绑
  4. python ==字符串
  5. 2015年《大数据》读者意见调查问卷
  6. CVPR 2020 论文大盘点—目标跟踪篇
  7. 正则表达式(面试会考)
  8. 17.3.13--python编码问题
  9. 编码问题,java,当不知道自己的字符串编码是什么的时候,可以用如下程序进行尝试并自动转码utf-8,源码直接可用
  10. 【空间】C++内存管理
  11. 实现Canvas2D绘图 使元素绕中心居中旋转
  12. 蒙牛新品来了,小明纯牛奶透明袋
  13. dataworks手册_DataWorks 使用教程
  14. 常用的算法(PHP 版)
  15. web服务器、数据库服务器
  16. 洛谷 P2791 幼儿园篮球题
  17. 华为鸿蒙第一期公测,华为鸿蒙开启第二轮公测,新增7款机型,有你的吗?
  18. Matlab ——旋转矩阵,四元数,欧拉角之间的转换
  19. Autofill 实践
  20. ArcGIS中地形渲染图制作技巧

热门文章

  1. jquery网页日历显示控件calendar3.1使用详解
  2. Object.preventExtensions()使用技巧
  3. halcon算子翻译——deserialize_measure
  4. eclipse-阶段二-字体修改问题
  5. 郭宏志的android无线点餐系统,Android无线点餐系统--含代码.doc
  6. LED,LCD,OLED,miniLED,MicroLED显示详解
  7. linux运行查依赖,linux运行命令缺少依赖库的查找方法
  8. Nagios_快速配置
  9. 关于2014年上半年全国计算机等级考试有关事宜的通知,关于2014年上半年全国计算机等级考试报名的通知...
  10. json爬虫获取列表数据不全,已解决