基于surf的图像拼接

这段代码展示了如何使用OpenCV中的SURF特征检测器和FLANN匹配器进行图像拼接。首先,从两个输入图像中检测SURF关键点,然后计算描述符。通过匹配描述符,找出匹配的关键点对,构建_homography_矩阵。最后,应用该矩阵对图像进行透视变换,实现图像拼接。
摘要由CSDN通过智能技术生成

#include <stdio.h>
#include <iostream>

#include <cv.h>
#include <highgui.h>
#include "opencv2\opencv.hpp"
#include "opencv2\core\core.hpp"
#include "opencv2\highgui\highgui.hpp"

#include "opencv2\features2d\features2d.hpp"
#include <opencv2/nonfree/nonfree.hpp>
#include "opencv2\calib3d\calib3d.hpp"
#include "opencv2\imgproc\imgproc.hpp"

using namespace cv;
using namespace std;

void readme();

/* @function main */
int main( int argc, char** argv )
{

        if( argc != 3)
        {
                readme();
                return -1;
        }


        //Load the images
        Mat image1 = cv::imread( argv[2] );
        Mat image2 = cv::imread( argv[1] );

        //Size size(1024,780);

        //resize(image1,image1,size);
        //resize(image2,image2,size);

        Mat gray_image1;
        Mat gray_image2;

        //Covert to Grayscale
        cvtColor( image1, gray_image1, CV_RGB2GRAY );
        cvtColor( image2, gray_image2, CV_RGB2GRAY );

        imshow( "First Image", image2 );
        imshow( "Second Image", image1 );

        if ( !gray_image1.data || !gray_image2.data )
        {
                std::cout << " --(!) Error reading images " << std::endl;
                return -1;
        }

        //cv::initModule_nonfree( );
        //--Step 1 : Detect the keypoints using SURF Detector

        int minHessian = 400;

        SurfFeatureDetector detector( minHessian );

        std::vector< KeyPoint > keypoints_object, keypoints_scene;

        detector.detect( gray_image1, keypoints_object );
        detector.detect( gray_image2, keypoints_scene );

        //--Step 2 : Calculate Descriptors (feature vectors)
        SurfDescriptorExtractor extractor;

        Mat descriptors_object,descriptors_scene;

        extractor.compute( gray_image1, keypoints_object, descriptors_object );
        extractor.compute( gray_image2, keypoints_scene, descriptors_scene );

        //--Step 3 : Matching descriptor vectors using FLANN matcher
        FlannBasedMatcher matcher;
        std::vector< DMatch > matches;
        matcher.match( descriptors_object, descriptors_scene, matches );

        double max_dist = 0;
        double min_dist = 100;

        //--Quick calculation of min-max distances between keypoints
        for(int i =0; i < descriptors_object.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 );

        //--Use only "good" matches (i.e. whose distance is less than 3 X min_dist )
        std::vector< DMatch > good_matches;

        for(int i =0 ; i < descriptors_object.rows ; i++)
        {
                if( matches[i].distance < 3*min_dist )
                {
                        good_matches.push_back( matches[i] );
                }
        }
        std::vector< Point2f > obj;
        std::vector< Point2f > scene;

        for( int i = 0; i < good_matches.size(); i++)
        {
                //--Get the keypoints from the good matches
                obj.push_back( keypoints_object[good_matches[i].queryIdx].pt );
                scene.push_back( keypoints_scene[good_matches[i].trainIdx].pt );
        }

        //Find the Homography Matrix
        Mat H = findHomography( obj, scene, CV_RANSAC );

        // Use the homography Matrix to warp the images
        cv::Mat result;

        warpPerspective( image1, result, H, cv::Size( image1.cols+image2.cols, image1.rows) );
        cv::Mat half(result, cv::Rect(0, 0, image2.cols, image2.rows) );
        image2.copyTo(half);

        /* To remove the black portion after stitching, and confine in a rectangular region*/

        // vector with all non-black point positions
        std::vector<cv::Point> nonBlackList;
        nonBlackList.reserve(result.rows*result.cols);

        // add all non-black points to the vector
        // there are more efficient ways to iterate through the image
        for(int j=0; j<result.rows; ++j)
                for(int i=0; i<result.cols; ++i)
                {
                        // if not black: add to the list
                        if(result.at<cv::Vec3b>(j,i) != cv::Vec3b(0,0,0))
                        {
                                nonBlackList.push_back(cv::Point(i,j));
                        }
                }

        // create bounding rect around those points
        cv::Rect bb = cv::boundingRect(nonBlackList);

        // display result and save it
        cv::imshow("Reult", result(bb));
        cv::imwrite("./Result.jpg", result(bb));

        //imshow( "Result", result );
        //imwrite( "./Result.jpg", result );


        waitKey(0);

        return 0;
}

/** function readme */
void readme()
{
        std::cout << " Usage: pano < img1 > < img2 > " <<std::endl;
}
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值