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 17 Python
Django框架模板介绍
Jan 15 Python
Python 安装第三方库 pip install 安装慢安装不上的解决办法
Jun 18 Python
Python OpenCV调用摄像头检测人脸并截图
Aug 20 Python
python requests使用socks5的例子
Jul 25 Python
Python递归函数 二分查找算法实现解析
Aug 12 Python
pandas条件组合筛选和按范围筛选的示例代码
Aug 26 Python
python3.6环境下安装freetype库和基本使用方法(推荐)
May 10 Python
Python生成器next方法和send方法区别详解
May 30 Python
如何在mac下配置python虚拟环境
Jul 06 Python
利用python汇总统计多张Excel
Sep 22 Python
python实现图片转字符画
Feb 19 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
收音机频率指针指示不准确和灵敏度低问题
2021/03/02 无线电
php实现文件下载实例分享
2014/06/02 PHP
php上传文件并显示上传进度的方法
2015/03/24 PHP
PHP实现查询两个数组中不同元素的方法
2016/02/23 PHP
PHP判断json格式是否正确的实现代码
2017/09/20 PHP
Gird组件 Part-3:范例RSSFeed Viewer
2007/03/10 Javascript
ExtJS的FieldSet的column列布局
2009/11/20 Javascript
cnblogs TagCloud基于jquery的实现代码
2010/06/11 Javascript
JS target与currentTarget区别说明
2011/08/28 Javascript
jQuery显示和隐藏 常用的状态判断方法
2015/01/29 Javascript
可以浮动某个物体的jquery控件用法实例
2015/07/24 Javascript
javascript中判断json的方法总结
2015/08/27 Javascript
jQuery hover事件简单实现同时绑定2个方法
2016/06/07 Javascript
jQuery表单事件实例代码分享
2016/08/18 Javascript
AngulerJS学习之按需动态加载文件
2017/02/13 Javascript
JavaScript 上传文件(psd,压缩包等),图片,视频的实现方法
2017/06/19 Javascript
利用VS Code开发你的第一个AngularJS 2应用程序
2017/12/15 Javascript
vue多页面开发和打包正确处理方法
2018/04/20 Javascript
jQuery基于随机数解决中午吃什么去哪吃问题示例
2018/12/29 jQuery
Vue之beforeEach非登录不能访问的实现(代码亲测)
2019/07/18 Javascript
vue 获取视频时长的实例代码
2019/08/20 Javascript
vue-router 路由传参用法实例分析
2020/03/06 Javascript
python中的插值 scipy-interp的实现代码
2018/07/23 Python
python实现剪切功能
2019/01/23 Python
用django设置session过期时间的方法解析
2019/08/05 Python
沙龙级头发造型工具:FOXYBAE
2018/07/01 全球购物
美国中西部家用医疗设备商店:Med Mart(轮椅、踏板车、升降机等)
2019/04/26 全球购物
世界上最伟大的马产品:Equiderma
2020/01/07 全球购物
Prototype如何更新局部页面
2013/03/03 面试题
热能动力工程毕业生自荐信
2013/11/07 职场文书
学前教育求职自荐信范文
2013/12/25 职场文书
大学班级计划书
2014/04/29 职场文书
节水标语大全
2014/06/11 职场文书
上课睡觉检讨书300字
2014/11/18 职场文书
2016教师年度考核评语大全
2015/12/01 职场文书
俄罗斯十大城市人口排名,第三首都仅排第六,第二是北方首都
2022/03/20 杂记