DarkHelp  v1.9.2-1
C++ API for the neural network framework Darknet
Looking for a C++ dev who knows OpenCV?
I'm looking for work. Hire me!
DarkHelp::PositionTracker Class Referencefinal

This class attempts to do very simple object tracking based on the position of the object. More...

#include "DarkHelpPositionTracker.hpp"

Collaboration diagram for DarkHelp::PositionTracker:

Classes

struct  Obj
 The position tracker uses Obj to keep information on objects that are being tracked. More...
 

Public Types

using Objects = std::list< Obj >
 A std::list type definition of objects. More...
 

Public Member Functions

 PositionTracker ()
 Constructor. More...
 
 ~PositionTracker ()
 Destructor. More...
 
PositionTrackeradd (DarkHelp::PredictionResults &results)
 Add the DarkHelp results to the tracker so it can start assinging OIDs. More...
 
PositionTrackerclear ()
 Removes all objects being tracked and resets the frame ID and object ID variables. More...
 
bool empty () const
 Returns true if zero objects are being tracked, otherwise returns false. More...
 
const Objget (const size_t oid) const
 Get a reference to the object that matches the given OID. More...
 
size_t size () const
 Returns the total number of objects currently being tracked. More...
 

Public Attributes

size_t age_of_objects_before_deletion
 When an object hasn't been seen for several frames, it is removed from the tracker and all associated data is deleted. More...
 
double maximum_distance_to_consider
 The maximum distance the tracker will consider when attempting to find a match between an object on a previous frame and one on a new frame. More...
 
size_t maximum_number_of_frames_per_object
 This is used to limit the number of frames and rectangles stored for each tracked object. More...
 
size_t most_recent_frame_id
 The most recent frame ID that was added to the tracker. More...
 
size_t most_recent_object_id
 The most recent object ID that was added to the tracker. More...
 
Objects objects
 A "database" of all the currently tracked objects. More...
 

Protected Member Functions

PositionTrackerprocess (const size_t frame_id, DarkHelp::PredictionResults &results)
 This is called internally by DarkHelp::PositionTracker::add(). More...
 
PositionTrackerremove_old_objects ()
 This is called internally by DarkHelp::PositionTracker::add(). More...
 

Detailed Description

This class attempts to do very simple object tracking based on the position of the object.

It assumes that objects move a small amount between frames, and don't randomly appear and disapear from view.

The tracker stores location rectangles for all objects. This data is kept in DarkHelp::PositionTracker::Obj::fids_and_rects which stores the rectangles by frame IDs (aka "fids"). This mapping between frame IDs and rectangles increases in size very quickly, which is why the tracker places a limit on how large it is allowed to grow. This can be modified using DarkHelp::PositionTracker::maximum_number_of_frames_per_object. This puts an upper limit on the number of past rectangles, meaning that recent location is kept while older historical location rectangles are deleted.

When a new frame is processed and DarkHelp::PositionTracker::add() is called with the results, the tracker computes the distance between the center of the rectangle to the previous known center coordinates of all tracked objects. The possible classes are compared, and already-identified objects are excluded. The remaining results are ordered by distance between past known locations and the new current location. If the distance is less than or equal to DarkHelp::PositionTracker::maximum_distance_to_consider then we assume this is a match, and we assign it the same object ID as the previous frame. If the distance is greater, then we assume this is a new object and assign it a new unique object ID.

Once an object has not appeared (or matched) for several consecutive frames, all information on that object is removed from the container of tracked objects. The length of time (aka "frames") before this behaviour triggers is controlled using DarkHelp::PositionTracker::age_of_objects_before_deletion.

  • This tracker works best when the camera frame rate is high enough to minimize the distance an object moves.
  • This tracker makes no attempt to re-identify objects that move off-screen and then come back into view. A new ID will be assigned to the object.
See also
DarkHelp::PositionTracker::PositionTracker()
Since
May 2023

Member Typedef Documentation

◆ Objects

A std::list type definition of objects.

See also
DarkHelp::PositionTracker::objects

