利用sift特征点判断相机是否发生移动。

具体解决的场景是 当你的相机在标定后如果不小心被触碰后,摄像机前后拍摄的图像来检测相机是否发生移动,从而准确定位到是哪个相机方便后续进行调整。具体的程序也很简单,具体思路为
利用sift寻找两张图像的匹配特征点——去除误匹配点——利用匹配点的欧式距离由小到大排序——以10.5为阈值点>10.5则认为有轻微移动(10.5是自己粗略估计值)
具体程序如下

#include <iostream>
#include<algorithm>
#include <opencv2/opencv.hpp>  
#include <opencv2/xfeatures2d.hpp>

using namespace cv;  //包含cv命名空间
using namespace std;
int main() {
    //Create SIFT class pointer
    Ptr<Feature2D> f2d = xfeatures2d::SIFT::create();
    vector<Mat> img_1;
    vector<Mat> img_2;
    char srcname[100];
    char dstname[100];
    int number = 19;
    for (int i = 0; i < number; i++)
    {
        sprintf(srcname, "./data/src/%04d.jpg", i);
        sprintf(dstname, "./data/dst/%04d.jpg", i);
   
        img_1.push_back(imread(srcname));
        img_2.push_back(imread(dstname));
        if (img_1.empty() || img_2.empty())
        {
            cout << "error ! not input images" << endl;
            return 0;
        }            
        if (img_1.size() != img_2.size())
        {
            cout << "error ! images number is not equal" << endl;
            return 0;
        }
    }
    //namedWindow("src", WINDOW_NORMAL);
    //imshow("src", img_1[0]);
    //waitKey(0);
    //namedWindow("dst", WINDOW_GUI_NORMAL);
    //imshow("dst", img_2[0]);
    //waitKey(0);
    //cout << img_1.size() << endl;
    //cout << img_2.size() << endl;

    for (int j = 0; j < number; j++)
    {
        //第一步,用SIFT算子检测关键点
        vector<KeyPoint> keypoints_1, keypoints_2;
        f2d->detect(img_1[j], keypoints_1);
        f2d->detect(img_2[j], keypoints_2);
        cout << "************************************" << endl;
        cout << "检测关键点......... " << endl;
        
        //第二步,计算特征向量
        Mat descriptors_1, descriptors_2;
        f2d->compute(img_1[j], keypoints_1, descriptors_1);
        f2d->compute(img_2[j], keypoints_2, descriptors_2);
        cout << "计算特征向量........." << endl;
 
     //  第三步,快速匹配
        vector<DMatch> matches;
        cv::Ptr<cv::FlannBasedMatcher> matcher = cv::FlannBasedMatcher::create();
        matcher->match(descriptors_1, descriptors_2, matches);
     

    //第四步,ransac去除误匹配点

    //RANSAC 消除误匹配特征点 主要分为三个部分:
    //1)根据matches将特征点对齐,将坐标转换为float类型
    //2)使用求基础矩阵方法 findFundamentalMat,得到RansacStatus
    //3)根据RansacStatus来将误匹配的点也即RansacStatus[i]=0的点删除

     //根据matches将特征点对齐,将坐标转换为float类型
     vector<KeyPoint> R_keypoint01, R_keypoint02;
    for (size_t i = 0; i < matches.size(); i++)
     {
       R_keypoint01.push_back(keypoints_1[matches[i].queryIdx]);
       R_keypoint02.push_back(keypoints_2[matches[i].trainIdx]);
            //这两句话的理解:R_keypoint1是要存储img01中能与img02匹配的特征点,
            //matches中存储了这些匹配点对的img01和img02的索引值
        }

        //坐标转换
        vector<Point2f>p01, p02;
        for (size_t i = 0; i < matches.size(); i++)
        {
            p01.push_back(R_keypoint01[i].pt);
            p02.push_back(R_keypoint02[i].pt);
        }

        //利用基础矩阵剔除误匹配点
        vector<uchar> RansacStatus;
        Mat Fundamental = findFundamentalMat(p01, p02, RansacStatus, FM_RANSAC);

        vector<KeyPoint> RR_keypoint01, RR_keypoint02;
        vector<DMatch> RR_matches;            //重新定义RR_keypoint 和RR_matches来存储新的关键点和匹配矩阵
        int index = 0;
        for (size_t i = 0; i < matches.size(); i++)
        {
            if (RansacStatus[i] != 0)
            {
                RR_keypoint01.push_back(R_keypoint01[i]);
                RR_keypoint02.push_back(R_keypoint02[i]);
                matches[i].queryIdx = index;
                matches[i].trainIdx = index;
                RR_matches.push_back(matches[i]);
                index++;
            }
        }
   
        sort(RR_matches.begin(),RR_matches.end());
        //for (int i = 0; i < 25; i++)
        //{
        //    cout << RR_matches[i].distance << endl;
        //}
        RR_matches.erase(RR_matches.begin()+10,RR_matches.end());
        
        
        
        //第五步,判断相机是否移动
        for (size_t i = 0; i <RR_matches.size(); i++)
        {
            if (RR_matches[i].distance >= 10.5)
            {   
                cout << "第  " << j << "相机发生移动" << endl;
                cout << "欧氏距离为 :" <<RR_matches[i].distance << endl;
                cout << "************************************"  << endl;
                cout << "\n";
                break;
            }
            if (i + 1 == RR_matches.size())
            {
                cout << j << " 相机正常" << endl;
                cout << "************************************" << endl;
                cout << "\n";
            }   
        }
      
     
    }
  
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值