python opencv进行图像拼接


Posted in Python onMarch 27, 2020

本文实例为大家分享了python opencv进行图像拼接的具体代码,供大家参考,具体内容如下

思路和方法

思路

1、提取要拼接的两张图片的特征点、特征描述符;
2、将两张图片中对应的位置点找到,匹配起来;
3、如果找到了足够多的匹配点,就能将两幅图拼接起来,拼接前,可能需要将第二幅图透视旋转一下,利用找到的关键点,将第二幅图透视旋转到一个与第一幅图相同的可以拼接的角度;
4、进行拼接;
5、进行拼接后的一些处理,让效果看上去更好。

实现方法

1、提取图片的特征点、描述符,可以使用opencv创建一个SIFT对象,SIFT对象使用DoG方法检测关键点,并对每个关键点周围的区域计算特征向量。在实现时,可以使用比SIFT快的SURF方法,使用Hessian算法检测关键点。因为只是进行全景图拼接,在使用SURF时,还可以调节它的参数,减少一些关键点,只获取64维而不是128维的向量等,加快速度。
2、在分别提取好了两张图片的关键点和特征向量以后,可以利用它们进行两张图片的匹配。在拼接图片中,可以使用Knn进行匹配,但是使用FLANN快速匹配库更快,图片拼接,需要用到FLANN的单应性匹配。
3、单应性匹配完之后可以获得透视变换H矩阵,用这个的逆矩阵来对第二幅图片进行透视变换,将其转到和第一张图一样的视角,为下一步拼接做准备。
4、透视变换完的图片,其大小就是最后全景图的大小,它的右边是透视变换以后的图片,左边是黑色没有信息。拼接时可以比较简单地处理,通过numpy数组选择直接把第一张图加到它的左边,覆盖掉重叠部分,得到拼接图片,这样做非常快,但是最后效果不是很好,中间有一条分割痕迹非常明显。使用opencv指南中图像金字塔的代码对拼接好的图片进行处理,整个图片平滑了,中间的缝还是特别突兀。
5、直接拼效果不是很好,可以把第一张图叠在左边,但是对第一张图和它的重叠区做一些加权处理,重叠部分,离左边图近的,左边图的权重就高一些,离右边近的,右边旋转图的权重就高一些,然后两者相加,使得过渡是平滑地,这样看上去效果好一些,速度就比较慢。如果是用SURF来做,时间主要画在平滑处理上而不是特征点提取和匹配。

python_opencv中主要使用的函数

0、基于python 3.7和对应的python-opencv

1、cv2.xfeatures2d.SURF_create ([hessianThreshold[, nOctaves[, nOctaveLayers[, extended[, upright]]]]])
该函数用于生成一个SURF对象,在使用时,为提高速度,可以适当提高hessianThreshold,以减少检测的关键点的数量,可以extended=False,只生成64维的描述符而不是128维,令upright=True,不检测关键点的方向。

2、cv2.SURF.detectAndCompute(image, mask[, descriptors[, useProvidedKeypoints]])

该函数用于计算图片的关键点和描述符,需要对两幅图都进行计算。

3、flann=cv2.FlannBasedMatcher(indexParams,searchParams)
match=flann.knnMatch(descrip1,descrip2,k=2)
flann快速匹配器有两个参数,一个是indexParams,一个是searchParams,都用手册上建议的值就可以。在创建了匹配器得到匹配数组match以后,就可以参考Lowe给出的参数,对匹配进行过滤,过滤掉不好的匹配。其中返回值match包括了两张图的描述符距离distance 、训练图(第二张)的描述符索引trainIdx 、查询的图(第一张)的描述符索引queryIdx 这几个属性。

4、M,mask=cv2.findHomography(srcPoints, dstPoints[, method[, ransacReprojThreshold[, mask]]])
这个函数实现单应性匹配,返回的M是一个矩阵,即对关键点srcPoints做M变换能变到dstPoints的位置。

5、warpImg=cv2.warpPerspective(src,np.linalg.inv(M),dsize[,dst[,flags[,borderMode[,borderValue]]]])
用这个函数进行透视变换,变换视角。src是要变换的图片,np.linalg.inv(M)是④中M的逆矩阵,得到方向一致的图片。

