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爬虫框架scrapy实战之爬取京东商城进阶篇
Apr 24 Python
Python数据结构与算法之使用队列解决小猫钓鱼问题
Dec 14 Python
深入浅析python with语句简介
Apr 11 Python
python3+PyQt5图形项的自定义和交互 python3实现page Designer应用程序
Jul 20 Python
详解Python中的四种队列
May 21 Python
python中的json总结
Oct 11 Python
Python处理PDF与CDF实例
Feb 26 Python
jupyter notebook中美观显示矩阵实例
Apr 17 Python
Selenium元素定位的30种方式(史上最全)
May 11 Python
Python基于xlutils修改表格内容过程解析
Jul 28 Python
详解Selenium 元素定位和WebDriver常用方法
Dec 04 Python
python读取mnist数据集方法案例详解
Sep 04 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
PHP中source #N问题的解决方法
2014/01/27 PHP
Laravel 5框架学习之用户认证
2015/04/09 PHP
将PHP从5.3.28升级到5.3.29时Nginx出现502错误
2015/05/09 PHP
PHP微信开发之二维码生成类
2015/06/26 PHP
javascript判断单选框或复选框是否选中方法集锦
2007/04/04 Javascript
JavaScript栏目列表隐藏/显示简单实现
2013/04/03 Javascript
Javascript简单改变表单元素背景的方法
2015/07/15 Javascript
jQuery 获取跨域XML(RSS)数据的相关总结分析
2016/05/18 Javascript
BootStrap创建响应式导航条实例代码
2016/05/31 Javascript
JavaScript事件学习小结(三)js事件对象
2016/06/09 Javascript
BootStrap Datepicker 插件修改为默认中文的实现方法
2017/02/10 Javascript
Vue自定义全局Toast和Loading的实例详解
2019/04/18 Javascript
微信小程序实现动态列表项的顺序加载动画
2019/07/25 Javascript
JS实现商城秒杀倒计时功能(动态设置秒杀时间)
2019/12/12 Javascript
jQuery实现动态操作table行
2020/11/23 jQuery
[01:29:17]RNG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.23
2019/09/05 DOTA
python实现文件名批量替换和内容替换
2014/03/20 Python
python中常用的九种预处理方法分享
2016/09/11 Python
python实现ip代理池功能示例
2019/07/05 Python
pow在python中的含义及用法
2019/07/11 Python
解决Python正则表达式匹配反斜杠''\''问题
2019/07/17 Python
django 多对多表的创建和插入代码实现
2019/09/09 Python
Python基于内置库pytesseract实现图片验证码识别功能
2020/02/24 Python
K最近邻算法(KNN)---sklearn+python实现方式
2020/02/24 Python
python数字类型math库原理解析
2020/03/02 Python
Jupyter Notebook 实现正常显示中文和负号
2020/04/24 Python
Pycharm中配置远程Docker运行环境的教程图解
2020/06/11 Python
纽约JewelryAffairs珠宝店:精细金银时尚首饰
2017/02/05 全球购物
VELTRA台湾:世界自由行专家
2017/08/15 全球购物
英国珠宝钟表和家居礼品精品店:David Shuttle
2018/02/24 全球购物
营销与策划实训报告
2014/11/05 职场文书
2014年创先争优工作总结
2014/12/11 职场文书
护士工作心得体会
2016/01/25 职场文书
利用Java设置Word文本框中的文字旋转方向的实现方法
2021/06/28 Java/Android
Java实现房屋出租系统详解
2021/10/05 Java/Android
Python利用Turtle绘制哆啦A梦和小猪佩奇
2022/04/04 Python