You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
16 KiB

//------------------------------------------------------------------------------
//
// Project: Anonymizer
//
// Brno University of Technology
// Faculty of Information Technology
//
//------------------------------------------------------------------------------
//
// This project was financially supported by project VG20102015006 funds
// provided by Ministry of the Interior of the Czech republic.
//
//------------------------------------------------------------------------------
/*!
@file videotracker.h
@brief Header file
@details Details
@authors Martin Borek (mborekcz@gmail.com)
@authors Filip Orsag (orsag@fit.vutbr.cz)
@date 2014-2015
@note This project was supported by MV CR project VG20102015006.
@copyright BUT OPEN SOURCE LICENCE (see License.txt)
*/
#ifndef VIDEOTRACKER_H
#define VIDEOTRACKER_H
#include <opencv/cv.h>
#include <opencv/cvaux.h>
#include <opencv/cxcore.h>
#include <opencv/highgui.h>
#include <QObject>
#include <QProgressDialog>
#include <QApplication>
#include <memory>
#include "ffmpegplayer.h"
#include "trackingalgorithm.h"
#include "trackedobject.h"
#include "videoframe.h"
#include "selection.h"
#include <cereal/types/vector.hpp>
#include <cereal/types/memory.hpp> // for shared_ptr
struct OutputException : public std::exception{};
struct UserCanceledException : public std::exception{};
class VideoTracker
{
public:
// CEREAL serialization
template<class Archive>
void serialize(Archive &archive)
{
archive(CEREAL_NVP(trackedObjects));
}
/**
* Constructor
*/
VideoTracker();
/**
* Constructor
* @param videoAddr Path to a video file
* @param progressDialog QT progress dialog for displaying information about video opening
*/
explicit VideoTracker(std::string const &videoAddr, QProgressDialog const *progressDialog);
/**
* Destructor
*/
~VideoTracker();
/**
* Loads a new video file.
* @param videoAddr Path to a video file
* @param progressDialog QT progress dialog for displaying information about video opening
*/
void load_video(std::string const &videoAddr, QProgressDialog const *progressDialog);
/**
* Returns frames per second value of the video.
* @return Frames per second
*/
double get_fps() const;
/**
* Returns information about number of frames.
* @return Number of frames
*/
unsigned long get_frame_count() const;
/**
* Returns information about video length.
* @return Video length in milliseconds
*/
unsigned long get_total_time() const;
/**
* Returns timestamp of the current frame.
* @return Timestamp
*/
int64_t get_frame_timestamp() const;
/**
* Returns time position of the current frame.
* @return Time position in milliseconds
*/
unsigned long get_time_position() const;
/**
* Returns frame number of the current frame.
* @return Frame number
*/
unsigned long get_frame_number() const;
/**
* Returns number of tracked objects
* @return Number of tracked objects
*/
unsigned int get_objects_count() const;
/**
* Tracks a new object.
* @param objectAppearance Object appearance
* @param objectName Object name
* @param initialPosition Initial object position
* @param initialTimestamp Initial timestamp
* @param initialTimePosition Initial time position
* @param initialFrameNumber Initial frame number
* @param endTimestampSet Is end timestamp set?
* @param endTimestamp End timestamp
* @param endTimePosition End time position
* @param endFrameNumber End frame number
* @return Object ID; First objest has ID 1. If frame at initialTimestamp is not read, -1 is returned;
*/
int add_object(const Characteristics &objectAppearance, const std::string &objectName,
Selection initialPosition, int64_t initialTimestamp, unsigned long initialTimePosition,
unsigned long initialFrameNumber, bool endTimestampSet=false, int64_t endTimestamp=0,
unsigned long endTimePosition=0, unsigned long endFrameNumber=0);
/**
* Reads a frame by its time position and returns it.
* @param imgFrame Altered read frame (contains tracked objects) converted to be displayed in QT
* @param originalImgFrame Read frame converted to be displayed in QT.
* @param includeOriginal Should be original frame read? If not, originalImgFrame does not contain a valid frame.
* @param time Time position
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @return True if successful
*/
bool get_frame_by_time(QImage &imgFrame, QImage &originalImgFrame, bool includeOriginal, int64_t time, QProgressDialog *progressDialog);
/**
* Reads a frame by its timestamp and returns it.
* @param imgFrame Altered read frame (contains tracked objects) converted to be displayed in QT
* @param originalImgFrame Read frame converted to be displayed in QT.
* @param includeOriginal Should be original frame read? If not, originalImgFrame does not contain a valid frame.
* @param timestamp Timestamp
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @return True if successful
*/
bool get_frame_by_timestamp(QImage &imgFrame, QImage &originalImgFrame, bool includeOriginal, int64_t timestamp, QProgressDialog *progressDialog);
/**
* Reads a frame by its frame number (index) and returns it.
* @param imgFrame Altered read frame (contains tracked objects) converted to be displayed in QT
* @param originalImgFrame Read frame converted to be displayed in QT.
* @param includeOriginal Should be original frame read? If not, originalImgFrame does not contain a valid frame.
* @param frameNumber Frame number (index)
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @return True if successful
*/
bool get_frame_by_number(QImage &imgFrame, QImage &originalImgFrame, bool includeOriginal, unsigned long frameNumber, QProgressDialog *progressDialog);
/**
* Reads a frame following to the current one returns it.
* @param imgFrame Altered read frame (contains tracked objects) converted to be displayed in QT
* @param originalImgFrame Read frame converted to be displayed in QT.
* @param includeOriginal Should be original frame read? If not, originalImgFrame does not contain a valid frame.
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @return True if successful
*/
bool get_next_frame(QImage &imgFrame, QImage &originalImgFrame, bool includeOriginal, QProgressDialog *progressDialog);
/**
* Reads a frame preceding to the current one returns it.
* @param imgFrame Altered read frame (contains tracked objects) converted to be displayed in QT
* @param originalImgFrame Read frame converted to be displayed in QT.
* @param includeOriginal Should be original frame read? If not, originalImgFrame does not contain a valid frame.
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @return True if successful
*/
bool get_previous_frame(QImage &imgFrame, QImage &originalImgFrame, bool includeOriginal, QProgressDialog *progressDialog);
/**
* Gets the current frame and returns it.
* @param imgFrame Altered read frame (contains tracked objects) converted to be displayed in QT
* @param originalImgFrame Read frame converted to be displayed in QT.
* @param includeOriginal Should be original frame read? If not, originalImgFrame does not contain a valid frame.
* @return True if successful
*/
bool get_current_frame(QImage &imgFrame, QImage &originalImgFrame, bool includeOriginal);
/**
* Reads the first frame and returns it.
* @param imgFrame Altered read frame (contains tracked objects) converted to be displayed in QT
* @param originalImgFrame Read frame converted to be displayed in QT.
* @param includeOriginal Should be original frame read? If not, originalImgFrame does not contain a valid frame.
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @return True if successful
*/
bool get_first_frame(QImage &imgFrame, QImage &originalImgFrame, bool includeOriginal, QProgressDialog *progressDialog);
/**
* Creates an output media file including all tracked objects.
* Throws UserCanceledException when user clicked "Cancel" button in the progress dialog
* Mind there are two progress dialogs. One is in track_all() and displays infinet progress
* bar when counting objects positions. The second progress dialog (fileProgressDialog shows percentage of
* creating the output file. When the first one (in track_all()) is canceled, the second one should be
* canceled too
* @param filename Output filename
* @param fileProgressDialog QT progress dialog for showing an information about creating the file progress
* @param trackingProgressDialog QT progress dialog for showing an information about tracking objects process
* @param inFileExtension Input file extensions
*/
void create_output(std::string const &filename, QProgressDialog &fileProgressDialog,
QProgressDialog *trackingProgressDialog, std::string inFileExtension);
/**
* Returns appearance of the object.
* @param objectID Object ID
* @return Object appearance
*/
Characteristics get_object_appearance(unsigned int objectID) const;
/**
* Returns trajectory sections of the object.
* @param objectID Object ID
* @return Trajectory section of the object
*/
std::map<int64_t, TrajectorySection> const &get_object_trajectory_sections(unsigned int objectID) const;
/**
* Returns computed trajectory of the object.
* @param objectID Object ID
* @return Trajectory of the object
*/
std::map<int64_t, TrajectoryEntry> const &get_object_trajectory(unsigned int objectID) const;
/**
* Changes appearance of the object.
* @param objectID Object ID
* @param newAppearance New appearance of the object
*/
bool change_object_appearance(unsigned int objectID, Characteristics const &newAppearance);
/**
* Rewinds the video to its beginning by seeking its first packet.
*/
void seek_first_packet();
// int64_t get_object_end_timestamp(unsigned int objectID, bool &isSet);
/**
* Return information about the end of the object.
* @param objectID Object ID
* @param timestamp Frame timestamp
* @param timePosition Time position
* @param frameNumber Frame number (index)
* @return True if end is set, false if it is not.
*/
bool get_object_end(unsigned int objectID, int64_t &timestamp, unsigned long &timePosition, unsigned long &frameNumber);
/**
* Changes a trajectory section of the object.
* @param objectID Object ID
* @param oldTimestamp Old timestamp of the section
* @param newTimestamp New timestamp of the section
* @param position Object position at the first frame of the section
* @param timePosition Time position of the section
* @param frameNumber Frame number of the section
* @return True if successful
*/
bool change_object_trajectory_section(unsigned int objectID, int64_t oldTimestamp, int64_t newTimestamp, Selection position, unsigned long timePosition, unsigned long frameNumber);
/**
* Changes the end frame of the object. If set==false, the end frame will be unset and the object
* will be tracked till the end of the video. newTimestamp and timePosition are valid onlt if set==true.
* @param objectID Object ID
* @param set Set / Unset last frame
* @param newTimestamp Timestamp of the last frame
* @param timePosition Time position of the last frame
* @param frameNumber Frame number of the last frame
* @return False if given timestamp is lower than the timestamp of Beginning.
*/
bool change_object_end_frame(unsigned int objectID, bool set, int64_t newTimestamp=0, unsigned long timePosition=0, unsigned long frameNumber=0);
/**
* Deletes a trajectory section of the object
* @param objectID Object ID
* @param timestamp Trajectory section to be deleted begins at this timestamp
* @return True if successful
*/
bool delete_object_trajectory_section(unsigned int objectID, int64_t timestamp);
/**
* Sets a trajectory section of the object.
* @param objectID Object ID
* @param newTimestamp New timestamp of the section
* @param position Object position at the first frame of the section
* @param timePosition Time position of the section
* @param frameNumber Frame number of the section
* @return True if successful
*/
bool set_object_trajectory_section(unsigned int objectID, int64_t newTimestamp, Selection position, unsigned long timePosition, unsigned long frameNumber);
/**
* Returns name of the object.
* @param objectID Object ID
* @return Object name
*/
std::string get_object_name(unsigned int objectID);
/**
* Returns names of all objects.
* @return Names of all objects
*/
std::vector<std::string> get_all_objects_names();
/**
* Sets name of the object.
* @param objectID Object ID
* @param newName New object name
* @return True if successful
*/
void set_object_name(unsigned int objectID, std::string newName);
/**
* Removes the object
* @param objectID Object ID
*/
void delete_object(unsigned int objectID);
/**
* Computes all trajectory for the tracked object
* @param objectID ObjectID
* @param progressDialog QT progress dialog for showing an information about tracking object process
* @return True if successful
*/
bool track_object(unsigned int objectID, QProgressDialog *progressDialog);
/**
* Erases a part of the computed trajectory. This is necessary after deserialization (with CEREAL)
* as track_next() initializes correct sections only when the trajectory's last frame is the last
* frame of the previous section.
* @param objectID ObjectID
*/
void erase_object_trajectories_to_comply();
private:
/**
* Converts cv::Mat format (OpenCV frame) to QImage (QT)
* @param src Source frame in cv::Mat
* @return Frame for QT
*/
QImage Mat2QImage(cv::Mat const &src) const;
// previousTimestamp can be used only when previousTimestampSet==true
/**
* Draws tracking mark to the result cv::Mat. If current frame was not yet processed, processes tracking till this frame.
* @param originalFrame Original frame
* @param result Altered frame; with drawn tracked objects
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @param previousTimestampSet Used only with get_next_frame(). True - this is the following frame to the one given the last time.
* @param previousTimestamp Timestamp of the preceding frame. This is used only if previousTimestampSet==true.
* @return Returns true if successful
*/
bool track_frame(VideoFrame const *originalFrame, cv::Mat &result, QProgressDialog *progressDialog=nullptr, bool previousTimestampSet=false, int64_t previousTimestamp=0);
/**
* Tracks all frames. This is called when an output media file is being created.
* @param progressDialog QT progress dialog for showing an information about tracking objects process
* @return True if successful
*/
bool track_all(QProgressDialog *progressDialog);
private:
QApplication *qApplication; // Is used for updating progress bars
std::shared_ptr<TrackedObject> a;
FFmpegPlayer *player;
VideoFrame *currentFrame;
VideoFrame *tempFrame;
std::vector<std::shared_ptr<TrackedObject>> trackedObjects;
};
#endif // VIDEOTRACKER_H