6、a=b.copy() 实现深度复制,Python中默认是按引用复制,a=b是a指向b的内存。

7、draw_params = dict(matchColor = (0,255,0),singlePointColor = (255,0,0),matchesMask = matchMask,flags = 2),img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
使用drawMatches可以画出匹配的好的关键点,matchMask是比较好的匹配点,之间用绿色线连接起来。

核心代码

import cv2
import numpy as np
from matplotlib import pyplot as plt
import time
MIN = 10
starttime=time.time()
img1 = cv2.imread('1.jpg') #query
img2 = cv2.imread('2.jpg') #train

#img1gray=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
#img2gray=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
surf=cv2.xfeatures2d.SURF_create(10000,nOctaves=4,extended=False,upright=True)
#surf=cv2.xfeatures2d.SIFT_create()#可以改为SIFT
kp1,descrip1=surf.detectAndCompute(img1,None)
kp2,descrip2=surf.detectAndCompute(img2,None)

FLANN_INDEX_KDTREE = 0
indexParams = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
searchParams = dict(checks=50)

flann=cv2.FlannBasedMatcher(indexParams,searchParams)
match=flann.knnMatch(descrip1,descrip2,k=2)


good=[]
for i,(m,n) in enumerate(match):
 if(m.distance<0.75*n.distance):
 good.append(m)

if len(good)>MIN:
 src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
 ano_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
 M,mask=cv2.findHomography(src_pts,ano_pts,cv2.RANSAC,5.0)
 warpImg = cv2.warpPerspective(img2, np.linalg.inv(M), (img1.shape[1]+img2.shape[1], img2.shape[0]))
 direct=warpImg.copy()
 direct[0:img1.shape[0], 0:img1.shape[1]] =img1
 simple=time.time()

#cv2.namedWindow("Result", cv2.WINDOW_NORMAL)
#cv2.imshow("Result",warpImg)
 rows,cols=img1.shape[:2]
 
 for col in range(0,cols):
 if img1[:, col].any() and warpImg[:, col].any():#开始重叠的最左端
 left = col
 break
 for col in range(cols-1, 0, -1):
 if img1[:, col].any() and warpImg[:, col].any():#重叠的最右一列
 right = col
 break

 res = np.zeros([rows, cols, 3], np.uint8)
 for row in range(0, rows):
 for col in range(0, cols):
 if not img1[row, col].any():#如果没有原图,用旋转的填充
 res[row, col] = warpImg[row, col]
 elif not warpImg[row, col].any():
 res[row, col] = img1[row, col]
 else:
 srcImgLen = float(abs(col - left))
 testImgLen = float(abs(col - right))
 alpha = srcImgLen / (srcImgLen + testImgLen)
 res[row, col] = np.clip(img1[row, col] * (1-alpha) + warpImg[row, col] * alpha, 0, 255)

 warpImg[0:img1.shape[0], 0:img1.shape[1]]=res
 final=time.time()
 img3=cv2.cvtColor(direct,cv2.COLOR_BGR2RGB)
 plt.imshow(img3,),plt.show()
 img4=cv2.cvtColor(warpImg,cv2.COLOR_BGR2RGB)
 plt.imshow(img4,),plt.show()
 print("simple stich cost %f"%(simple-starttime))
 print("\ntotal cost %f"%(final-starttime))
 cv2.imwrite("simplepanorma.png",direct)
 cv2.imwrite("bestpanorma.png",warpImg)
 
else:
 print("not enough matches!")

运行结果

原图1.jpg

python opencv进行图像拼接

原图2.jpg

python opencv进行图像拼接

特征点匹配

python opencv进行图像拼接

直接拼接和平滑对比

python opencv进行图像拼接

效果

python opencv进行图像拼接

