OpenCV学习——对富特征进行光流匹配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/AileenNut/article/details/76464329

《深入理解OpenCV——实用计算机视觉项目解析》第四章学习。
在富特征上使用光流匹配的优势在于处理过程通常较快且能容纳更多的匹配点。
将结构KeyPoint转化成Point2f的代码如下:

void KeyPointsToPoints(const vector<KeyPoint>& kps, vector<Point2f>& ps)
 {
    ps.clear();
    for (unsigned int i = 0; i<kps.size(); i++) 
        ps.push_back(kps[i].pt);
}

特征提取的方式可以根据实际情况改变,这里使用FAST特征点检测。
光流匹配的代码如下:

void OFMatch()
{
    String fileName1 = "1.jpg";
    String fileName2 = "2.jpg";
    Mat img1;
    Mat img2;
    img1 = imread(fileName1,1);
    img2 = imread(fileName2,1);
    if (!img1.data || !img2.data)
    {
        cout << "error reading" << endl;
    }
    vector<KeyPoint>left_keypoints, right_keypoints;
    //寻找左右两张图中的特征点
    FastFeatureDetector ffd;
    ffd.detect(img1, left_keypoints);
    ffd.detect(img2, right_keypoints);
    vector<Point2f> left_points;
    KeyPointsToPoints(left_keypoints, left_points);
    vector<Point2f> right_points(left_keypoints.size());
    KeyPointsToPoints(right_keypoints, right_points);
    //保证图片为灰度图
    Mat imgGray1, imgGray2;
    cvtColor(img1, imgGray1, CV_RGB2GRAY);
    cvtColor(img2, imgGray2, CV_RGB2GRAY);
    //计算光流域
    vector<uchar>vstatus;
    vector<float>verror;
    calcOpticalFlowPyrLK(imgGray1, imgGray2, left_points, right_points, vstatus, verror);
    Mat imofkl = img1.clone();
    for (int i = 0; i < vstatus.size(); i++)
    {
        if (vstatus[i] && verror[i] < 12)
        {
            line(imofkl, left_points[i], right_points[i], CV_RGB(255, 255, 255), 1, 8, 0);
            circle(imofkl, right_points[i], 3, CV_RGB(255, 255, 255), 1, 8, 0);
        }
    }
    namedWindow("光流", WINDOW_NORMAL);
    imshow("光流", imofkl);
    //去除大误差点
    vector<Point2f> right_points_to_find;
    vector<int> right_points_to_find_back_index;
    for (unsigned int i = 0; i < vstatus.size(); i++)
    {
        if (vstatus[i] && verror[i] < 12.0)
        {
            //为使用特征保留原始光流序列的点索引
            right_points_to_find_back_index.push_back(i);
            //保持特征点本身
            right_points_to_find.push_back(right_points[i]);  
        }
        else
        {
            vstatus[i] = 0;
        }
    }
    //查看每个正确点属于的特征
    Mat right_points_to_find_flat = Mat(right_points_to_find).reshape(1, right_points_to_find.size());
    vector<Point2f> right_features;
    KeyPointsToPoints(right_keypoints, right_features);
    Mat right_features_flat = Mat(right_features).reshape(1, right_features.size());
    //匹配
    BFMatcher matcher(CV_L2);
    vector<vector<DMatch>> nearest_neighbors;
    matcher.radiusMatch(right_points_to_find_flat, right_features_flat, nearest_neighbors, 2.0f);
    //去除距离过近可能导致错误的点
    set<int>found_in_right_points;
    vector<DMatch>matches;
    for (int i = 0; i < nearest_neighbors.size(); i++)
    {
        DMatch _m;
        if (nearest_neighbors[i].size() == 1)
        {
            _m = nearest_neighbors[i][0];
        }
        else if (nearest_neighbors[i].size()>1)
        {
            double ratio = nearest_neighbors[i][0].distance / nearest_neighbors[i][1].distance;
            if (ratio < 0.7)
            {
                _m = nearest_neighbors[i][0];
            }
            else
                continue;
        }
        else
            continue;
        if (found_in_right_points.find(_m.trainIdx) == found_in_right_points.end())
        {
            _m.queryIdx = right_points_to_find_back_index[_m.queryIdx];
            matches.push_back(_m);
            found_in_right_points.insert(_m.trainIdx);
        }
    }
    cout << "pruned" << matches.size() << "/" << nearest_neighbors.size() << "matches" << endl;
    Mat result;
    drawMatches(img1, left_keypoints, img2, right_keypoints, matches, result);
    namedWindow("结果", WINDOW_NORMAL);
    imshow("结果", result);
    waitKey(0);
}

匹配结果如下:

1.光流

这里写图片描述

2.对富特征进行光流匹配结果

这里写图片描述

猜你喜欢

转载自blog.csdn.net/AileenNut/article/details/76464329