Constructor & Destructor Documentation

◆ PositionTracker()

DarkHelp::PositionTracker::PositionTracker ( )

Constructor.

Instantiate one of these trackers (on the stack, or as a member of another class for example) and every time you call DarkHelp::NN::predict() you need to pass the results into the tracker. For example:

DarkHelp::NN nn("pigs.cfg", "pigs.names", "pigs_best.weights");
cv::VideoCapture cap("pigs.mp4");
while (cap.isOpened())
{
cv::Mat frame;
cap >> frame;
if (frame.empty())
{
break;
}
auto results = nn.predict(mat);
tracker.add(results);
std::cout << results << std::endl;
std::cout << tracker << std::endl;
for (const auto & prediction : results)
{
// get the tracking details for this specific prediction
const auto & obj = tracker.get(prediction.object_id);
cv::putText(mat, std::to_string(obj.oid), obj.center(), cv::FONT_HERSHEY_SIMPLEX, 0.75, {0, 0, 0}, 1, cv::LINE_AA);
// use the many rectangles stored in obj.fids_and_rects to draw the tail
// ...etc...
}
cv::imshow("output", mat);
cv::waitKey();
}

Once the call into PositionTracker::add() returns, the results will have been modified with the unique tracking object IDs (DarkHelp::PredictionResult::object_id).

DarkHelp itself doesn't draw the tracking details on images. But it is trivial to use standard OpenCV calls like cv::putText() and cv::circle() to add object IDs and tails to images:

See also
DarkHelp::PositionTracker::add()
DarkHelp::PositionTracker::get()
DarkHelp::PositionTracker::age_of_objects_before_deletion
DarkHelp::PositionTracker::maximum_number_of_frames_per_object
DarkHelp::PositionTracker::maximum_distance_to_consider

References clear().

Here is the call graph for this function:

◆ ~PositionTracker()

DarkHelp::PositionTracker::~PositionTracker ( )

Destructor.

Member Function Documentation

◆ add()

DarkHelp::PositionTracker & DarkHelp::PositionTracker::add ( DarkHelp::PredictionResults results)

Add the DarkHelp results to the tracker so it can start assinging OIDs.

This automatically increments the frame ID counter and calls process() internally to manage matching up the predictions with all known tracked objects, as well as creating new entries for objects that have not yet been seen.

Note
You must remember to call add() for every video frame to ensure objects are properly tracked. See the example code in DarkHelp::PositionTracker::PositionTracker().

Referenced by main().

Here is the caller graph for this function:

◆ clear()

DarkHelp::PositionTracker & DarkHelp::PositionTracker::clear ( )

Removes all objects being tracked and resets the frame ID and object ID variables.

This will also reset all the configuration variables such as DarkHelp::PositionTracker::maximum_distance_to_consider and DarkHelp::PositionTracker::maximum_number_of_frames_per_object to their default values.

References clear().

Referenced by clear(), and PositionTracker().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ empty()

bool DarkHelp::PositionTracker::empty ( ) const
inline

Returns true if zero objects are being tracked, otherwise returns false.

References objects.

◆ get()

const DarkHelp::PositionTracker::Obj & DarkHelp::PositionTracker::get ( const size_t  oid) const

Get a reference to the object that matches the given OID.

This will throw if the requested OID does not exist. The object will provide you with the frame ID where the object first appeared, the frame ID when it was last seen, and the corresponding bounding box rectangles for many of the previous frames.

The number of items stored and retrieved for each object is determined by DarkHelp::PositionTracker::maximum_number_of_frames_per_object.

Referenced by main().

Here is the caller graph for this function:

◆ process()

DarkHelp::PositionTracker & DarkHelp::PositionTracker::process ( const size_t  frame_id,
DarkHelp::PredictionResults results 
)
protected

◆ remove_old_objects()

DarkHelp::PositionTracker & DarkHelp::PositionTracker::remove_old_objects ( )
protected

This is called internally by DarkHelp::PositionTracker::add().

◆ size()

size_t DarkHelp::PositionTracker::size ( ) const
inline