本文已被收录到专题《python图片处理操作》 ,欢迎大家点击学习更多精彩内容。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
黑科技 Python脚本帮你找出微信上删除你好友的人
Jan 07 Python
Python的Flask框架应用程序实现使用QQ账号登录的方法
Jun 07 Python
python虚拟环境virualenv的安装与使用
Dec 18 Python
Python 中迭代器与生成器实例详解
Mar 29 Python
Django使用redis缓存服务器的实现代码示例
Apr 28 Python
Python嵌套函数,作用域与偏函数用法实例分析
Dec 26 Python
Python多进程编程multiprocessing代码实例
Mar 12 Python
使用python无账号无限制获取企查查信息的实例代码
Apr 17 Python
Python GUI之tkinter窗口视窗教程大集合(推荐)
Oct 20 Python
详解如何使用Pytest进行自动化测试
Jan 14 Python
pandas中DataFrame检测重复值的实现
May 26 Python
Python正则表达式中flags参数的实例详解
Apr 01 Python
Python爬虫爬取电影票房数据及图表展示操作示例
Mar 27 #Python
Pyspark读取parquet数据过程解析
Mar 27 #Python
Python基于pyecharts实现关联图绘制
Mar 27 #Python
Python爬虫爬取杭州24时温度并展示操作示例
Mar 27 #Python
Django添加bootstrap框架时无法加载静态文件的解决方式
Mar 27 #Python
Python itertools.product方法代码实例
Mar 27 #Python
python实现图像全景拼接
Mar 27 #Python
You might like
java微信开发之上传下载多媒体文件
2016/06/24 PHP
关于laravel-admin ueditor 集成并解决刷新的问题
2019/10/21 PHP
javascript一些不错的函数脚本代码
2008/09/10 Javascript
JQuery 1.6发布 性能提升,同时包含大量破坏性变更
2011/05/10 Javascript
解析瀑布流布局:JS+绝对定位的实现
2013/05/08 Javascript
JS自动适应的图片弹窗实例
2013/06/29 Javascript
jquery绑定事件不生效的解决方法
2014/02/11 Javascript
如何调试异步加载页面里包含的js文件
2014/10/30 Javascript
jQuery+PHP实现可编辑表格字段内容并实时保存
2015/10/09 Javascript
jQueryUI DatePicker 添加时分秒
2016/06/04 Javascript
进阶之初探nodeJS
2017/01/24 NodeJs
Vue.js 60分钟快速入门教程
2017/03/28 Javascript
MUI 解决动态列表页图片懒加载再次加载不成功的bug问题
2017/04/13 Javascript
vue+socket.io+express+mongodb 实现简易多房间在线群聊示例
2017/10/21 Javascript
微信小程序js文件改变参数并在视图上及时更新【推荐】
2018/06/11 Javascript
jQuery实现获取form表单内容及绑定数据到form表单操作分析
2018/07/03 jQuery
vue-cli 打包后提交到线上出现 &quot;Uncaught SyntaxError:Unexpected token&quot; 报错
2018/11/06 Javascript
jQuery实现带3D切割效果的轮播图功能示例【附源码下载】
2019/04/04 jQuery
修改layui的后台模板的左侧导航栏可以伸缩的方法
2019/09/10 Javascript
vue 获取url里参数的两种方法小结
2020/11/12 Javascript
Python类定义和类继承详解
2015/05/08 Python
Python使用爬虫爬取静态网页图片的方法详解
2018/06/05 Python
Django框架使用富文本编辑器Uedit的方法分析
2018/07/31 Python
Python图像处理模块ndimage用法实例分析
2019/09/05 Python
多版本python的pip 升级后, pip2 pip3 与python版本失配解决方法
2019/09/11 Python
Keras之fit_generator与train_on_batch用法
2020/06/17 Python
新西兰最大的在线设计师眼镜店:SmartBuyGlasses新西兰
2017/10/20 全球购物
文件中有一组整数,要求排序后输出到另一个文件中
2012/01/04 面试题
大学生职业生涯规划书
2014/03/14 职场文书
实习生评语
2014/04/26 职场文书
医药销售自荐书
2014/05/29 职场文书
汉语言文学毕业求职信
2014/07/17 职场文书
青年标兵事迹材料
2014/08/16 职场文书
商务宴请邀请函范文
2015/02/02 职场文书
大学运动会加油稿
2015/07/22 职场文书
golang 接口嵌套实现复用的操作
2021/04/29 Golang