Subversion Repositories Code-Repo

Rev

Blame | Last modification | View Log | RSS feed

#include "MovingPointTracker.h"

MovingPointTracker::MovingPointTracker() {
        active_objects = 0;
        nextID = 0;
}


MovingPointTracker::~MovingPointTracker() {

}

float MovingPointTracker::pointDistance(cv::Point2f &pt1, cv::Point2f &pt2) {
        cv::Point2f diff = pt1 - pt2;
        return cv::sqrt(diff.x * diff.x + diff.y * diff.y);
}

std::vector<MOVING_OBJECT> MovingPointTracker::update(std::vector<cv::Point2f> points) {
        // Mark each existing object as invalid
        for (int i = 0; i < objects.size(); i++) {
                objects[i].valid = false;
        }

        std::vector<MOVING_OBJECT> newObjects;

        // For each point, determine if it is an extension of an existing object
        for (int i = 0; i < points.size(); i++) {
                bool found = false;
                int index;
                for (index = 0; index < objects.size(); index++) {
                        // Find the first object within the distance threshold
                        // TODO: calculate all distances and use the closest one
                        // TODO: handle case where multiple objects are merged into one
                        if (pointDistance(points[i], objects[index].last_known_pt) < OBJECT_DISTANCE_THRESHOLD) {
                                found = true;
                                break;
                        }
                }
                if (found) {
                        // If a match was found, update the object
                        objects[index].valid = true;
                        // Predict the next point using the Kalman filter
                        objects[index].filter->predict();
                        objects[index].last_known_pt = points[i];
                        objects[index].predicted_pt = objects[index].filter->correct(points[i].x, points[i].y);
                        // Calculate the running average
                        objects[index].history.push_front(objects[index].predicted_pt);
                        if (objects[index].history.size() > HISTORY_DEPTH)
                                objects[index].history.pop_back();
                        float avgX = 0, avgY = 0;
                        for (std::list<cv::Point2f>::iterator it = objects[index].history.begin(); it != objects[index].history.end(); it++) {
                                avgX += (*it).x;
                                avgY += (*it).y;
                        }
                        avgX /= objects[index].history.size();
                        avgY /= objects[index].history.size();
                        objects[index].historyAvg = cv::Point2f(avgX, avgY);
                        // Calculate the updated velocity and angle
                        objects[index].velocity = pointDistance(objects[index].predicted_pt, objects[index].historyAvg);
                        cv::Point2f diff = objects[index].predicted_pt - objects[index].historyAvg;
                        objects[index].angle = atan2(diff.y, diff.x);
                } else {
                        // If no matches were found, create a new object
                        MOVING_OBJECT newObject;
                        newObject.ID = nextID;
                        nextID++;
                        newObject.last_known_pt = points[i];
                        newObject.predicted_pt = points[i];
                        newObject.velocity = 0;
                        newObject.angle = 0;
                        newObject.filter = new KalmanFilter(points[i].x, points[i].y);
                        newObject.historyAvg = cv::Point2f(0, 0);
                        newObjects.push_back(newObject);
                }
        }

        // If an object is invalid at this point, remove it
        //std::vector<MOVING_OBJECT> newObjects;
        for (int i = 0; i < objects.size(); i++) {
                if (objects[i].valid) {
                        newObjects.push_back(objects[i]);
                }
        }
        objects = newObjects;

        return objects;
}