OpenCV-4.x Stitching
流程图

模块详解
核心模块:
- 特征点检测与图像匹配(matchers.hpp、matchers.cpp)
- 估计相机运动,计算相机内外参(motion_estimators.hpp、motion_estimators.cpp)
- 图像变形(warpers.hpp、warpers.cpp)
- 计算接缝(seam_finders.hpp、seam_finders.cpp)
- 补偿曝光(exposure_compensate.hpp、exposure_compensate.cpp)
- 图像融合(blenders.hpp、blenders.hpp)
图像拼接模式:
- PANORAMA(全景模式),此模式假设各个图像对应的相机光心位置一致,各相机光轴之间存在旋转关系。

-
SCANS(扫描模式),此模式假设各个图像对应的相机光心位于同一平面,各相机光轴与此平面垂直,各图像之间符合仿射变换的约束,各相机拍摄的是与光心所在平面平行的平面上的场景。
**注:**官方文档要求图像之间满足仿射变换,假设同一空间点P在图像A和在图像B中的像素坐标分别为(u1,v1)和(u2,v2),内参分别为K1和K2,在图像A对应的相机坐标系下的坐标和在图像B对应的相机坐标系下的坐标分别为(X1,Y1,Z1)和(Z2,Y2,Z2),矩阵R和平移t描述图像B对应的相机相对于图像A对应的相机的位姿。则有
u1v11=Z1Z2K1RK2−1u2v21+Z11K1t
根据官方要求,矩阵Z1Z2K1RK2−1第三行应为[0,0,1],平移Z11K1t第三维应为0. 由此可知Z1=Z2,且对于任意点P,Z1为常数,因此可知SCANS模式下要求:各相机光轴与此平面垂直,各相机拍摄的是与光心所在平面平行的平面上。
特征点检测与图像匹配
模块过程:
- 计算图像集合中每个图像的特征点集合及其描述子集合;
- 根据对应图像的特征点和描述子,对图像集合进行两两配对;
- 对匹配上的两张图像,根据对应的特征点集合,计算其变换矩阵H。
PANORAMA模式:
图像匹配的class:BestOf2NearestMatcher
H是两个特征点集之间的单应变换矩阵,利用RANSAC算法,拟合出H,计算矩阵H的函数为:
cv::Mat cv::findHomography( InputArray _points1, InputArray _points2,
OutputArray _mask, int method, double ransacReprojThreshold )
SCANS模式:
图像匹配的class:AffineBestOf2NearestMatcher
H是两个特征点集之间的仿射变换矩阵,opencv的具体实现中,只包含旋转、缩放和平移,利用RANSAC算法,拟合出H,计算矩阵H的函数为:
CV_EXPORTS_W cv::Mat estimateAffinePartial2D(InputArray from, InputArray to, OutputArray inliers = noArray(),
int method = RANSAC, double ransacReprojThreshold = 3,
size_t maxIters = 2000, double confidence = 0.99,
size_t refineIters = 10);
估计相机运动,计算相机内外参
模块过程:
- 利用图像匹配过程中计算得到的H,估计相机外参R,并初始化相机内参K。其中H和R是相对值,首先由多个图像为节点,各个图像之间的匹配关系为边,构造Spanning Tree,然后树中心节点对应的图像外参为单位矩阵,其他图像外参是基于此图像的位姿变化。
- 利用Bundle Adjustment方法优化相机内外参;
- 波形矫正,进一步优化相机外参。
PANORAMA模式:
估计相机外参的class:HomographyBasedEstimator
根据H计算R的过程:CalcRotation结构体及其operator()成员函数
优化相机参数的clas:BundleAdjusterRay
波形矫正优化策略:WAVE_CORRECT_HORIZ
PANORAMA模式下,根据两个图像像素之间的单应变换矩阵H,计算相机旋转矩阵R的过程如下:
假设同一空间点P在图像A和在图像B中的像素坐标分别为(u1,v1)和(u2,v2),在图像A对应的相机坐标系下的坐标和在图像B对应的相机坐标系下的坐标分别为(X1,Y1,Z1)和(Z2,Y2,Z2),则根据opencv stitching模块中的定义,H满足
u2v21=Hu1v11
而根据相机成像模型,有
u1v11=Z11⋅K1X1Y1Z1, u2v21=Z21⋅K2X2Y2Z2
其中K1和K2分别为图像A对应的相机的内参和图像B对应的相机内参。而R为图像B对应的相机相对于图像A对应的相机的旋转,因此有
X1Y1Z1=RX2Y2Z2
由上述等式,可以求出R满足
R=Z2Z1K1−1H−1K2
图像B对应的相机相对于图像A对应的相机的旋转矩阵R由上式给出。
(注:opencv stitching模块的具体实现中旋转矩阵用K1−1⋅H−1K2来表示,相当于在实际上的旋转矩阵R基础上多一个系数Z2Z1. 此系数在利用Bundle Adjustment方法优化相机参数的过程中,通过cv::Rodrigues()函数将旋转矩阵转换为旋转向量的时候,去除了尺度信息)
SCANS模式:
估计相机外参的class:AffineBasedEstimator
根据H计算R的过程:CalcAffineTransform结构体及其operator()成员函数
优化相机参数的class:BundleAdjusterAffinePartial
波形矫正策略:不进行波形矫正
SCANS模式下,根据两个图像像素之间的仿射变换矩阵H,估计相机旋转矩阵R和平移t的过程如下:
假设同一空间点P在图像A和在图像B中的像素坐标分别为(u1,v1)和(u2,v2),则根据opencv stitching模块中的定义,H是仿射矩阵,满足
u2v21=Hu1v11
根据仿射变换矩阵的性质,H可表示为
H=h11h210h12h220h13h231
根据仿射变换的性质,可将矩阵H拆分为旋转缩放矩阵R′和平移t′,即
u2v21=R′u1v11+t′=h11h210h12h220001u1v11+h13h230
根据opencv中的定义,旋转矩阵R和平移t描述的是图像B对应的相机相对于图像A对应的相机的位姿,是与H相反的过程,因此可得
R=R′−1t=−R′−1⋅t′
此时得到的R和t都是基于像素坐标,即对于点P在图像A和在图像B中的像素坐标(u1,v1)和(u2,v2),有
u1v11=Ru2v21+t
**经过bundle adjustment过程优化之后,由H得到与真实的相机之间的位姿R和t。**对于P点在图像A对应的相机坐标系下的坐标和在图像B对应的相机坐标系下的坐标(X1,Y1,Z1)和(Z2,Y2,Z2),因此有
Z1X1Z1Y11=RZ2X2Z2Y21+t
图像变形
模块过程:
- 建立原图像和其对应的投影面之间的像素对应关系;
- 将图像本身的像素范围变换为对应到投影面上的ROI框;
- 对投影面上的ROI框中每个像素坐标,在原图像中找到对应的像素点,将其值赋给投影面上ROI框中对应的坐标。
PANORAMA模式:
图像变形class:SphericalWarper
原图与投影面映射变换class:SphericalProjector
PANORAMA模式下,图像投影方式为球面投影,即将图像投影到以相机光心为球心的球面上。
注1: 以下涉及的齐次坐标,是指相对于相机z轴方向上的齐次坐标。
注2: 球面坐标系即为半径为常数的球坐标系,具体定义可参考球坐标系。
-
正向投影:
首先,将图像像素坐标转换到相机坐标系下的齐次坐标。选取原图像中像素位置(u,v),其对应的空间点P在当前相机坐标系下的坐标为(X,Y,Z),则根据相机模型有
ZXZY1=K−1uv1
则(ZX,ZY,1)即为P点当前相机坐标系下,投影到单位平面的齐次坐标,其中K是当前相机内参。
然后,将P点在当前相机坐标系下的齐次坐标,变换为中心相机坐标系下的齐次坐标(X′,Y′,Z′),即
X′Y′Z′=RZXZY1
其中,R为当前相机相对于中心相机的旋转。
最后,根据利用直角坐标系和球面坐标系的关系,将P点在中心相机坐标系下的齐次坐标(X′,Y′,Z′)投影到,以中心相机光心为球心以s为半径的球面上得到P点在球面坐标系下的坐标(u′,v′)
u′=s⋅arctan2(Z′X′)v′=s⋅(π−arccosX′2+Y′2+Z′2Y′)
其中,函数arctan2()与c++中的函数定义一致。
-
反向投影:
反向投影即是正向投影的逆向操作,我们沿用上述符号定义。
首先,将P点球面坐标(u′,v′),转为中心相机坐标系下的齐次坐标
X′2+Y′2+Z′2X′X′2+Y′2+Z′2Y′X′2+Y′2+Z′2Z′=sin(π−sv′)⋅sin(su′)cos(π−sv′)sin(π−sv′)⋅cos(su′)
然后,将中心相机坐标系下的齐次坐标转为原图像相机坐标系下的齐次坐标
X2+Y2+Z2XX2+Y2+Z2YX2+Y2+Z2Z=R−1X′2+Y′2+Z′2X′X′2+Y′2+Z′2Y′X′2+Y′2+Z′2Z′
将原图像相机下的齐次坐标,除去z轴方向的长度,得到
ZXZY1=ZX2+Y2+Z2X2+Y2+Z2XX2+Y2+Z2YX2+Y2+Z2Z
最后,根据原图像相机的内参,计算出齐次坐标投影到成像平面上的像素坐标(u,v),即
uv1=KZXZY1
SCANS模式:
图像变形class:AffineWarper
原图与投影面映射变换class:PlaneProjector
SCANS模式下,图像投影方式仿射变换,即将图像投影到与其平行的平面,并利用相对于中心相机图像的仿射变换关系对图像进行变换。
-
正向投影:
首先,将图像像素坐标转换到相机坐标系下的齐次坐标。选取原图像中像素位置(u,v),其对应的空间点P在当前相机坐标系下的坐标为(X,Y,Z),则根据相机模型有
ZXZY1=K−1uv1
则(ZX,ZY,1)即为P点当前相机坐标系下,投影到单位平面的齐次坐标,其中K是当前相机内参。
然后,根据R和t,将P点在当前相机坐标系下的齐次坐标,变换为中心相机坐标系下的齐次坐标(X′,Y′,Z′),即
Z′X′Z′Y′1=RZXZY1+t
其中Z′=1.
最后,将投影面进行尺度s的缩放,得到P点在投影面上的像素坐标(u′,v′):u′=sZ′X′,v′=sZ′Y′. 因此正向投影,相当于把所有图像投影到距离相机光心所在平面为1的平面上,再将图像缩放s倍。
-
反向投影:
首先,P点将投影面图像坐标进行s1尺度缩放,得到在中心相机下的齐次坐标(Z′X′,Z′Y′,1),然后进行正向投影的逆操作
ZXZY1=R−1Z′X′Z′Y′1+R−1t
最后,根据相机内参K,得到原图像像素坐标(u,v),满足
uv1=KZXZY1
计算接缝、补偿曝光
PANORAMA模式:
计算接缝class:GraphCutSeamFinder,使用图形切割算法,可以查找图像中最佳的拼接缝隙
补偿曝光class:SphericalWarper,对图像中不同区域进行增益补偿
SCANS模式:
计算接缝class:GraphCutSeamFinder,使用图形切割算法,可以查找图像中最佳的拼接缝隙
补偿曝光class:BlocksGainCompensator,一种不使用曝光补偿的方法来校正拍摄照片中的一些失真
图像融合
模块过程:
- 根据投影之后各个的图像尺寸和位置,确定最终拼接完成之后的图像尺寸;
- 利用对应模式下的图像变形方式,将图像投影到最终图像上;
- 将拼接好的图像中重叠的部分,利用多频带混合算法进行融合。
图像融合class:MultiBandBlender,图像拼接的多频带混合算法
多频带混合算法:
多频带混合的基本思想是图像可以分解为不同频率的图像的叠加,在不同的频率上,使用不同的权重来进行融合,在低频部分应该使用波长较宽的加权信号,在高频部分使用较窄的加权信号,其算法过程如下:
- 计算输入图像的高斯金字塔;
- 计算输入图像的拉普拉斯金字塔;
- 将处于同一级的拉普拉斯金字塔进行融合;
- 将高层的拉普拉斯金字塔依次扩展直至和相同分辨率;
- 将上一步中得到的图像依次叠加,则得到最终的输出图像。