Opencv2.4.9源码分析——Stitching(四)

4、图像投影变换

4.1 原理

前文我们已经说过,每幅图像是相机在不同角度下拍摄得到的,它们并不在同一个投影平面上,如果对重叠部分直接进行拼接,则会破坏实际场景的视觉一致性。所以我们需要在拼接之前,对图像进行投影变换,即对图像进行扭曲变形。

设图像中某像素点的二维坐标为(x, y),它所对应的世界坐标为(X, Y, Z),两者之间的关系为:

(70)

式中,R为旋转矩阵,K为相机的内参数矩阵。像素点可以映射到不同的表面上,最简单的是映射到平面上,设(u, v)为映射后的二维坐标,则

(71)

如果世界坐标有平移,并且投影图像有尺度的变化,则式71改写为:

(72)

式中,s表示尺度,与相机焦距成正比,t1t2t3表示三个坐标轴的位移。

上面的变换是由源图像变换到投影图像上,即由(x, y)映射为(u, v),我们称为正向投影。如果是由投影图像变换为源图像,我们称为反向投影。反向投影的公式为:

(73)

(74)

平面投影简单,但拼接图像较多时,视觉效果并不好。另一种常见的投影方式是柱面投影。柱面投影是以相机为圆柱中心点,相机焦距为半径的一个柱面作为投影面。它的投影图像与投影到的圆柱表面的位置无关,柱面全景图像可在水平方向上满足360度环视,具有较好的视觉效果,并且柱面投影也符合我们对相机位置的假设(相机只做旋转动作)。柱面投影后的坐标为:

(75)

柱面投影的反向映射关系为:

(76)

由(X, Y, Z)得到(x, y)的公式也是式74。

球面投影是将图像序列投影到以一点为坐标中心的球面上。人的眼睛在看东西时的原理就类似于球面投影,因此,以视点为中心的球面投影模型是最自然的投影模型。但是球面投影模型也存在着一些缺点,比如球面上的像素点不是行列均匀排列的关系,球面不能展开成平面,这些都使得很多图像处理算法很难用在平面投影上。球面投影的正向映射为:

(77)

球面投影的反向映射为:

(78)

立方体投影是为了克服球形投影缺点而提出的投影模型。这种投影模型的优点是方便计算机处理与储存图像。立方体投影的正向映射为:

(79)

立方体投影的反向映射为:

(80)

鱼眼投影图像具有较大的视角,非常适用于导航、监视和检测等方面。它的正向映射为:

(81)

鱼眼投影的反向映射为:

(82)

在图像拼接过程中,我们首先需要把图像进行正向映射,又因为最终图像还是要在平面上进行展示,所以还是需要再进行反向映射。最终被映射到的平面就是全景图像所在的平面,这是因为在上一步,我们已经通过最大生成树得到了基准图像,相机的内参数都是基于该基准图像的,所以所有的图像最终都映射到了该基准图像所在的平面上,这样就构成了一幅全景图像。

 

4.2 源码

 

RotationWarper类是只处理因旋转而引起的图像扭曲的接口类,它是RotationWarperBase类的基类:

template <class P>
class CV_EXPORTS RotationWarperBase : public RotationWarper
{
public:
    //表示投影图像的像素点,pt为源像素点,它通过P.mapForward函数得到投影点(该函数的返回值),K为相机的内参数,R为相机的旋转矩阵,通过P.setCameraParams函数设置
    Point2f warpPoint(const Point2f &pt, const Mat &K, const Mat &R);
    //由给定的相机数据建立投影关系,src_size为源图像区域,xmap和ymap是分别表示坐标值由两次映射的值,该函数返回投影图区域
    Rect buildMaps(Size src_size, const Mat &K, const Mat &R, Mat &xmap, Mat &ymap);
    //表示由源图src经buildMaps函数得到投影图像dst,interp_mode和border_mode分别表示投影时用到的插值算法和边界扩展方法,该函数返回dst在最终的全景图像投影后的左上角坐标
    Point warp(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
               Mat &dst);
    //与buildMaps函数相类似,只不过该函数使用的是P.mapForward函数
    void warpBackward(const Mat &src, const Mat &K, const Mat &R, int interp_mode, int border_mode,
                      Size dst_size, Mat &dst);
    //表示确定扭曲图像区域
    Rect warpRoi(Size src_size, const Mat &K, const Mat &R);

    float getScale() const { return projector_.scale; }    //得到尺度
    void setScale(float val) { projector_.scale = val; }    //设置尺度

protected:

    // Detects ROI of the destination image. It's correct for any projection.
    //该虚函数用于得到目标图像的区域
    virtual void detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br);

    // Detects ROI of the destination image by walking over image border.
    // Correctness for any projection isn't guaranteed.
    //该函数仅由源图像的边界得到目标图像的区域
    void detectResultRoiByBorder(Size src_size, Point &dst_tl, Point &dst_br);

    P projector_;    //表示投影的方法
};

下面我们给出RotationWarperBase类中主要函数的介绍:

template <class P>
Point2f RotationWarperBase<P>::warpPoint(const Point2f &pt, const Mat &K, const Mat &R)
//pt表示投射的源点
//K表示相机的内参数
//R表示相机的旋转参数
//该函数返回投射点
{
    projector_.setCameraParams(K,
  • 13
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
opencv是一个开源的计算机视觉库,opencv2.4.9是其中的一个版本。在opencv2.4.9中,有一个模块叫做stitching,用于图像拼接。 图像拼接是将多张图像按照一定的顺序和方式进行合并,形成一张更大视野覆盖范围的图像。拼接的过程需要解决图像间的重叠区域匹配、图像变换与叠加等问题。 在opencv2.4.9stitching模块中,主要有以下几个重要的类: 1. Stitcher类:拼接器类,用于执行拼接的主要操作。它提供了一系列的方法,如设置拼接的模式、添加要拼接的图像等。 2. FeaturesFinder类:特征点检测类,用于在图像中寻找特征点。该类利用SIFT、SURF等算法来检测图像中的关键点,以便进行匹配。 3. FeaturesMatcher类:特征点匹配类,用于对图像中的特征点进行匹配。该类使用KNN算法进行特征点的匹配,并利用RANSAC算法进一步筛选特征点,剔除误匹配。 4. Estimator类:变换估计类,用于估计图像间的变换参数。该类可以通过特征点的对应关系,计算图像间的旋转矩阵、平移矩阵等变换参数。 5. Blender类:图像融合类,用于将拼接后的图像进行融合。该类可以进行多种融合方式,如线性融合、多频融合等。 通过以上的类和方法,opencv2.4.9stitching模块能够完成图像拼接的过程。整个过程包括特征点检测、特征点匹配、变换参数估计和图像融合等步骤。 需要指出的是,本文只是对opencv2.4.9stitching模块进行了初步的介绍,具体的源码分析需要深入研究。整个源码工程庞大,包含很多细节和算法,需要对计算机视觉和图像处理有较深入的理解才能进行分析和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值