I have a tracking program as given below. I draw two ROI's (rectangle boxes) in the first frame of a video and the object in these ROI's are tracked in the whole video. I want to obtain the x&y coordinates of the ROI's that will be tracked in the video (that is, position of the 2 ROI's from all frames of the video). I can see these value when debugging but when I try to print them using bboxes[0].x,bboxes[0].y,bboxes[1].x,bboxes[1].y
for each frame, I am getting the same value for all the frames. What am I doing wrong here?
#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
using namespace std;
// Convert to string
//#define SSTR( x ) static_cast< std::ostringstream & >( \
( std::ostringstream() << std::dec << x ) ).str()
vector<string> trackerTypes = { "BOOSTING", "MIL", "KCF", "TLD", "MEDIANFLOW", "GOTURN", "MOSSE", "CSRT" };
// create tracker by name
Ptr<Tracker> createTrackerByName(string trackerType)
{
Ptr<Tracker> tracker;
if (trackerType == trackerTypes[0])
tracker = TrackerBoosting::create();
else if (trackerType == trackerTypes[1])
tracker = TrackerMIL::create();
else if (trackerType == trackerTypes[2])
tracker = TrackerKCF::create();
else if (trackerType == trackerTypes[3])
tracker = TrackerTLD::create();
else if (trackerType == trackerTypes[4])
tracker = TrackerMedianFlow::create();
else if (trackerType == trackerTypes[5])
tracker = TrackerGOTURN::create();
else if (trackerType == trackerTypes[6])
tracker = TrackerMOSSE::create();
else if (trackerType == trackerTypes[7])
tracker = TrackerCSRT::create();
else {
cout << "Incorrect tracker name" << endl;
cout << "Available trackers are: " << endl;
for (vector<string>::iterator it = trackerTypes.begin(); it != trackerTypes.end(); ++it)
std::cout << " " << *it << endl;
}
return tracker;
}
// Fill the vector with random colors
void getRandomColors(vector<Scalar> &colors, int numColors)
{
RNG rng(0);
for (int i = 0; i < numColors; i++)
colors.push_back(Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)));
}
int main(int argc, char * argv[])
{
cout << "Available tracking algorithms are:" << endl;
for (vector<string>::iterator it = trackerTypes.begin(); it != trackerTypes.end(); ++it)
std::cout << " " << *it << endl;
string trackerType = "KCF";
cout << "The Selected tracker is " << trackerType << endl;
string videoPath = "SS-100_zoom_Trim.mp4";
// Initialize MultiTracker with tracking algo
vector<Rect> bboxes;
Mat frame;
cv::VideoCapture cap(videoPath);
//cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
//cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
if (!cap.isOpened())
{
cout << "Error opening video file " << videoPath << endl;
return -1;
}
cap >> frame;
bool showCrosshair = true;
bool fromCenter = false;
cv::selectROIs("MultiTracker", frame, bboxes, showCrosshair, fromCenter);
if (bboxes.size() < 1)
return 0;
vector<Scalar> colors;
getRandomColors(colors, bboxes.size());
// Create multitracker
Ptr<MultiTracker> multiTracker = cv::MultiTracker::create();
// initialize multitracker
for (int i = 0; i < bboxes.size(); i++)
multiTracker->add(createTrackerByName(trackerType), frame, Rect2d(bboxes[i]));
cout << "Started tracking, press ESC to quit." << endl;
while (cap.isOpened())
{
cap >> frame;
if (frame.empty()) break;
//update the tracking result with new frame
multiTracker->update(frame);
putText(frame, trackerType + " Tracker", Point(100, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(50, 170, 50), 2);
// draw tracked objects
for (unsigned i = 0; i < multiTracker->getObjects().size(); i++)
{
rectangle(frame, multiTracker->getObjects()[i], colors[i], 2, 1);
}
cout << "\nPosition of box1 in X-axis :" << bboxes[0].x << endl;
cout << "\nPosition of box1 in Y-axis :" << bboxes[0].y << endl;
cout << "\nPosition of box2 in X-axis :" << bboxes[1].x << endl;
cout << "\nPosition of box2 in Y-axis :" << bboxes[1].y << endl;
resize(frame, frame, Size(1280, 720), 0, 0, INTER_CUBIC);
imshow("MultiTracker", frame);
if (waitKey(1) == 27) break;
}
}
The bboxes.size() is 2 , since i am drawing only 2 ROI's. I am using OpenCV 3.4.1 and Visual Studio 2015
As mentioned by @Nicolas Gaborel, you are not updating the values of bboxes
. There are two ways of doing this
If order does not matter, then simply do bboxes[i] = multiTracker->getObjects()[i]
inside your for-loop
If you also want to keep track of the order, then you need to assign some sort of ID to the detected boxes. A quick way of doing so is by first computing the centroids of the rectangles and storing them. Once an object is detected, you compute the centroid of the object's rectangle. Thereafter compute the Euclidean distance of the detected object's centroid and those stored in bboxes
. The rectangle with the minimum distance in bboxes
is the correct one.