Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
tracking::MultiTracker Class Reference

Class for tracking multiple bounding boxes in images using OpenCV. This class supports all OpenCV tracking algorithms and can be used to track multiple objects in a single image or video stream. More...

#include <BoundingBoxTracking.h>

Public Member Functions

 MultiTracker (const double dTrackingLostTimeout=1.0, const double dMaxTrackingTime=3.0, const double dIOUThreshold=0.3)
 Construct a new Multi Tracker object.
 
 ~MultiTracker ()
 Destroy the Multi Tracker object.
 
bool InitTracker (const cv::Mat &cvFrame, const std::shared_ptr< cv::Rect2d > cvBoundingBox, const TrackerType eTrackerType=TrackerType::eKCF)
 Add a new tracker for a given frame and bounding box.
 
void Update (const cv::Mat &cvFrame)
 Initialize the MultiTracker with a new frame and a vector of bounding boxes.
 
void ClearTrackers ()
 Clear all trackers and bounding boxes from the MultiTracker.
 
void SetTrackerLostTimeout (const double dTimeout)
 Set the timeout for when a tracker is considered lost.
 
void SetMaxTrackingTime (const double dMaxTime)
 Set the maximum tracking time for a tracker.
 
double GetTrackerLostTimeout () const
 Get the timeout for when a tracker is considered lost.
 
double GetMaxTrackingTime () const
 Get the maximum tracking time for a tracker.
 

Private Member Functions

double CalculateIOU (const cv::Rect2d &cvBoxA, const cv::Rect2d &cvBoxB)
 Calculate the Intersection over Union (IoU) of two bounding boxes.
 
cv::Ptr< cv::TrackerCreateTracker (const TrackerType eType)
 Create a tracker based on the specified type.
 

Private Attributes

std::map< int, cv::Ptr< cv::Tracker > > m_mTrackers
 
std::map< int, std::shared_ptr< cv::Rect2d > > m_mBoundingBoxes
 
std::map< int, std::chrono::system_clock::time_point > m_mLastUpdateTime
 
std::map< int, std::chrono::system_clock::time_point > m_mTimeSinceLastGroundTruthDetection
 
double m_dTrackingLostThreshold
 
double m_dMaxTrackingTime
 
double m_dIOUThreshold
 
int m_nNextId
 

Detailed Description

Class for tracking multiple bounding boxes in images using OpenCV. This class supports all OpenCV tracking algorithms and can be used to track multiple objects in a single image or video stream.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-14

Constructor & Destructor Documentation

◆ MultiTracker()

tracking::MultiTracker::MultiTracker ( const double  dTrackingLostThreshold = 1.0,
const double  dMaxTrackingTime = 3.0,
const double  dIOUThreshold = 0.3 
)

Construct a new Multi Tracker object.

Parameters
dTrackingLostThreshold- The time in seconds after which a tracker is considered lost (default is 1.0).
dMaxTrackingTime- The maximum time in seconds a tracker can be lost before being removed (default is 3.0).
dIOUThreshold- The minimum Intersection over Union (IoU) required to associate a new detection with an existing tracker (default is 0.3).
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-15
39 {
40 // Initialize member variables.
41 m_dTrackingLostThreshold = dTrackingLostThreshold;
42 m_dMaxTrackingTime = dMaxTrackingTime;
43 m_dIOUThreshold = dIOUThreshold;
44 m_nNextId = 0;
45 }

◆ ~MultiTracker()

tracking::MultiTracker::~MultiTracker ( )

Destroy the Multi Tracker object.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-15
55 {
56 // Nothing to do yet.
57 }

Member Function Documentation

◆ InitTracker()

bool tracking::MultiTracker::InitTracker ( const cv::Mat cvFrame,
const std::shared_ptr< cv::Rect2d cvBoundingBox,
const TrackerType  eTrackerType = TrackerType::eKCF 
)

Add a new tracker for a given frame and bounding box.

