OpenCV 基于Lucas-Kanade光流算法的对象跟踪

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

视频来源:https://www.youtube.com/watch?v=EvIwL0aSCZY

以下代码用OpenCV实现了视频中基于Lucas-Kanade光流算法【OpenCV中的实现为calcOpticalFlowPyrLK函数】的对象跟踪。为了规避孔径问题,以下代码实现仅对角点【通过goodFeaturesToTrack函数做角点检测】做光流计算。

//
//  main.cpp
//  opencv-learning
//
//  Created by _R on 2019/1/9.
//  Copyright © 2019 _R. All rights reserved.
//

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

using namespace std;
using namespace cv;


int main(int argc, char* argv[])
{
    VideoCapture video = VideoCapture("/Users/_R/Desktop/Flying_disc_freestyle_640x360.mp4");
    if (!video.isOpened()) {
        cout << "could not load video file ..." << endl;
        return -1;
    }
    
    Mat frame, frame_in_gray, prev_frame, prev_frame_in_gray;
    vector<Point2f> initPoints;
    vector<Point2f> feature_points[2];
    vector<uchar> status_of_feature_points;
    vector<float> errors;
    double count_of_success = 0;
    double distance_between_feature_points = 0.0;
    
    
    
    namedWindow("flying_disc", WINDOW_AUTOSIZE);
    
    while (video.read(frame)) {
        cvtColor(frame, frame_in_gray, COLOR_BGR2GRAY);
        
        if (feature_points[0].empty() || initPoints.size() < 10) {
            
            goodFeaturesToTrack(frame_in_gray, feature_points[0], 1000, 0.01, 10.0);
            initPoints.assign(feature_points[0].begin(), feature_points[0].end());
            
        } else {
            
            goodFeaturesToTrack(frame_in_gray, feature_points[1], 1000, 0.01, 10.0);
            calcOpticalFlowPyrLK(prev_frame_in_gray, frame_in_gray, feature_points[0], feature_points[1], status_of_feature_points, errors);
            
            count_of_success = 0;
            for (size_t t=0; t<status_of_feature_points.size(); t++) {
                distance_between_feature_points = abs(feature_points[0][t].x - feature_points[1][t].x) + abs(feature_points[0][t].y - feature_points[1][t].y);
                
                if (distance_between_feature_points > 2 && status_of_feature_points[t]) {
                    initPoints[count_of_success] = initPoints[t];
                    feature_points[1][count_of_success] = feature_points[1][t];
                    count_of_success++;
                }
                
            }
            initPoints.resize(count_of_success);
            feature_points[1].resize(count_of_success);
            std::swap(feature_points[0], feature_points[1]);
            
            cout << initPoints.size() << " " << feature_points[0].size() << endl;
            
            for (size_t t=0; t<feature_points[0].size(); t++) {
                cout << "(" << initPoints[t].x << "," << initPoints[t].y << ")" << " " << "(" << feature_points[0][t].x << "," << feature_points[0][t].y << ")" << endl;
                
                line(frame, initPoints[t], feature_points[0][t], Scalar(0,255,0));
                circle(frame, feature_points[0][t], 2, Scalar(0,0,255));
            }
            
            cout << endl;
        }
        
        frame.copyTo(prev_frame);
        frame_in_gray.copyTo(prev_frame_in_gray);
        
        imshow("flying_disc", frame);
        
        char c = waitKey(50);
        if (c == 27) {
            break;
        }
    }
    
    waitKey(0);
    video.release();
    return 0;
}


效果展示

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u012841922/article/details/86519833