python实现图像全景拼接


Posted in Python onMarch 27, 2020

图像的全景拼接包括三大部分:特征点提取与匹配、图像配准、图像融合。

1、基于SIFT的特征点的提取与匹配

利用Sift提取图像的局部特征,在尺度空间寻找极值点,并提取出其位置、尺度、方向信息。

具体步骤:

1). 生成高斯差分金字塔(DOG金字塔),尺度空间构建

2). 空间极值点检测(关键点的初步查探)

3). 稳定关键点的精确定位

4). 稳定关键点方向信息分配

5). 关键点描述

6). 特征点匹配

2、图像配准

图像配准是一种确定待拼接图像间的重叠区域以及重叠位置的技术,它是整个图像拼接的核心。本节采用的是基于特征点的图像配准方法,即通过匹配点对构建图像序列之间的变换矩阵,从而完成全景图像的拼接。

变换矩阵H求解是图像配准的核心,其求解的算法流程如下。

1)检测每幅图像中特征点。

2)计算特征点之间的匹配。

3)计算图像间变换矩阵的初始值。

4)迭代精炼H变换矩阵。

5)引导匹配。用估计的H去定义对极线附近的搜索区域,进一步确定特征点的对应。

6)重复迭代4)和5)直到对应点的数目稳定为止。

设图像序列之间的变换为投影变换

可用4组最佳匹配计算出H矩阵的8 个自由度参数hi=( i=0,1,...,7),并以此作为初始值。

为了提高图像配准的精度,本节采用RANSAC算法对图像变换矩阵进行求解与精炼,达到了较好的图像拼接效果。RANSAC算法的思想简单而巧妙:首先随机地选择两个点,这两个点确定了一条直线,并且称在这条直线的一定范围内的点为这条直线的支撑。这样的随机选择重复数次,然后,具有最大支撑集的直线被确认为是样本点集的拟合。在拟合的误差距离范围内的点被认为是内点,它们构成一致集,反之则为外点。根据算法描述,可以很快判断,如果只有少量外点,那么随机选取的包含外点的初始点集确定的直线不会获得很大的支撑,值得注意的是,过大比例的外点将导致RANSAC算法失败。在直线拟合的例子中,由点集确定直线至少需要两个点;而对于透视变换,这样的最小集合需要有4个点。

3、图像融合

因为相机和光照强度的差异,会造成一幅图像内部,以及图像之间亮度的不均匀,拼接后的图像会出现明暗交替,这样给观察造成极大的不便。 亮度与颜色均衡处理,通常的处理方式是通过相机的光照模型,校正一幅图像内部的光照不均匀性,然后通过相邻两幅图像重叠区域之间的关系,建立相邻两幅图像之间直方图映射表,通过映射表对两幅图像做整体的映射变换,最终达到整体的亮度和颜色的一致性。

具体实现:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

if __name__ == '__main__':
top, bot, left, right = 100, 100, 0, 500
img1 = cv.imread('1.jpg')
img2 = cv.imread('2.jpg')
srcImg = cv.copyMakeBorder(img1, top, bot, left, right, cv.BORDER_CONSTANT, value=(0, 0, 0))
testImg = cv.copyMakeBorder(img2, top, bot, left, right, cv.BORDER_CONSTANT, value=(0, 0, 0))
img1gray = cv.cvtColor(srcImg, cv.COLOR_BGR2GRAY)
img2gray = cv.cvtColor(testImg, cv.COLOR_BGR2GRAY)
sift = cv.xfeatures2d_SIFT().create()
# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1gray, None)
kp2, des2 = sift.detectAndCompute(img2gray, None)
# FLANN parameters
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)

# Need to draw only good matches, so create a mask
matchesMask = [[0, 0] for i in range(len(matches))]

good = []
pts1 = []
pts2 = []
# ratio test as per Lowe's paper
for i, (m, n) in enumerate(matches):
if m.distance < 0.7*n.distance:
good.append(m)
pts2.append(kp2[m.trainIdx].pt)
pts1.append(kp1[m.queryIdx].pt)
matchesMask[i] = [1, 0]

draw_params = dict(matchColor=(0, 255, 0),
singlePointColor=(255, 0, 0),
matchesMask=matchesMask,
flags=0)
img3 = cv.drawMatchesKnn(img1gray, kp1, img2gray, kp2, matches, None, **draw_params)
plt.imshow(img3, ), plt.show()

rows, cols = srcImg.shape[:2]
MIN_MATCH_COUNT = 10
if len(good) > MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5.0)
warpImg = cv.warpPerspective(testImg, np.array(M), (testImg.shape[1], testImg.shape[0]), flags=cv.WARP_INVERSE_MAP)

