Opencv学习(13)—极线的绘制

本质矩阵E

Opencv学习(13)—极线的绘制_第1张图片左右两个平行四边形分别是相机在不同位置的成像平面,C0, C1分别是两个位置中相机的光心,也就是针孔相机模型中的针孔,P是空间中的一个三维点,p0, p1分别是P点在不同成像平面上对应的像素点
Opencv学习(13)—极线的绘制_第2张图片p0, p1都是图像上的二维点,不过,这里我们会把它变成三维的方向向量来考虑
方向向量:只考虑它的方向,而不考虑它的起点或终点的向量。我们假设一个归一化的图像平面,该平面上焦距f =1 ,因此我们可以定义在以C0为原点的坐标系下
Opencv学习(13)—极线的绘制_第3张图片=30x30而在以C1为原点的坐标系下

Opencv学习(13)—极线的绘制_第4张图片
C0-p0就可以用p0表示,向量C0-C1就是光心C1相对于C0的平移,我们记为t, 向量C1-p1根据前面的讨论,可以用 Rp1 来表示
Opencv学习(13)—极线的绘制_第5张图片
记为本质矩阵或本征矩阵(Essential Matrix)为
Opencv学习(13)—极线的绘制_第6张图片
得:
Opencv学习(13)—极线的绘制_第7张图片

极线方程

点p在直线l上的充分必要条件就是 直线l 的系数与p的齐次坐标p’的内积为0
在这里插入图片描述
可以把Ep1看做是直线的方程,p0看做是直线上的点,也就是说Ep1就是以C0为原点坐标系中的极线了。如下图中红色线条所示,就是极线啦,它的方程是E*p1。
Opencv学习(13)—极线的绘制_第8张图片

void cv::computeCorrespondEpilines	(	InputArray 	points,
int 	whichImage,
InputArray 	F,
OutputArray 	lines 
)		

Python:
lines	=	cv.computeCorrespondEpilines(	points, whichImage, F[, lines]	)

Opencv学习(13)—极线的绘制_第9张图片

#include
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;
int main( int argc, char** argv )
{

    Mat rgb1 = imread( "/home/xiaohu/learn_SLAM/zuoye11/code/rgb1.ppm" );
    Mat rgb2 = imread( "/home/xiaohu/learn_SLAM/zuoye11/code/rgb2.ppm" );

//    Ptr detector;
//    Ptr descriptor;
//    detector = FeatureDetector::create("ORB");
//    descriptor = DescriptorExtractor::create("ORB");

    // used in OpenCV3
    Ptr<FeatureDetector> detector = ORB::create();
    Ptr<DescriptorExtractor> descriptor = ORB::create();
    // use this if you are in OpenCV2
    // Ptr detector = FeatureDetector::create ( "ORB" );
    // Ptr descriptor = DescriptorExtractor::create ( "ORB" );

    vector< KeyPoint > kp1, kp2;
    detector->detect( rgb1, kp1 );
    detector->detect( rgb2, kp2 );

    // 计算描述子
    Mat desp1, desp2;
    descriptor->compute( rgb1, kp1, desp1 );
    descriptor->compute( rgb2, kp2, desp2 );

    // 匹配描述子
    vector< DMatch > matches;
    BFMatcher matcher;

    matcher.match( desp1, desp2, matches );
    cout<<"Find total "<<matches.size()<<" matches."<<endl;

    // 筛选匹配对
    vector< DMatch > goodMatches;
    double minDis = 9999;
    for ( size_t i=0; i<matches.size(); i++ )
    {
        if ( matches[i].distance < minDis )
            minDis = matches[i].distance;
    }

    for ( size_t i=0; i<matches.size(); i++ )
    {
        if (matches[i].distance < 10*minDis)
            goodMatches.push_back( matches[i] );
    }


    vector< Point2f > pts1, pts2;
    for (size_t i=0; i<goodMatches.size(); i++)
    {
        pts1.push_back(kp1[goodMatches[i].queryIdx].pt);
        pts2.push_back(kp2[goodMatches[i].trainIdx].pt);
    }

    // 请先计算基础矩阵并据此绘制出前10个匹配点对应的对极线,可以调用opencv函数

    //首先根据对应点计算出两视图的基础矩阵,基础矩阵包含了两个相机的外参数关系
    Mat fundamental_matrix=findFundamentalMat(pts1,pts2,CV_FM_8POINT);
    //计算对应点的外极线epilines是一个三元组(a,b,c),表示点在另一视图中对应的外极线ax+by+c=0;
    vector<cv::Vec<float, 3>> epilines1,epilines2;
    computeCorrespondEpilines(pts1,1,fundamental_matrix,epilines1);
    computeCorrespondEpilines(pts2,2,fundamental_matrix,epilines2);
    cv::RNG &rng = theRNG();
    for (int i = 0; i < 10; ++i) {
        //随机产生颜色
        Scalar color = Scalar(rng(255), rng(255), rng(255));
        circle(rgb1, pts1[i], 5, color, 3);
        //绘制外极线的时候,选择两个点,一个是x=0处的点,一个是x为图片宽度处
        line(rgb1, cv::Point(0, -epilines2[i][2] / epilines2[i][1]),Point(rgb1.cols, -(epilines2[i][2] + epilines2[i][0] * rgb1.cols) / epilines2[i][1]), color);

        circle(rgb2, pts2[i], 5, color, 3);
        line(rgb2, cv::Point(0, -epilines1[i][2] / epilines1[i][1]),Point(rgb2.cols, -(epilines1[i][2] + epilines1[i][0] * rgb2.cols) / epilines1[i][1]), color);
    }
    imshow("epiline1", rgb2);
    imwrite("../epiline1.jpg",rgb2);
    imshow("epiline2", rgb1);
    imwrite("../epiline2.jpg",rgb1);
    waitKey(0);
    return 0;
}

Opencv学习(13)—极线的绘制_第10张图片

你可能感兴趣的:(opencv)