Python实现图像全景拼接
个人博客:wyxogo.top
目标:将数张有重叠部分的图像通过特征点检测,匹配,图像变换拼成一幅无缝的全景图或高分辨率图像
在图像拼接中首先利用SIFT算法提取图像特征进而进行特征匹配,继而使用RANSAC算法对特征匹配的结果进行优化,接着利用图像变换结构进行图像映射,最终进行图像融合。
在图像拼接过程中,运用SIFT局部描述算子检测图像中的关键点和特征,SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高,所以用来检测要拼接图像的特征及关键点就很有优势。而接下来即步骤三是找到重叠的图片部分,连接所有图片之后就可以形成一个基本的全景图了。匹配图片最常用的方式是采用RANSAC(RANdom SAmple Consensus, 随机抽样一致),用此排除掉不符合大部分几何变换的匹配。之后利用这些匹配的点来估算单应矩阵”(Homography Estimation),也就是将其中一张图像通过关联性和另一张匹配。
使用的算法:
- RANSAC
- SIFT
1. 利用SIFT方法检测特征点
def detectAndDescribe(image):# 将彩色图片转换成灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 建立SIFT生成器descriptor = cv2.xfeatures2d.SIFT_create()# 检测SIFT特征点,并计算描述子(kps, features) = descriptor.detectAndCompute(image, None)# 将结果转换成NumPy数组kps = np.float32([kp.pt for kp in kps])# 返回特征点集,及对应的描述特征return (kps, features)
2. 将检测到的特征点进行匹配
def matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh):# 建立暴力匹配器matcher = cv2.BFMatcher()# 使用KNN检测来自A、B图的SIFT特征匹配对,K=2rawMatches = matcher.knnMatch(featuresA, featuresB, 2)matches = []for m in rawMatches:# 当最近距离跟次近距离的比值小于ratio值时,保留此匹配对if len(m) == 2 and m[0].distance < m[1].distance * ratio:# 存储两个点在featuresA, featuresB中的索引值matches.append((m[0].trainIdx, m[0].queryIdx))# 当筛选后的匹配对大于4时,计算视角变换矩阵if len(matches) > 4:# 获取匹配对的点坐标ptsA = np.float32([kpsA[i] for (_, i) in matches])ptsB = np.float32([kpsB[i] for (i, _) in matches])# 计算视角变换矩阵(H, status) = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, reprojThresh)# 返回结果return (matches, H, status)# 如果匹配对小于4时,返回Nonereturn None
3. 将匹配的特征点可视化
def drawMatches(imageA, imageB, kpsA, kpsB, matches, status):# 初始化可视化图片,将A、B图左右连接到一起(hA, wA) = imageA.shape[:2](hB, wB) = imageB.shape[:2]vis = np.zeros((max(hA, hB), wA + wB, 3), dtype="uint8")vis[0:hA, 0:wA] = imageAvis[0:hB, wA:] = imageB# 联合遍历,画出匹配对for ((trainIdx, queryIdx), s) in zip(matches, status):# 当点对匹配成功时,画到可视化图上if s == 1:# 画出匹配对ptA = (int(kpsA[queryIdx][0]), int(kpsA[queryIdx][1]))ptB = (int(kpsB[trainIdx][0]) + wA, int(kpsB[trainIdx][1]))cv2.line(vis, ptA, ptB, (0, 255, 0), 1)# 返回可视化结果return vis
4. 图像拼接
def stitch(images, ratio=0.75, reprojThresh=4.0,showMatches=False):#获取输入图片(imageB, imageA) = images#检测A、B图片的SIFT关键特征点,并计算特征描述子(kpsA, featuresA) = detectAndDescribe(imageA)(kpsB, featuresB) = detectAndDescribe(imageB)# 匹配两张图片的所有特征点,返回匹配结果M = matchKeypoints(kpsA, kpsB, featuresA, featuresB, ratio, reprojThresh)# 如果返回结果为空,没有匹配成功的特征点,退出算法if M is None:return None# 否则,提取匹配结果# H是3x3视角变换矩阵 (matches, H, status) = M# 将图片A进行视角变换,result是变换后图片result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))cv_show('result', result)# 将图片B传入result图片最左端result[0:imageB.shape[0], 0:imageB.shape[1]] = imageBcv_show('result', result)# 检测是否需要显示图片匹配if showMatches:# 生成匹配图片vis = drawMatches(imageA, imageB, kpsA, kpsB, matches, status)# 返回结果return (result, vis)# 返回匹配结果return result
Python实现图像全景拼接相关推荐
- 可以使用的图像全景拼接opencv
引自:基于Python和OpenCV实现图像的全景拼接_半濠春水的博客-CSDN博客_python opencv 图片合成 使用环境opencv4.5.4.58,python3.6,numpy1.19 ...
- Python 对图像进行base64编码及解码读取为numpy、opencv、matplot需要的格式
Python 对图像进行base64编码及解码读取为numpy.opencv.matplot需要的格式 1. 效果图 2. 源码 参考 这篇博客将介绍Python如何对图像进行base64编解码及读取 ...
- 使用OpenCV和Python计算图像的“彩色度”
使用OpenCV和Python计算图像"彩色度" 1. 效果图 2. 炫彩度量方法是什么? 3. 源代码 参考 你是否尝试过计算每个图像的炫彩值,并根据炫彩值对自己的图像数据集进行 ...
- 【python】图像映射:单应性变换与图像扭曲
[python]图像映射:单应性变换与图像扭曲 单应性变换(Homography) 图像扭曲(仿射变换) 图中图 分段仿射扭曲 单应性变换(Homography) 单应性变换(Homography)即 ...
- Python计算机视觉——图像到图像的映射
Python计算机视觉--图像到图像的映射 文章目录 Python计算机视觉--图像到图像的映射 写在前面 1 单应性变换 1.1 直接线性变换算法 1.2 仿射变换 2 图像扭曲 2.1 图像中的图 ...
- 使用 Python 的图像隐写术
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 今天,世界正在见证前所未有的数据爆炸,我们每天产生的数据量确实令人 ...
- Python垂直翻转图像(Vertically Flip Image)
Python垂直翻转图像(Vertically Flip Image) 目录 Python垂直翻转图像(Vertically Flip Image) #原始图像 #垂直图像翻转
- Python为图像添加文本内容(Writing Text on Image)
Python为图像添加文本内容(Writing Text on Image) #原始图像 #图像添加文本 # from PIL import Image, ImageDraw, ImageFontim ...
- Python为图像添加水印(add watermark to an image)
Python为图像添加水印(add watermark to an image) 目录 Python为图像添加水印(add watermark to an image) #原始图像
最新文章
- 卷进大厂系列之LeetCode刷题笔记:长度最小的子数组(中等)
- mysql 取某个范围内随机日期
- 2015-07-22 JQuery 第二课(JQ元素获取,添加,删除,判断,遍历,取值,样式设置,改变对象,切换)...
- Java设计模式(学习整理)---策略模式
- FastDFS集群部署
- Struts标签和OGNL表达式
- J2SE综合对java util的总结 一
- 网络安全:图片防盗链的实现原理
- C# WPF开源控件库:MahApps.Metro
- 织梦php远程连接数据库,用PHP连接Oracle for NT 远程数据库
- vue 使用了浏览器的刷新之后报错_vue调试工具vue-devtools的安装
- 【lucene】lucene 高级搜索
- mybatis基础_动态代理开发
- 2021年4月蓝桥杯软件类省赛:题目+解析(完整版)
- 35 红外接收头在linux内核里的驱动
- oppo preloader驱动_手机企业冲向IoT新赛道,HOMA格局下OPPO有何不同?
- 【Luogu P1878】舞蹈课
- 试题 算法提高 断案
- P5304旅行者(比bk201还要流氓的解法)
- hazelcast java_Spring Boot和Hazelcast使用详解