Parameters
cvFrame- The frame to initialize the tracker with.
cvBoundingBox- The bounding box (cv::Rect2d) for the object to track.
eTrackerType- The type of tracker to use (default is KCF).
Returns
true - The given bounding box was matched to an existing tracker and the tracker was updated.
false - The given bounding box was not matched to an existing tracker and a new tracker was created.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-15
72 {
73 // Create instance variables.
74 double dBestIOU = 0.0;
75 int nBestTrackerID = -1;
76 bool bMatchedOldTracker = false;
77
78 // Loop through the existing trackers to find the best match for the given bounding box.
79 for (const std::pair<int, std::shared_ptr<cv::Rect2d>>& stdEntry : m_mBoundingBoxes)
80 {
81 int nID = stdEntry.first;
82 double dIOU = this->CalculateIOU(*stdEntry.second, *cvBoundingBox);
83 if (dIOU > dBestIOU)
84 {
85 dBestIOU = dIOU;
86 nBestTrackerID = nID;
87 }
88 }
89
90 // Catch OpenCV exceptions.
91 try
92 {
93 // If the best IoU is above the threshold and a tracker was found, update the tracker.
94 if (dBestIOU > m_dIOUThreshold && nBestTrackerID != -1)
95 {
96 // Reinitialize the tracker with the new bounding box.
97 m_mBoundingBoxes[nBestTrackerID]->x = cvBoundingBox->x;
98 m_mBoundingBoxes[nBestTrackerID]->y = cvBoundingBox->y;
99 m_mBoundingBoxes[nBestTrackerID]->width = cvBoundingBox->width;
100 m_mBoundingBoxes[nBestTrackerID]->height = cvBoundingBox->height;
101 cv::Ptr<cv::Tracker> cvTracker = this->CreateTracker(eTrackerType);
102 cvTracker->init(cvFrame, *m_mBoundingBoxes[nBestTrackerID]);
103 // Update the last update time for the tracker.
104 m_mLastUpdateTime[nBestTrackerID] = std::chrono::system_clock::now();
105 // Update the time since the last ground truth detection.
106 m_mTimeSinceLastGroundTruthDetection[nBestTrackerID] = std::chrono::system_clock::now();
107 // Set the matched tracker flag.
108 bMatchedOldTracker = true;
109 }
110 else
111 {
112 // Create a new tracker and initialize it with the given frame and bounding box.
113 cv::Ptr<cv::Tracker> cvTracker = this->CreateTracker(eTrackerType);
114 cvTracker->init(cvFrame, *cvBoundingBox);
115 // Add the new tracker to the maps.
116 m_mTrackers[m_nNextId] = cvTracker;
117 m_mBoundingBoxes[m_nNextId] = cvBoundingBox;
118 m_mLastUpdateTime[m_nNextId] = std::chrono::system_clock::now();
119 m_mTimeSinceLastGroundTruthDetection[m_nNextId] = std::chrono::system_clock::now();
120 m_nNextId++;
121 }
122 }
123 catch (const std::exception& stdException)
124 {
125 // Submit logger message if an exception occurs.
126 LOG_ERROR(logging::g_qSharedLogger, "Exception in tracker initialization: {}", stdException.what());
127 // Set the bounding box to 0,0,0,0.
128 cvBoundingBox->x = 0;
129 cvBoundingBox->y = 0;
130 cvBoundingBox->width = 0;
131 cvBoundingBox->height = 0;
132 }
133
134 return bMatchedOldTracker;
135 }
cv::Ptr< cv::Tracker > CreateTracker(const TrackerType eType)
Create a tracker based on the specified type.
Definition BoundingBoxTracking.cpp:324
double CalculateIOU(const cv::Rect2d &cvBoxA, const cv::Rect2d &cvBoxB)
Calculate the Intersection over Union (IoU) of two bounding boxes.
Definition BoundingBoxTracking.cpp:305
std::shared_ptr< _Tp > Ptr
Here is the call graph for this function:

◆ Update()

void tracking::MultiTracker::Update ( const cv::Mat cvFrame)

Initialize the MultiTracker with a new frame and a vector of bounding boxes.