for col in range(0, cols):
if srcImg[:, col].any() and warpImg[:, col].any():
left = col
break
for col in range(cols-1, 0, -1):
if srcImg[:, 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 srcImg[row, col].any():
res[row, col] = warpImg[row, col]
elif not warpImg[row, col].any():
res[row, col] = srcImg[row, col]
else:
srcImgLen = float(abs(col - left))
testImgLen = float(abs(col - right))
alpha = srcImgLen / (srcImgLen + testImgLen)
res[row, col] = np.clip(srcImg[row, col] * (1-alpha) + warpImg[row, col] * alpha, 0, 255)

# opencv is bgr, matplotlib is rgb
res = cv.cvtColor(res, cv.COLOR_BGR2RGB)
# show the result
plt.figure()
plt.imshow(res)
plt.show()
else:
print("Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT))
matchesMask = None

实验结果:

1、室内场景:

python实现图像全景拼接

原图1

python实现图像全景拼接

原图2

拼接后:

python实现图像全景拼接

2、室外场景:

场景1:

python实现图像全景拼接

原图1

python实现图像全景拼接

原图2

拼接后:

python实现图像全景拼接

场景2:

python实现图像全景拼接

原图1

python实现图像全景拼接

原图2

拼接后:

python实现图像全景拼接

场景3:

python实现图像全景拼接

原图1

python实现图像全景拼接

原图2

拼接后:

python实现图像全景拼接

总结:

本文分别针对室内和室外两种情况对两张图像做全景拼接,发现室内情况下拼接的效果较为好。在室外场景1情况下,两张图像有近景和远景结合,两张图像拼接后近景的图像被放大并有一定程度的倾斜;在场景2中,两张图像都是远景,拼接后的效果还不错但是在拼接后图像的中上方出现了拼接缝;场景3是在不同明亮程度下图像的拼接可以发现拼接后的图像出现明显的明暗差距,并且拼接缝明显两张图像没有很好的拼接在一起,出现很多没有重合的地方。

本实验最初是用opencv-contrib3.4.5版本,但是由于sift的专利限制无法使用,随后用opencv-contriv3.4.2代码可以运行,不会出现问题。方法:先卸载当前版本的opencv并安装:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.2.16

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

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

Python 相关文章推荐
python回调函数中使用多线程的方法
Dec 25 Python
python+opencv实现动态物体识别
Jan 09 Python
scrapy爬虫完整实例
Jan 25 Python
将TensorFlow的模型网络导出为单个文件的方法
Apr 23 Python
matplotlib给子图添加图例的方法
Aug 03 Python
Python基于matplotlib画箱体图检验异常值操作示例【附xls数据文件下载】
Jan 07 Python
使用python实现语音文件的特征提取方法
Jan 09 Python
python爬取盘搜的有效链接实现代码
Jul 20 Python
pytorch 自定义数据集加载方法
Aug 18 Python
对pytorch的函数中的group参数的作用介绍
Feb 18 Python
python-xpath获取html文档的部分内容
Mar 06 Python
浅析Python模块之间的相互引用问题
Feb 26 Python
如何在Python 游戏中模拟引力
Mar 27 #Python
Python 实现平台类游戏添加跳跃功能
Mar 27 #Python
django配置app中的静态文件步骤
Mar 27 #Python
使用卷积神经网络(CNN)做人脸识别的示例代码
Mar 27 #Python
django实现HttpResponse返回json数据为中文
Mar 27 #Python
python对XML文件的操作实现代码
Mar 27 #Python
Python Socketserver实现FTP文件上传下载代码实例
Mar 27 #Python
You might like
用libTemplate实现静态网页的生成
2006/10/09 PHP
php导入csv文件碰到乱码问题的解决方法
2014/02/10 PHP
php编写的抽奖程序中奖概率算法
2015/05/14 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
javaScript 删除字符串空格多种方法小结
2012/10/24 Javascript
在Javascript中 声明时用&quot;var&quot;与不用&quot;var&quot;的区别
2013/04/15 Javascript
javascript动态创建表格及添加数据实例详解
2015/05/13 Javascript
jQuery中 prop() attr()使用详解
2015/05/19 Javascript
JavaScript优化专题之Loading and Execution加载和运行
2016/01/20 Javascript
Bootstrap富文本组件wysiwyg数据保存到mysql的方法
2016/05/09 Javascript
Bootstrap Validator 表单验证
2016/07/25 Javascript
AngularJS基础 ng-include 指令示例讲解
2016/08/01 Javascript
详解Bootstrap的iCheck插件checkbox和radio
2016/08/24 Javascript
在DWR中实现直接获取一个JAVA类的返回值的两种方法
2016/12/25 Javascript
Javascript基础回顾之(二) js作用域
2017/01/31 Javascript
AngularJS 霸道的过滤器小结
2017/04/26 Javascript
Vue.js实现价格计算器功能
2020/03/30 Javascript
浅谈vue2 单页面如何设置网页title
2017/11/08 Javascript
Vue.js图片预览插件使用详解
2018/08/27 Javascript
详解微信小程序文件下载--视频和图片
2019/04/24 Javascript
浅谈nuxtjs校验登录中间件和混入(mixin)
2020/11/06 Javascript
[01:03:50]DOTA2-DPC中国联赛 正赛 CDEC vs DLG BO3 第二场 2月7日
2021/03/11 DOTA
python抓取网页图片并放到指定文件夹
2014/04/24 Python
python3解析库lxml的安装与基本使用
2018/06/27 Python
详解pyinstaller生成exe的闪退问题解决方案
2020/06/19 Python
Java byte数组操纵方式代码实例解析
2020/07/22 Python
浅析python 字典嵌套
2020/09/29 Python
泰国王权免税店官方网站:KingPower
2019/03/11 全球购物
Crabtree & Evelyn欧盟:豪华洗浴、身体和护发
2021/03/09 全球购物
企业党员个人自我评价
2014/09/20 职场文书
群众路线剖析材料范文
2014/10/09 职场文书
2014年党委工作总结
2014/11/22 职场文书
2015年乡镇纪检工作总结
2015/04/22 职场文书
2015年副班长工作总结
2015/05/15 职场文书
2016年寒假家长评语
2015/10/10 职场文书
2019同学聚会主持词
2019/05/06 职场文书