基于OpenCV的图像配准之后的透视变换

??在通过SIFT、SURF或者ORB进行特征点检测,生成了特征点和特征点描述子的vector后,如何进一步的进行对于图像的矫正。这个时候就用到了opencv的另外两个函数findHomography和perspectiveTransform。 
??findHomography是用来计算两张图像的单应性矩阵的。opencv的官方文档中有详细的使用说明: 

??前两个参数分别是通过之前的特征检测找到的特征点,第三个参数为计算单应性矩阵的方法,默认为使用所有的点。第四个参数仅在第三个参数为CV_RANSAC时使用,为最大允许的特征点对间二次投影的误差。 
??perspectiveTransform函数为通过单应性矩阵生成校正之后的图像。 

??前两个参数为原始图像和矫正之后的图像的点的集合。只能为2维或3维的向量。这里的点的集合指的是图像的位置排布,和像素值没有任何关系。第三个参数即为之前求出的单应性矩阵。 
??注意:生成的矫正图像为点的集合,即为vector向量,并不是图像,生成的只是原始图像与校正图像的位置对应关系,图像的生成在下面的例子中会说明。 
示例:

int main()  
{  
    Mat img_1 = imread("00068.jpg");  
    Mat img_2 = imread("00069.jpg");  
    if (!img_1.data || !img_2.data)  
    {  
        cout << "error reading images " << endl;  
        return -1;  
    }  

    ORB orb;  
    vector<KeyPoint> keyPoints_1, keyPoints_2;  
    Mat descriptors_1, descriptors_2;  

    orb(img_1, Mat(), keyPoints_1, descriptors_1);  
    orb(img_2, Mat(), keyPoints_2, descriptors_2);  

    BruteForceMatcher<HammingLUT> matcher;  
    vector<DMatch> matches;  
    matcher.match(descriptors_1, descriptors_2, matches);  

    double max_dist = 0; double min_dist = 100;  
    //-- Quick calculation of max and min distances between keypoints  
    for( int i = 0; i < descriptors_1.rows; i++ )  
    {   
        double dist = matches[i].distance;  
        if( dist < min_dist ) min_dist = dist;  
        if( dist > max_dist ) max_dist = dist;  
    }  
    printf("-- Max dist : %f \n", max_dist );  
    printf("-- Min dist : %f \n", min_dist );  
    //-- Draw only "good" matches (i.e. whose distance is less than 0.6*max_dist )  
    //-- PS.- radiusMatch can also be used here.  
    std::vector< DMatch > good_matches;
    vector<Point2f> leftPoint,rightPoint;
    for( int i = 0; i < descriptors_1.rows; i++ )  
    {   
        if( matches[i].distance < 0.6*max_dist )  
        {   
            good_matches.push_back( matches[i]);
            leftPoint.push_back(keyPoints_1[matches[i].queryIdx].pt);//保存左图像的关键点
            rightPoint.push_back(keyPoints_2[matches[i].trainIdx].pt);//保存右图像的关键点
        }  
    }  


    Mat Homography = findHomography(leftPoint,rightPoint,CV_RANSAC,3);//生成单应性矩阵
    cout<<Homography<<endl;
    vector<Point2f> CorrectImg;//根据单应性矩阵校正之后的点
    vector<Point2f> ponits;//保存图像的所有的点
    for(int i=0;i<img_1.rows;i++)
    {  
        for(int j=0;j<img_2.cols;j++)
        {  
            ponits.push_back(Point2f(j,i));  
        }  
    }
    perspectiveTransform(ponits,CorrectImg,Homography);//生成对应关系
    imshow("left",img_1);
    imshow("right",img_2);
     Mat img_trans = Mat::zeros(img_1.rows,img_1.cols,CV_8UC3);  //矫正后的图像
    int count = 0;  
    for(int i=0;i<img_1.rows;i++)
    {  
        uchar* p = img_1.ptr<uchar>(i);  
        for(int j=0;j<img_1.cols;j++)
        {  
            int y = CorrectImg[count].y;  
            int x = CorrectImg[count].x;  
            if (y < 0 || x < 0 || x >= img_1.cols || y >= img_1.rows)
            {
                count++;
                continue;
            }
            uchar* t = img_trans.ptr<uchar>(y);  
            t[x*3]  = p[j*3];  
            t[x*3+1]  = p[j*3+1];  
            t[x*3+2]  = p[j*3+2];  
            count++;  
        }  
    }  

    imshow("CorrectImg",img_trans);
    waitKey();

    return 0;  
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值