Parameters
cvFrame- The initial frame to track objects in.
Note
If the tracking for a bounding box is lost, it will be set to 0,0,0,0 and removed from the tracker.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-15
148 {
149 // Create instance variables.
150 std::vector<int> vToRemove;
151 std::chrono::system_clock::time_point tmCurrentTime = std::chrono::system_clock::now();
152
153 // Loop through the existing trackers.
154 for (const std::pair<const int, cv::Ptr<cv::Tracker>>& stdEntry : m_mTrackers)
155 {
156 // Create instance variables.
157 int nID = stdEntry.first;
158 cv::Rect cvBoundingBox;
159
160 // Check if the tracker is valid
161 if (!stdEntry.second)
162 {
163 LOG_WARNING(logging::g_qSharedLogger, "Tracker is null for ID: {}", std::to_string(nID));
164 continue;
165 }
166
167 // OpenCV loves to throw exceptions, so we need to catch them.
168 try
169 {
170 // Try to update the tracker with the current frame.
171 if (stdEntry.second->update(cvFrame, cvBoundingBox))
172 {
173 // Update the bounding box
174 m_mBoundingBoxes[nID]->x = cvBoundingBox.x;
175 m_mBoundingBoxes[nID]->y = cvBoundingBox.y;
176 m_mBoundingBoxes[nID]->width = cvBoundingBox.width;
177 m_mBoundingBoxes[nID]->height = cvBoundingBox.height;
178 m_mLastUpdateTime[nID] = tmCurrentTime;
179 }
180
181 // If the tracker fails to update, we need to check if it has been lost for too long.
182 double dTimeElapsedSinceGoodTrack = std::chrono::duration_cast<std::chrono::milliseconds>(tmCurrentTime - m_mLastUpdateTime[nID]).count() / 1000.0;
183 double dTimeElapsedSinceLastDetection =
184 std::chrono::duration_cast<std::chrono::milliseconds>(tmCurrentTime - m_mTimeSinceLastGroundTruthDetection[nID]).count() / 1000.0;
185 if (dTimeElapsedSinceGoodTrack > m_dTrackingLostThreshold || dTimeElapsedSinceLastDetection > m_dMaxTrackingTime)
186 {
187 vToRemove.push_back(nID);
188 }
189 }
190 catch (const std::exception& stdException)
191 {
192 // Submit logger message if an exception occurs.
193 LOG_ERROR(logging::g_qSharedLogger, "Exception in tracker update for ID: {} Error {}", nID, stdException.what());
194 // Remove the problematic tracker.
195 vToRemove.push_back(nID);
196 }
197 }
198
199 // Remove trackers that have been lost for too long.
200 for (int nID : vToRemove)
201 {
202 // Remove the tracker and last update time from the maps.
203 m_mTrackers.erase(nID);
204 m_mLastUpdateTime.erase(nID);
205 m_mTimeSinceLastGroundTruthDetection.erase(nID);
206
207 // Set the bounding box to 0,0,0,0.
208 m_mBoundingBoxes[nID]->x = 0;
209 m_mBoundingBoxes[nID]->y = 0;
210 m_mBoundingBoxes[nID]->width = 0;
211 m_mBoundingBoxes[nID]->height = 0;
212 // Remove the bounding box from the map.
213 m_mBoundingBoxes.erase(nID);
214 }
215 }

◆ ClearTrackers()

void tracking::MultiTracker::ClearTrackers ( )

Clear all trackers and bounding boxes from the MultiTracker.

Note
This function will set all bounding boxes to 0,0,0,0 and remove all trackers.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-27
226 {
227 m_mTrackers.clear();
228 m_mLastUpdateTime.clear();
229 m_mTimeSinceLastGroundTruthDetection.clear();
230
231 // Set the bounding boxes to 0,0,0,0.
232 for (const std::pair<int, std::shared_ptr<cv::Rect2d>>& stdEntry : m_mBoundingBoxes)
233 {
234 stdEntry.second->x = 0;
235 stdEntry.second->y = 0;
236 stdEntry.second->width = 0;
237 stdEntry.second->height = 0;
238 }
239 // Clear the bounding boxes.
240 m_mBoundingBoxes.clear();
241 }

