TrackerCSRT is extremely slow with OpenCV 4.10.0

I am using the TrackerCSRT in OpenCV 4.10.0 and it’s so slow I can’t use it. I’ve tested this code on the Jetson Nano and on my laptop and have similar results. FYI, I had originally written this with OpenCV 4.5.0 on my Jetson, and had great real time performance so I’m not sure why it’s so slow right now.

Code summary:

  1. Detect object (in another code file)
  2. Wrap video image to make it compatible with opencv. It is a uchar3* type which I wrap with
image_cv_wrapped = cv::Mat(input_video_height, input_video_width, CV_8UC3, image);
  1. Extract the bounding box information from the detected object to use as a starting point for the tracker.
  2. In Track::track_target() I make sure I have a valid image before I start tracking.
  3. Initialize the tracker with the bounding box from the detected object with
  target_bounding_box = cv::Rect(target_left, target_top, target_width, target_height);
  tracker_init(target_tracker, image_cv_wrapped, target_bounding_box);
  1. Start tracking
target_tracked = tracker_update(target_tracker, image_cv_wrapped, target_bounding_box);

Full code:

bool target_tracked;
bool tracking;
bool initialized_cv_image;
bool initialized_tracker;
bool target_valid;
bool target_valid_prv;
int target_detection_ID;
int target_track_ID;
float target_cntr_offset_x;
float target_cntr_offset_y;
float target_center_y;
float target_center_x;
float target_height;
float target_width;
float target_aspect;
float target_left;
float target_right;
float target_top;
float target_bottom;

cv::cuda::GpuMat gpuImage;
cv::Mat image_cv_wrapped;
cv::Ptr<cv::TrackerCSRT> target_tracker;
cv::Rect target_bounding_box;

/********************************************************************************
 * Calibration definitions
 ********************************************************************************/
const float center_of_frame_width = 640.0f;
const float center_of_frame_height = 360.0f;

/********************************************************************************
* Function definitions
********************************************************************************/

/********************************************************************************
* Function: Track
* Description: Track class constructor.
********************************************************************************/
Track::Track(void) {};

/********************************************************************************
* Function: ~Track
* Description: Track class destructor.
********************************************************************************/
Track::~Track(void) {};

/********************************************************************************
* Function: tracker_init
* Description: Initialize the tracker by resetting the bounding box to zeros.
********************************************************************************/

bool Track::tracker_init(cv::Ptr<cv::TrackerCSRT> &tracker, cv::Mat &cv_image, cv::Rect &bounding_box)
{
  tracker->init(cv_image, bounding_box);

  return true;
}

/********************************************************************************
* Function: tracker_update
* Description: Update the bounding box around the tracked target.
********************************************************************************/
bool Track::tracker_update(cv::Ptr<cv::TrackerCSRT> &tracker, cv::Mat &cv_image, cv::Rect &bounding_box)
{
  bool success;
  try {
      success = tracker->update(cv_image, bounding_box);
      if (!success) {
          std::cerr << "Tracking failed." << std::endl;
      }
  }
  catch (const cv::Exception& e) {
      std::cerr << "OpenCV error: " << e.what() << std::endl;
  }

  return success;
}

/********************************************************************************
* Function: identify_target
* Description: Determine which detected object to track.
********************************************************************************/
void Track::identify_target(void)
{
  target_detection_ID = -1;

  for (int n = 0; n < detection_count; n++)
  {
      /* A tracked object, classified as a person with some confidence level */
      if (detections[n].TrackID >= 0 && detections[n].ClassID == 1 && detections[n].Confidence > 0.5)
      {
          target_detection_ID = n;
      }
  }
}

/********************************************************************************
* Function: get_target_info
* Description: Obtain the important information about the target, such as the
*              height and location of the center of the target in the frame.
********************************************************************************/
void Track::get_target_info(void)
{
  target_height = detections[target_detection_ID].Height();
  target_width = detections[target_detection_ID].Width();
  target_track_ID = detections[target_detection_ID].TrackID;
  target_left = detections[target_detection_ID].Left;
  target_right = detections[target_detection_ID].Right;
  target_top = detections[target_detection_ID].Top;
  target_bottom = detections[target_detection_ID].Bottom;
  target_center_y = (target_left + target_right) / 2.0f;
  target_center_x = (target_bottom + target_top) / 2.0f;
  target_cntr_offset_y = target_center_y - center_of_frame_width;
  target_cntr_offset_x = target_center_x - center_of_frame_height;
  target_aspect = target_width / target_height;
}

/********************************************************************************
* Function: validate_target
* Description: Determine which detected object to track.
********************************************************************************/
void Track::validate_target(void)
{
  /* Target detected, tracked, and has a size greater than 0.  Controls based on the target may be
     implimented. */
  if (target_detection_ID >= 0 && target_track_ID >= 0 && target_height > 1 && target_width > 1)
  {
      target_valid = true;
  }
  else
  {
      target_valid = false;
  }

  target_valid_prv = target_valid;
}

/********************************************************************************
* Function: track_target
* Description: Use the bounding box provided by the detection model as the
*              basis for target_tracked the targeted object.
********************************************************************************/
void Track::track_target(void)
{
	/* Don't wrap the image from jetson inference until a valid image has been received.
	That way we know the memory has been allocaed and is ready. */
  if (valid_image_rcvd && !initialized_cv_image)
  {
      image_cv_wrapped = cv::Mat(input_video_height, input_video_width, CV_8UC3, image); // Directly wrap uchar3*
      initialized_cv_image = true;
  }
  else if (valid_image_rcvd && initialized_cv_image)
  {
      if (target_valid && !initialized_tracker)
      {
          target_bounding_box = cv::Rect(target_left, target_top, target_width, target_height);
          tracker_init(target_tracker, image_cv_wrapped, target_bounding_box);
          initialized_tracker = true;
      }

      if (initialized_tracker)
      {
          target_tracked = tracker_update(target_tracker, image_cv_wrapped, target_bounding_box);
      }

      if (target_tracked)
      {
          std::cout << "Tracking" << std::endl;
          cv::rectangle(image_cv_wrapped, target_bounding_box, cv::Scalar(255, 0, 0));

          tracking = true;
      }
      else
      {
          std::cout << "Not Tracking" << std::endl;
          initialized_tracker = false;
          tracking = false;
      }
  }
}

/********************************************************************************
* Function: update_target_info
* Description: Obtain the important information about the target, such as the
*              height and location of the center of the target in the frame.
********************************************************************************/
void Track::update_target_info(void)
{
  target_height = target_bounding_box.height;
  target_width = target_bounding_box.width;
  target_left = target_bounding_box.x;
  target_right = target_left + target_width;
  target_top = target_bounding_box.y;
  target_bottom = target_top + target_height;
  target_center_y = (target_left + target_right) / 2.0f;
  target_center_x = (target_bottom + target_top) / 2.0f;
  target_cntr_offset_y = target_center_y - center_of_frame_width;
  target_cntr_offset_x = target_center_x - center_of_frame_height;
  target_aspect = target_width / target_height;
}

/********************************************************************************
* Function: localize_target_init
* Description: Initialize all Track target variables.  Run once at the start
*              of the program.
********************************************************************************/
bool Track::init(void)
{
  target_valid = false;
  target_valid_prv = false;
  target_cntr_offset_x = 0.0f;
  target_cntr_offset_y = 0.0f;
  target_height = 0.0f;
  target_width = 0.0f;
  target_aspect = 0.0f;
  target_left = 0.0f;
  target_right = 0.0f;
  target_top = 0.0f;
  target_bottom = 0.0f;
  target_detection_ID = -1;

  initialized_cv_image = false;
  target_tracked = false;
  tracking = false;
  target_bounding_box = cv::Rect(0.0, 0.0, 0.0, 0.0);
  target_tracker = cv::TrackerCSRT::create();

  return true;
}

/********************************************************************************
* Function: localize_control_loop
* Description: Return control parameters for the vehicle to Track a designated
*              target at a distance.
********************************************************************************/
void Track::loop(void)
{
  identify_target();
  get_target_info();
  validate_target();
  track_target();
  // update_target_info();
}