单应矩阵定义及应用

这篇具有很好参考价值的文章主要介绍了单应矩阵定义及应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 单应矩阵介绍

在张正友标定法的时候,可以使用单应矩阵来计算标定板平面和像素平面之间的变换关系,其本身包含了相机的内参和标定板与相机的外参矩阵。而在射影几何中,单应矩阵更多地用来表征两个平面之间的变换关系。对于标定时

令世界点的,并将中间部分协作M,则有

如果存在两个不同的相机,或者相同相机在不同位置派到同一个平面,则有

这表明,存在一组关系,可以实现两个像素平面的互相变换,具体的计算和标定时类似。

因为最后一行的1的缘故,H矩阵仍然只有8个自由度,所以只需要四组对应点即可计算出。

2. 单应矩阵在计算机视觉中的作用

1. 图像校正

使用四组对应点即可实现

单应矩阵定义及应用

2. 视角变换

 可以方便将普通视图转换为鸟瞰图

单应矩阵定义及应用

3.图像拼接

因为单应矩阵可以进行视角转换,则可以将不同角度拍摄的图像转换到相同的视角,从而实现图像的拼接

 单应矩阵定义及应用

 单应矩阵定义及应用

4. 增强现实(AR)

平面二维标记图案长用来做AR展示,根据marker不同视角下的图像可以方便地得到虚拟物体的位置姿态并进行显示 

单应矩阵定义及应用

 3.单应矩阵求解

令 

单应矩阵定义及应用

单应矩阵定义及应用

整理可得

单应矩阵定义及应用

单应矩阵定义及应用

整理成矩阵形式

所以只需要四组点即可求解出单应矩阵

但是再实际中,我们计算的关键点对会包含噪声,甚至出现误匹配的现象,所以只使用4组点来计算单应矩阵会出现很大的误差。因此一般会使用多于四组点来计算。另外直接法求解很难得到最优解,所以实际中会使用其他优化方法进行求解,比如SVD、LM等算法。

在opencv中有现成的函数可以进行调用

Mat findHomography(InputArray srcPoints, InputArray dstPoints, int method=0, double ransacReprojThreshold=3, OutputArray mask=noArray() )

从函数中看,只需要输入对应的匹配点,指定具体计算方法即可输出结果。

4. 图像拼接代码示例

输入:两张图片

单应矩阵定义及应用​​​​​​单应矩阵定义及应用

 输出:将图二拼接到图一

 代码:virtual_billboard.cpp

#include <opencv/cv.h>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>

class ImageMosic{
public:
    ImageMosic(cv::Mat img_src,cv::Mat img_target){
        img_src_ = img_src.clone();
        img_target_ = img_target.clone();
        SetSrcPts();
        SetTargetPts();
        CalcHAndPerspective();
    }

private:
    struct UserData{
        cv::Mat img;
        std::vector<cv::Point2f> pts;
    };
    void SetSrcPts()
    {
        cv::Size src_size = img_src_.size();
        src_pts_.push_back(cv::Point2f(0, 0));
        src_pts_.push_back(cv::Point2f(src_size.width-1, 0));
        src_pts_.push_back(cv::Point2f(src_size.width-1, src_size.height-1));
        src_pts_.push_back(cv::Point2f(0, src_size.height-1));
    }

    static void mouseHandler(int event, int x, int y, int flags,void* data_ptr)
    {
        if (event ==cv::EVENT_LBUTTONDOWN)
        {
            UserData *data = (UserData *)data_ptr;
            cv::circle( data->img, cv::Point(x, y), 3, cv::Scalar(0, 255, 255), 5);
            cv::imshow("Image_target", data->img);
            if (data->pts.size() < 4)
            {
                data->pts.push_back(cv::Point2f(x,y));
            }
        }
    }

    void SetTargetPts(){
        //show the image
        cv::imshow("Image_target", img_target_);
        std::cout << "Click on four corners of a billboard and then press ENTER" << std::endl;
        //set the callback function for any mouse event
        UserData user_data;
        user_data.img = img_target_;
        cv::setMouseCallback("Image_target", mouseHandler, &user_data);
        cv::waitKey(0);
        target_pts_ = user_data.pts;
    }
    void CalcHAndPerspective(){
        assert(target_pts_.size() == 4);
        cv::Mat H = cv::findHomography(src_pts_, target_pts_, 0);                   //计算单应矩阵
        cv::warpPerspective(img_src_, img_src_perspective_, H, img_target_.size()); //透视变换
        cv::Point pts_dst[4] = {target_pts_[0], target_pts_[1], target_pts_[2], target_pts_[3]};
        cv::fillConvexPoly(img_target_, pts_dst, 4, cv::Scalar(0));
        img_target_ = img_target_ + img_src_perspective_;

        cv::imshow("Image_target", img_target_);
        cv::waitKey(0);
    }
private:
    cv::Mat img_src_;
    cv::Mat img_src_perspective_;
    cv::Mat img_target_;
    std::vector<cv::Point2f> src_pts_;
    std::vector<cv::Point2f> target_pts_;
};

int main(){
    cv::Mat img_src = cv::imread("../images/cvlife.jpg");
    cv::Mat img_target = cv::imread("../images/ad.jpg");
    ImageMosic img_mosaic(img_src, img_target);
   
    return 0;
}

 CMakelists.txt

cmake_minimum_required(VERSION 1.0)
project(virtual_billboard)

find_package(OpenCV)

add_executable(virtual-billboard src/virtual_billboard.cpp)
target_link_libraries(virtual-billboard ${OpenCV_LIBS})

 操作步骤:在图片上从左上角顺时针选4个点,按enter结束

单应矩阵定义及应用

 结果:

单应矩阵定义及应用

5. 旋转平移恢复

        与本质矩阵类似,单应矩阵需要进行分解,才能得到旋转平移矩阵。分解的方法包含数值法[2][3]和解析法[4]。与本质矩阵类似,单应矩阵的分解也会返回4组旋转平移矩阵,并且同时可以解算出他们分别对应的场景点所在平面的法向量。如果已知成像的地图点的深度全为正值(即在相机前方),则可以排除两组。最后剩余两组解,需要更多的先验信息进行判断。通常我们可以通过假设已知场景平面的法向量来解决,如场景平面与相机平面平行,那么法向量的理论值为。

        单应性在SLAM中有重要意义。当特征点共面或相机发生纯旋转时,基础矩阵自由度下降,出现退化。现实中数据总会包含一些噪声,这是继续使用八点法求解基础矩阵,其多余出来的自由度将会主要由噪声决定。为了避免退化现象造成影响,通常我们会同时估计基础矩阵F和单应矩阵H,选择重投影误差较小的那个作为最终的运动估计矩阵。

6.参考

[1]单应性矩阵的理解及求解_机器视觉001的博客-CSDN博客_单应性矩阵

[2]Faugeras O D, Lustman F. Motion and structure from motion in a piecewise planar environment[J]. International Journal of Pattern Recognition and Artificial Intelligence, 1988, 2(03): 485-508.

[3]Zhang Z, Hanson A R. 3D reconstruction based on homography mapping[J]. Proc. ARPA96, 1996: 1007-1012.

[4]Malis E, Vargas M. Deeper understanding of the homography decomposition for vision-based control[D]. INRIA, 2007.文章来源地址https://www.toymoban.com/news/detail-404808.html

到了这里,关于单应矩阵定义及应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包