◆ SetTrackerLostTimeout()

void tracking::MultiTracker::SetTrackerLostTimeout ( const double  dTimeout)

Set the timeout for when a tracker is considered lost.

Parameters
dTimeout- The time in seconds after which a tracker is considered lost.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-29
252 {
253 m_dTrackingLostThreshold = dTimeout;
254 }

◆ SetMaxTrackingTime()

void tracking::MultiTracker::SetMaxTrackingTime ( const double  dMaxTime)

Set the maximum tracking time for a tracker.

Parameters
dMaxTime- The maximum time in seconds a tracker can be lost before being removed.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-04-15
265 {
266 m_dMaxTrackingTime = dMaxTime;
267 }

◆ GetTrackerLostTimeout()

double tracking::MultiTracker::GetTrackerLostTimeout ( ) const

Get the timeout for when a tracker is considered lost.

Returns
double - The time in seconds after which a tracker is considered lost.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-29
278 {
279 return m_dTrackingLostThreshold;
280 }

◆ GetMaxTrackingTime()

double tracking::MultiTracker::GetMaxTrackingTime ( ) const

Get the maximum tracking time for a tracker.

Returns
double - The maximum time in seconds a tracker can be lost before being removed.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-04-15
291 {
292 return m_dMaxTrackingTime;
293 }

◆ CalculateIOU()

double tracking::MultiTracker::CalculateIOU ( const cv::Rect2d cvBoxA,
const cv::Rect2d cvBoxB 
)
private

Calculate the Intersection over Union (IoU) of two bounding boxes.

Parameters
cvBoxA- The first bounding box (cv::Rect2d).
cvBoxB- The second bounding box (cv::Rect2d).
Returns
double - The IoU value between the two bounding boxes, ranging from 0.0 to 1.0.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-15
306 {
307 // Calculate the intersection area.
308 double dIntersectionArea = (cvBoxA & cvBoxB).area();
309 // Calculate the union area.
310 double dUnionArea = cvBoxA.area() + cvBoxB.area() - dIntersectionArea;
311 // Return the Intersection over Union (IoU).
312 return (dUnionArea > 0) ? (dIntersectionArea / dUnionArea) : 0.0;
313 }
_Tp area() const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CreateTracker()

cv::Ptr< cv::Tracker > tracking::MultiTracker::CreateTracker ( const TrackerType  eType)
private

Create a tracker based on the specified type.

Parameters
eType- The type of tracker to create (eMIL, eKCF, eGOTURN, eCSRT).
Returns
cv::Ptr<cv::Tracker> - A pointer to the created tracker.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-03-29
325 {
326 // Catch OpenCV exceptions.
327 try
328 {
329 // Create a tracker based on the specified type.
330 switch (eType)
331 {
332 case TrackerType::eMIL: return cv::TrackerMIL::create(); break;
333 case TrackerType::eKCF: return cv::TrackerKCF::create(); break;
334 case TrackerType::eCSRT: return cv::TrackerCSRT::create(); break;
335 default:
336 // Submit a warning message if the tracker type is unknown.
337 LOG_WARNING(logging::g_qSharedLogger, "Unknown tracker type specified. Defaulting to KCF.");
338 // Return a default tracker (KCF) if the type is unknown.
339 return cv::TrackerKCF::create();
340 break;
341 }
342 }
343 catch (const std::exception& stdException)
344 {
345 // Submit a warning message if an exception occurs.
346 LOG_ERROR(logging::g_qSharedLogger, "Exception in tracker creation: {}", stdException.what());
347 // Return a default tracker (KCF) if an exception occurs.
348 return cv::TrackerKCF::create();
349 }
350 }
static Ptr< TrackerCSRT > create(const TrackerCSRT::Params &parameters=TrackerCSRT::Params())
static Ptr< TrackerKCF > create(const TrackerKCF::Params &parameters=TrackerKCF::Params())
static Ptr< TrackerMIL > create(const TrackerMIL::Params &parameters=TrackerMIL::Params())
Here is the caller graph for this function:

The documentation for this class was generated from the following files: