计算机视觉—opencv图像拼接

文章目录

        • 一、图像拼接
          • 1、图像拼接技术
          • 2、图像拼接算法分类
        • 二、图像拼接基本步骤
          • 1、基本流程
        • 三、图像拼接原理
          • 1、特征匹配
          • 2、计算图像之间的变换结构
          • 3、图像配准
          • 4、图像变形
          • 5、根据multi-band bleing策略实现融合
          • 6、通过graph cut寻找拼接缝
        • 四、对比实验
          • 1、实验目的
          • 2、实验过程
        • 五、opencv实现图像拼接
        • 六、总结

一、图像拼接

1、图像拼接技术

图像拼接技术就是将数张有重叠部分的图像(可能是不同时间、不同视角或者不同传感器获得的)拼成一幅无缝的全景图或高分辨率图像的技术。
在医学成像、计算机视觉、卫星数据、军事目标自动识别等领域具有重要意义。

2、图像拼接算法分类

图像拼接目前有很多算法,图像拼接的质量,主要依赖于图像的配准程度,因此通过不同的图像匹配方式将算法分为以下两种:

  1. 基于区域相关拼接算法
    该算法比较传统和普遍,从待拼接图像的灰度值出发,对待配准图像中一块区域与参考图像中的相同尺寸的区域使用最小二乘法或者其它数学方法计算其灰度值的差异(1.通过累加各点灰度的差值,2.计算两块区域的对应像素点灰度值的相关系数,相关系数越大,则两块图像的匹配程度越高,3.两者中计算相关系数的效果更好)。对此差异比较后来判断待拼接图像重叠区域的相似程度,由此得到待拼接图像重叠区域的范围和位置,从而实现图像拼接。
    也可以通过FFT 变换将图像由时域变换到频域,然后再进行配准。对位移量比较大的图像,可以先校正图像的旋转,然后建立两幅图像之间的映射关系。
  2. 基于特征相关拼接算法
    于特征的配准方法不是直接利用图像的像素值,而是通过像素导出图像的特征,然后以图像特征为标准,对图像重叠部分的对应特征区域进行搜索匹配,该类拼接算法有比较高的健壮性和鲁棒性。
    在两幅图像对应的特征集中利用特征匹配算法尽可能地将存在对应关系的特征对选择出来。一系列的图像分割技术都被用到特征的抽取和边界检测上。

二、图像拼接基本步骤

1、基本流程
  1. 根据给定图像/集,实现特征匹配
  2. 通过匹配特征计算图像之间的变换结构
  3. 利用图像变换结构,实现图像映射
  4. 针对叠加后的图像,采用APAP之类的算法, 对齐特征点
  5. 通过图割方法,自动选取拼接缝
  6. 根据multi-band bleing策略实现融合

三、图像拼接原理

1、特征匹配

特征是要匹配的两个输入图像中的元素,为了给图像提供更好的特征匹配,采用角点匹配,进行定量测量。在视点变化时,角点特征是稳定的。角点检测算法有Harris角点检测算法、SIFT特征点检测算法、FAST角点检测算法、SURF特征点检测算法。
本次实验使用的Opencv stitch源码中默认第一选择是SURF特征点检测,第二是ORB特征点检测。
SURF(Speeded Up Robust Features)改进了特征的提取和描述方式,用一种更为高效的方式完成特征的提取和描述。它是SIFT的高效变种,也是提取尺度不变特征,算法步骤与SIFT算法大致相同,但采用的方法不一样,SURF算法要比SIFT算法更高效。

2、计算图像之间的变换结构

SIFT算法:变换过程在上一篇博客有详细介绍。
SURF算法:

  1. SURF使用Hessian矩阵来检测特征点,该矩阵是x,y方向的二阶导数矩阵,可测量一个函数的局部曲率,其行列式值代表像素点周围的变化量,特征点需取行列式值的极值点。
  2. 特征点定位:通过特征点邻近信息插补来定位特征点。
  3. 方向定位:通过计算特征点周围像素点x,y方向的哈尔小波变换,并将x,y方向的变换值在xy平面某一角度区间内相加组成一个向量,在所有的向量当中最长的(即x、y分量最大的)即为此特征点的方向。
  4. 特征描述子:选定了特征点的方向后,其周围相素点需要以此方向为基准来建立描述子。此时以 5 ∗ 5 5*5 55个像素点为一个子区域,取特征点周围 20 ∗ 20 20*20 2020个像素点的范围共16个子区域,计算子区域内的x、y方向(此时以平行特征点方向为x、垂直特征点方向为y的哈尔小波转换总和Σdx、ΣdyΣdx、Σdy与其向量长度总和Σ|dx|、Σ|dy|Σ|dx|、Σ|dy|共四个量值,共可产生一个64维的描述子。
  5. 如果两个特征点的矩阵迹正负号相同,代表这两个特征具有相同方向上的对比度变化,如果不同,说明这两个特征点的对比度变化方向是相反的,即使欧氏距离为0,也直接予以排除。
  6. 用方型滤波器取代SIFT中的高斯滤波器,利用积分图(计算位于滤波器方型的四个角落值)大幅提高运算速度。

3、图像配准

在特征点被检测出来之后,这样子我们就可以得到了两幅待拼接图的匹配点集,接下来我们进行图像的配准,即将两张图像转换为同一坐标下,我们需要以某种方式将它们关联起来。
因为是在使用opencv的条件下面做的实验,这里我们需要使用findHomography函数来求得变换矩阵。但是需要注意的是,findHomography函数所要用到的点集是Point2f类型的,所有我们需要对我们刚得到的点集GoodMatchePoints再做一次处理,使其转换为Point2f类型的点集。

vector imagePoints1, imagePoints2;

for (int i = 0; i

这样子,我们就可以拿着imagePoints1, imagePoints2去求变换矩阵了,并且实现图像配准。值得注意的是findHomography函数的参数中我们选泽了CV_RANSAC,这表明我们选择RANSAC算法继续筛选可靠地匹配点,这使得匹配点解更为精确。
RANSAC原理在上一节也有就介绍,在此简述一下其原理:
从数据集中随机选取一组数据并认为是有效数据(内点)来确定待定参数模型,以此模型测试数据集中的所有数据,满足该模型的数据成为内点,反之为外点(通常为噪声、错误测量或不正确数据的点),迭代执行,直到某一个参数模型得到的内点数最大,则该模型为最优模型。
RANSAC算法在此应用于剔除错误匹配点,提高匹配的精度。

4、图像变形

首先计算每个输入图像的变形图像坐标范围,得到输出图像大小,可以很容易地通过映射每个源图像的四个角并且计算坐标(x,y)的最小值和最大值确定输出图像的大小。最后,需要计算指定参考图像原点相对于输出全景图的偏移量的偏移量xoffset和偏移量yoffset。
下一步是使用上面所述的反向变形,将每个输入图像的像素映射到参考图像定义的平面上,分别执行点的正向变形和反向变形。

5、根据multi-band bleing策略实现融合

融合目的在于拼缝消除, Multi-Band能够达到比较好的融合效果,但是效率低,采用Laplacian(拉普拉斯)金字塔,通过对相邻两层的高斯金字塔进行差分,将原图分解成不同尺度的子图,对每一个之图进行加权平均,得到每一层的融合结果,最后进行金字塔的反向重建,得到最终融合效果过程。

6、通过graph cut寻找拼接缝
计算机视觉—opencv图像拼接_第1张图片

上图中,我们把两个Patch拼合到一起,它们首先被放置为有一定重合区域。为了让两者之间的缝隙尽可能的不明显,我们需要知道一个分割线(cut),在这个分割线的左边,图像像素由A贡献,相反在其右边,图像像素则由B贡献。
这里我们将输出的图像看做是由”图(Graph)“所表示,并且给这个Graph两个端点,一个是A,一个是B:
计算机视觉—opencv图像拼接_第2张图片
上图中,标有数字的节点实际上是重合区域的像素,节点之间的连接都是有代价的。我们需要拿起剪刀从某个连接上剪掉某些连接,并且要使得被剪掉的连接的代价之和最小化,这就是最典型的图算法中的最小割问题(min cut),它也对应着所谓的最大流问题(max flow)。
那么,如何定义连接之间的代价呢?这里假设在重合区域两个相邻的输出像素分别是s和t。我们知道输出的像素既可能来自于A,也可能来自于B,于是我们用A(s),B(s)来表示s点在A图和B图的颜色, 用A(t),B(t)来表示t点在A图和B图的颜色。
于是,s点和t点的连接的代价被定义为:
在这里插入图片描述
我们要做的就是寻找一个切割缝,最小化 M ( s , t , A , B ) M(s,t,A,B) M(s,t,A,B)当找到这条缝之后,左边的像素从A中拷贝而来,而右边的像素则从B中拷贝而来即可。
接下来就可以不断的拼合更多的Patch,目标是用越来越多次的覆盖输出图片中的缝隙,使得图像重合部分越来越多,直到代价值收敛。

四、对比实验

1、实验目的

实现两张图片的全景拼接,图片有重叠部分
进行三组不同场景的实验

2、实验过程
  1. 以某点为固定点拍摄的场景,景深较小
    拼接前:

拼接后:

小结:由于光照不同,可以通过色差,看出缝隙的位置。所以在室外景深小的图像中,该图除了后期的色差还未融合,其他地方的衔接都比较完美,效果较好。拼接之后的图片左侧有点倾斜是因为拍摄时的角度有所倾斜,所以整个画面呈现“凸起”状态。

  1. 视差变化大的场景
    拼接前:
拼接后:


小结:不管是远处还是近处,因为其是在同一光照下,同一角度,拍摄的同一尺寸的图片,其拼接效果非常好,近处的枯草墙面,和远处的楼房都在一张图片里面拼接的很完整,几乎看不出缝隙在哪(我的确没有发现),即使是视差较大,但是效果很好,应该是因为没有太大角度变化和尺度变化加上opencv的这个拼接函数的确很强大的原因。。。。

  1. 场景有尺寸变换
    拼接前:
拼接后:


小结:在这组实验中,可以发现拼接后的图片有明显的“扭曲”现象,因为其中一张图片的角度变化较大,图像中的水平面处于倾斜状态。为了实现拼接,应该是对图像进行了旋转变换处理,将缝隙边缘部分尽量重叠在一起后进行图片融合。所以最后结图片呈现不是很完美,但是能把两张图片中的特征融合在一起。
实验小结:要做图像拼接,避免产生“鬼影”现象,尽量保证使用的是静态图片,不要加入一些动态因素干扰拼接。

五、opencv实现图像拼接

Opencv stitch源码
调用函数实现:

# -*- coding: utf-8 -*-
import numpy as np
import cv2
from cv2 import Stitcher

if __name__ == "__main__":
    img1 = cv2.imread(r'D:\CVphoto\03205.jpg')
    img2 = cv2.imread(r'D:\CVphoto\03203.jpg')
    stitcher = cv2.createStitcher(False)
    #stitcher = cv2.Stitcher.create(cv2.Stitcher_PANORAMA), 根据不同的OpenCV版本来调用
    (_result, pano) = stitcher.stitch((img1, img2))
    #cv2.imshow('pano',pano)
    res = cv2.resize(pano, (1000, 600), interpolation=cv2.INTER_CUBIC)
    cv2.imshow('llg.jpg', res)
    cv2.waitKey(0)

六、总结

  1. 出现错误
    error: C:\projects\opencv-python\opencv\modules\imgproc\src\resize.cpp:4044: error: (-215) ssize.width > 0 && ssize.height > 0 in function cv::resize
    在实验过程中,进行图片拼接时,发现并不是所有图片都能通过这个opencv函数实现拼接,经过检查,图片大小与路径读入没有问题。
    但是这个错误是因为image的存在None值,需要增加一个判断语句
if image is not None:
res = cv2.resize(pano, (1000, 600), interpolation=cv2.INTER_CUBIC)

不过这只是让程序不再报错,依然没有拼接结果,直接进行imshow也是没有拼接结果的,
因此初步判断是因为通过opencv函数stitch形成的拼接结果为空,所以不能将图片进行resize和imshow,具体原因希望可以有空探究一下。
目前暂时只能通过改变图片寻找可以进行拼接的探讨实验。

  1. 实现过程中
    本次实验是直接利用opnecv中的stitch函数实现图像拼接,当然效果也是相当好的,但是因为其实现很复杂,而且代码量很庞大,其实在一些小应用下的拼接有点杀鸡用牛刀的感觉
    课本《计算机视觉》上面有提供通过SIFT的特征匹配,然后进行图像拼接的源码,希望有机会可以进行对比实验,对比两种算法对于图像拼接的优缺点。

  2. 匹配算法改进
    在之前进行图像特征匹配时,使用的一直是SIFT特征匹配,但是这次实验中接触了SURF算法。
    用SIFT算法来实现图像拼接是很常用的方法,但是因为SIFT计算量很大,所以在速度要求很高的场合下不再适用。所以,它的改进方法SURF因为在速度方面有了明显的提高(速度是SIFT的3倍),所以在图像拼接领域还是大有作为。虽说SURF精确度和稳定性不及SIFT,但是其综合能力还是优越一些。下面将详细介绍拼接的主要步骤。

你可能感兴趣的:(计算机视觉—opencv图像拼接)