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设计模式之中介模式简单示例
Jan 09 Python
python 多线程中子线程和主线程相互通信方法
Nov 09 Python
在Python中Dataframe通过print输出多行时显示省略号的实例
Dec 22 Python
python实现大转盘抽奖效果
Jan 22 Python
python利用跳板机ssh远程连接redis的方法
Feb 19 Python
Django框架实现的普通登录案例【使用POST方法】
May 15 Python
python实现获取单向链表倒数第k个结点的值示例
Oct 24 Python
Pyspark获取并处理RDD数据代码实例
Mar 27 Python
在Matplotlib图中插入LaTex公式实例
Apr 17 Python
python装饰器代码深入讲解
Mar 01 Python
聊聊Python pandas 中loc函数的使用,及跟iloc的区别说明
Mar 03 Python
Python GUI编程之tkinter 关于 ttkbootstrap 的使用详解
Mar 03 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
Apache+php+mysql在windows下的安装与配置图解(最新版)
2008/11/30 PHP
CentOS安装php v8js教程
2015/02/26 PHP
laravel 实现用户登录注销并限制功能
2019/10/24 PHP
JavaScript delete 属性的使用
2009/10/08 Javascript
让div层随鼠标移动的实现代码 ie ff
2009/12/18 Javascript
jquery插件制作 提示框插件实现代码
2012/08/17 Javascript
jQuery的3种请求方式$.post,$.get,$.getJSON
2014/03/28 Javascript
单击和双击事件的冲突处理示例代码
2014/04/03 Javascript
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
2015/01/01 NodeJs
js实现顶部可折叠的菜单工具栏效果实例
2015/05/09 Javascript
在JavaScript中处理数组之reverse()方法的使用
2015/06/09 Javascript
javascript从作用域链谈闭包
2020/07/29 Javascript
浅谈$('div a') 与$('div&gt;a')的区别
2016/07/18 Javascript
AngularJS入门教程之路由机制ngRoute实例分析
2016/12/13 Javascript
js获取地址栏中传递的参数(两种方法)
2017/02/08 Javascript
babel基本使用详解
2017/02/17 Javascript
MUI 解决动态列表页图片懒加载再次加载不成功的bug问题
2017/04/13 Javascript
js解决软键盘遮挡输入框的问题分享
2017/12/19 Javascript
Vue表单及表单绑定方法
2018/09/04 Javascript
深入理解 Koa 框架中间件原理
2018/10/18 Javascript
Vue组件模板的几种书写形式(3种)
2020/02/19 Javascript
详解Python列表赋值复制深拷贝及5种浅拷贝
2019/05/15 Python
python中的decimal类型转换实例详解
2019/06/26 Python
Python pandas用法最全整理
2019/08/04 Python
利用python实现PSO算法优化二元函数
2019/11/13 Python
Python 爬取必应壁纸的实例讲解
2020/02/24 Python
解决Python中导入自己写的类,被划红线,但不影响执行的问题
2020/07/13 Python
python+opencv3.4.0 实现HOG+SVM行人检测的示例代码
2021/01/28 Python
美国一家专业的太阳镜网上零售商:Solstice太阳镜
2016/07/25 全球购物
入党自我鉴定范文
2013/10/04 职场文书
十佳班主任事迹材料
2014/01/18 职场文书
升旗仪式主持词
2014/03/19 职场文书
团日活动总结书格式
2014/05/08 职场文书
青年志愿者服务活动总结
2015/05/06 职场文书
大学生创业,为什么都会选择快餐饮?
2019/08/08 职场文书
Python词云的正确实现方法实例
2021/05/08 Python