Returns the total number of objects currently being tracked.

References objects.

Member Data Documentation

◆ age_of_objects_before_deletion

size_t DarkHelp::PositionTracker::age_of_objects_before_deletion

When an object hasn't been seen for several frames, it is removed from the tracker and all associated data is deleted.

This includes frame references, bounding rectangles, and object ID. The length of time it takes for this to happen is measured in frames. If you set it for too long, then the object ID might end up being re-used if a new object appears near the same location. If it is set too short then an object may jump to a new object ID if detection misses it in several consecutive frames.

The right value to use depends on how quickly the objects in your video move, how successful detection is on every frame, whether your objects may be momentarily obscured from view, and the FPS for your input video.

This value is the number of consecutive frames that must elapse before an object is removed. Set to zero to keep all objects. Default value is 10.

Since
May 2023

◆ maximum_distance_to_consider

double DarkHelp::PositionTracker::maximum_distance_to_consider

The maximum distance the tracker will consider when attempting to find a match between an object on a previous frame and one on a new frame.

If the distance between the old position and the new position is greater than this value, then a match will not be made and the object will instead be assigned a new ID. The value you use for this will depend on:

  • your image size,
  • your network dimensions,
  • and most importantly, the rate at which objects are moving across the image.

This value is the distance in pixels between the old position and the new position. The reason it is a double and not an int is because the distance is calculated using cv::norm() (aka pythagoras).

Default value is 100.0.

Since
May 2023

◆ maximum_number_of_frames_per_object

size_t DarkHelp::PositionTracker::maximum_number_of_frames_per_object

This is used to limit the number of frames and rectangles stored for each tracked object.

The first and last few frames and rectangles are always kept, but those in the middle can be pruned to limit the amount of memory that object tracking consumes. Set to zero to keep all frames and rectangles. Default value is 90, which is 3 seconds of data with a typical 30 FPS video.

Since
May 2023

Referenced by main().

◆ most_recent_frame_id

size_t DarkHelp::PositionTracker::most_recent_frame_id

The most recent frame ID that was added to the tracker.

This is automatically incremented when calling add(). The special value zero is resrved to indicate no frame ID. This means frames are numbered sequentially starting with 1.

Under normal circumstances you shouldn't need to access nor modify this value.

Referenced by DarkHelp::operator<<().

◆ most_recent_object_id

size_t DarkHelp::PositionTracker::most_recent_object_id

The most recent object ID that was added to the tracker.

This is automatically incremented when calling add(). The special value zero is reserved to indicate no object ID. This means objects are numbered sequentially starting with 1.

Under normal circumstances you shouldn't need to access nor modify this value.

Referenced by DarkHelp::operator<<().

◆ objects

Objects DarkHelp::PositionTracker::objects

A "database" of all the currently tracked objects.

This is regularly prunned by automatic calls to remove_old_objects().

Under normal circumstances you shouldn't need to access nor modify this value. Instead, use DarkHelp::PositionTracker::get().

See also
add()
get()

Referenced by empty(), DarkHelp::operator<<(), and size().


The documentation for this class was generated from the following files:
DarkHelp::NN::predict
PredictionResults predict(const std::string &image_filename, const float new_threshold=-1.0f)
Use the neural network to predict what is contained in this image.
Definition: DarkHelpNN.cpp:450
DarkHelp::PositionTracker
This class attempts to do very simple object tracking based on the position of the object.
Definition: DarkHelpPositionTracker.hpp:45
DarkHelp::NN
Instantiate one of these objects by giving it the name of the .cfg and .weights file,...
Definition: DarkHelpNN.hpp:60
DarkHelp::PositionTracker::add
PositionTracker & add(DarkHelp::PredictionResults &results)
Add the DarkHelp results to the tracker so it can start assinging OIDs.
Definition: DarkHelpPositionTracker.cpp:106
DarkHelp::PositionTracker::get
const Obj & get(const size_t oid) const
Get a reference to the object that matches the given OID.
Definition: DarkHelpPositionTracker.cpp:121