CV_XADD(&(u->refcount), 1);
CV_XADD(&(u->urefcount), 1);
}
- hdr.flags = flags;
- hdr.usageFlags = usageFlags;
- setSize(hdr, dims, size.p, step.p);
- finalizeHdr(hdr);
- hdr.u = new_u;
- hdr.offset = 0; //data - datastart;
- hdr.addref();
- return hdr;
+ try
+ {
+ hdr.flags = flags;
++ hdr.usageFlags = usageFlags;
+ setSize(hdr, dims, size.p, step.p);
+ finalizeHdr(hdr);
+ hdr.u = new_u;
+ hdr.offset = 0; //data - datastart;
+ hdr.addref();
+ return hdr;
+ }
+ catch(...)
+ {
+ if (u != NULL)
+ {
+ CV_XADD(&(u->refcount), -1);
+ CV_XADD(&(u->urefcount), -1);
+ }
+ new_u->currAllocator->deallocate(new_u);
+ throw;
+ }
++
}
void UMat::create(int d, const int* _sizes, int _type, UMatUsageFlags _usageFlags)
// TODO Support ACCESS_READ (ACCESS_WRITE) without unnecessary data transfers
accessFlags |= ACCESS_RW;
UMatDataAutoLock autolock(u);
- if(CV_XADD(&u->refcount, 1) == 0)
- u->currAllocator->map(u, accessFlags);
- if (u->data != 0)
+ try
{
- Mat hdr(dims, size.p, type(), u->data + offset, step.p);
- hdr.flags = flags;
- hdr.u = u;
- hdr.datastart = u->data;
- hdr.data = u->data + offset;
- hdr.datalimit = hdr.dataend = u->data + u->size;
- return hdr;
+ if(CV_XADD(&u->refcount, 1) == 0)
+ u->currAllocator->map(u, accessFlags);
+ if (u->data != 0)
+ {
+ Mat hdr(dims, size.p, type(), u->data + offset, step.p);
+ hdr.flags = flags;
+ hdr.u = u;
+ hdr.datastart = u->data;
+ hdr.data = u->data + offset;
+ hdr.datalimit = hdr.dataend = u->data + u->size;
+ return hdr;
+ }
}
- else
+ catch(...)
{
CV_XADD(&u->refcount, -1);
- CV_Assert(u->data != 0 && "Error mapping of UMat to host memory.");
- return Mat();
+ throw;
}
+ CV_XADD(&u->refcount, -1);
+ CV_Assert(u->data != 0 && "Error mapping of UMat to host memory.");
+ return Mat();
}
-void* UMat::handle(int accessFlags) const
+void* UMat::handle(AccessFlag accessFlags) const
{
if( !u )
return 0;
--- /dev/null
- return sqrt(pow(p_a.x - p_b.x, 2) + pow(p_a.y - p_b.y, 2));
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+
+/*
+ * The Evaluation Methodologies are partially based on:
+ * ====================================================================================================================
+ * [OTB] Y. Wu, J. Lim, and M.-H. Yang, "Online object tracking: A benchmark," in Computer Vision and Pattern Recognition (CVPR), 2013
+ *
+ */
+
+enum BBTransformations
+{
+ NoTransform = 0,
+ CenterShiftLeft = 1,
+ CenterShiftRight = 2,
+ CenterShiftUp = 3,
+ CenterShiftDown = 4,
+ CornerShiftTopLeft = 5,
+ CornerShiftTopRight = 6,
+ CornerShiftBottomLeft = 7,
+ CornerShiftBottomRight = 8,
+ Scale_0_8 = 9,
+ Scale_0_9 = 10,
+ Scale_1_1 = 11,
+ Scale_1_2 = 12
+};
+
+namespace {
+
+std::vector<std::string> splitString(const std::string& s_, const std::string& delimiter)
+{
+ std::string s = s_;
+ std::vector<string> token;
+ size_t pos = 0;
+ while ((pos = s.find(delimiter)) != std::string::npos)
+ {
+ token.push_back(s.substr(0, pos));
+ s.erase(0, pos + delimiter.length());
+ }
+ token.push_back(s);
+ return token;
+}
+
+float calcDistance(const Rect& a, const Rect& b)
+{
+ Point2f p_a((float)(a.x + a.width / 2), (float)(a.y + a.height / 2));
+ Point2f p_b((float)(b.x + b.width / 2), (float)(b.y + b.height / 2));
++ Point2f diff = p_a - p_b;
++ return sqrt(diff.dot(diff));
+}
+
+float calcOverlap(const Rect& a, const Rect& b)
+{
+ float rectIntersectionArea = (float)(a & b).area();
+ return rectIntersectionArea / (a.area() + b.area() - rectIntersectionArea);
+}
+
+} // namespace
+
+template <typename Tracker, typename ROI_t = Rect2d>
+class TrackerTest
+{
+public:
+ TrackerTest(const Ptr<Tracker>& tracker, const string& video, float distanceThreshold,
+ float overlapThreshold, int shift = NoTransform, int segmentIdx = 1, int numSegments = 10);
+ ~TrackerTest() {}
+ void run();
+
+protected:
+ void checkDataTest();
+
+ void distanceAndOverlapTest();
+
+ Ptr<Tracker> tracker;
+ string video;
+ std::vector<Rect> bbs;
+ int startFrame;
+ string suffix;
+ string prefix;
+ float overlapThreshold;
+ float distanceThreshold;
+ int segmentIdx;
+ int shift;
+ int numSegments;
+
+ int gtStartFrame;
+ int endFrame;
+ vector<int> validSequence;
+
+private:
+ Rect applyShift(const Rect& bb);
+};
+
+template <typename Tracker, typename ROI_t>
+TrackerTest<Tracker, ROI_t>::TrackerTest(const Ptr<Tracker>& _tracker, const string& _video, float _distanceThreshold,
+ float _overlapThreshold, int _shift, int _segmentIdx, int _numSegments)
+ : tracker(_tracker)
+ , video(_video)
+ , overlapThreshold(_overlapThreshold)
+ , distanceThreshold(_distanceThreshold)
+ , segmentIdx(_segmentIdx)
+ , shift(_shift)
+ , numSegments(_numSegments)
+{
+ // nothing
+}
+
+template <typename Tracker, typename ROI_t>
+Rect TrackerTest<Tracker, ROI_t>::applyShift(const Rect& bb_)
+{
+ Rect bb = bb_;
+ Point center(bb.x + (bb.width / 2), bb.y + (bb.height / 2));
+
+ int xLimit = bb.x + bb.width - 1;
+ int yLimit = bb.y + bb.height - 1;
+
+ int h = 0;
+ int w = 0;
+ float ratio = 1.0;
+
+ switch (shift)
+ {
+ case CenterShiftLeft:
+ bb.x = bb.x - (int)ceil(0.1 * bb.width);
+ break;
+ case CenterShiftRight:
+ bb.x = bb.x + (int)ceil(0.1 * bb.width);
+ break;
+ case CenterShiftUp:
+ bb.y = bb.y - (int)ceil(0.1 * bb.height);
+ break;
+ case CenterShiftDown:
+ bb.y = bb.y + (int)ceil(0.1 * bb.height);
+ break;
+ case CornerShiftTopLeft:
+ bb.x = (int)cvRound(bb.x - 0.1 * bb.width);
+ bb.y = (int)cvRound(bb.y - 0.1 * bb.height);
+
+ bb.width = xLimit - bb.x + 1;
+ bb.height = yLimit - bb.y + 1;
+ break;
+ case CornerShiftTopRight:
+ xLimit = (int)cvRound(xLimit + 0.1 * bb.width);
+
+ bb.y = (int)cvRound(bb.y - 0.1 * bb.height);
+ bb.width = xLimit - bb.x + 1;
+ bb.height = yLimit - bb.y + 1;
+ break;
+ case CornerShiftBottomLeft:
+ bb.x = (int)cvRound(bb.x - 0.1 * bb.width);
+ yLimit = (int)cvRound(yLimit + 0.1 * bb.height);
+
+ bb.width = xLimit - bb.x + 1;
+ bb.height = yLimit - bb.y + 1;
+ break;
+ case CornerShiftBottomRight:
+ xLimit = (int)cvRound(xLimit + 0.1 * bb.width);
+ yLimit = (int)cvRound(yLimit + 0.1 * bb.height);
+
+ bb.width = xLimit - bb.x + 1;
+ bb.height = yLimit - bb.y + 1;
+ break;
+ case Scale_0_8:
+ ratio = 0.8f;
+ w = (int)(ratio * bb.width);
+ h = (int)(ratio * bb.height);
+
+ bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
+ break;
+ case Scale_0_9:
+ ratio = 0.9f;
+ w = (int)(ratio * bb.width);
+ h = (int)(ratio * bb.height);
+
+ bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
+ break;
+ case 11:
+ //scale 1.1
+ ratio = 1.1f;
+ w = (int)(ratio * bb.width);
+ h = (int)(ratio * bb.height);
+
+ bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
+ break;
+ case 12:
+ //scale 1.2
+ ratio = 1.2f;
+ w = (int)(ratio * bb.width);
+ h = (int)(ratio * bb.height);
+
+ bb = Rect(center.x - (w / 2), center.y - (h / 2), w, h);
+ break;
+ default:
+ break;
+ }
+
+ return bb;
+}
+
+template <typename Tracker, typename ROI_t>
+void TrackerTest<Tracker, ROI_t>::distanceAndOverlapTest()
+{
+ bool initialized = false;
+
+ int fc = (startFrame - gtStartFrame);
+
+ bbs.at(fc) = applyShift(bbs.at(fc));
+ Rect currentBBi = bbs.at(fc);
+ ROI_t currentBB(currentBBi);
+ float sumDistance = 0;
+ float sumOverlap = 0;
+
+ string folder = cvtest::TS::ptr()->get_data_path() + "/" + TRACKING_DIR + "/" + video + "/" + FOLDER_IMG;
+ string videoPath = folder + "/" + video + ".webm";
+
+ VideoCapture c;
+ c.open(videoPath);
+ if (!c.isOpened())
+ throw SkipTestException("Can't open video file");
+#if 0
+ c.set(CAP_PROP_POS_FRAMES, startFrame);
+#else
+ if (startFrame)
+ std::cout << "startFrame = " << startFrame << std::endl;
+ for (int i = 0; i < startFrame; i++)
+ {
+ Mat dummy_frame;
+ c >> dummy_frame;
+ ASSERT_FALSE(dummy_frame.empty()) << i << ": " << videoPath;
+ }
+#endif
+
+ for (int frameCounter = startFrame; frameCounter < endFrame; frameCounter++)
+ {
+ Mat frame;
+ c >> frame;
+
+ ASSERT_FALSE(frame.empty()) << "frameCounter=" << frameCounter << " video=" << videoPath;
+ if (!initialized)
+ {
+ tracker->init(frame, currentBB);
+ std::cout << "frame size = " << frame.size() << std::endl;
+ initialized = true;
+ }
+ else if (initialized)
+ {
+ if (frameCounter >= (int)bbs.size())
+ break;
+ tracker->update(frame, currentBB);
+ }
+ float curDistance = calcDistance(currentBB, bbs.at(fc));
+ float curOverlap = calcOverlap(currentBB, bbs.at(fc));
+
+#ifdef DEBUG_TEST
+ Mat result;
+ repeat(frame, 1, 2, result);
+ rectangle(result, currentBB, Scalar(0, 255, 0), 1);
+ Rect roi2(frame.cols, 0, frame.cols, frame.rows);
+ rectangle(result(roi2), bbs.at(fc), Scalar(0, 0, 255), 1);
+ imshow("result", result);
+ waitKey(1);
+#endif
+
+ sumDistance += curDistance;
+ sumOverlap += curOverlap;
+ fc++;
+ }
+
+ float meanDistance = sumDistance / (endFrame - startFrame);
+ float meanOverlap = sumOverlap / (endFrame - startFrame);
+
+ EXPECT_LE(meanDistance, distanceThreshold);
+ EXPECT_GE(meanOverlap, overlapThreshold);
+}
+
+template <typename Tracker, typename ROI_t>
+void TrackerTest<Tracker, ROI_t>::checkDataTest()
+{
+
+ FileStorage fs;
+ fs.open(cvtest::TS::ptr()->get_data_path() + TRACKING_DIR + "/" + video + "/" + video + ".yml", FileStorage::READ);
+ fs["start"] >> startFrame;
+ fs["prefix"] >> prefix;
+ fs["suffix"] >> suffix;
+ fs.release();
+
+ string gtFile = cvtest::TS::ptr()->get_data_path() + TRACKING_DIR + "/" + video + "/gt.txt";
+ std::ifstream gt;
+ //open the ground truth
+ gt.open(gtFile.c_str());
+ ASSERT_TRUE(gt.is_open()) << gtFile;
+ string line;
+ int bbCounter = 0;
+ while (getline(gt, line))
+ {
+ bbCounter++;
+ }
+ gt.close();
+
+ int seqLength = bbCounter;
+ for (int i = startFrame; i < seqLength; i++)
+ {
+ validSequence.push_back(i);
+ }
+
+ //exclude from the images sequence, the frames where the target is occluded or out of view
+ string omitFile = cvtest::TS::ptr()->get_data_path() + TRACKING_DIR + "/" + video + "/" + FOLDER_OMIT_INIT + "/" + video + ".txt";
+ std::ifstream omit;
+ omit.open(omitFile.c_str());
+ if (omit.is_open())
+ {
+ string omitLine;
+ while (getline(omit, omitLine))
+ {
+ vector<string> tokens = splitString(omitLine, " ");
+ int s_start = atoi(tokens.at(0).c_str());
+ int s_end = atoi(tokens.at(1).c_str());
+ for (int k = s_start; k <= s_end; k++)
+ {
+ std::vector<int>::iterator position = std::find(validSequence.begin(), validSequence.end(), k);
+ if (position != validSequence.end())
+ validSequence.erase(position);
+ }
+ }
+ }
+ omit.close();
+ gtStartFrame = startFrame;
+ //compute the start and the and for each segment
+ int numFrame = (int)(validSequence.size() / numSegments);
+ startFrame += (segmentIdx - 1) * numFrame;
+ endFrame = startFrame + numFrame;
+
+ std::ifstream gt2;
+ //open the ground truth
+ gt2.open(gtFile.c_str());
+ ASSERT_TRUE(gt2.is_open()) << gtFile;
+ string line2;
+ int bbCounter2 = 0;
+ while (getline(gt2, line2))
+ {
+ vector<string> tokens = splitString(line2, ",");
+ Rect bb(atoi(tokens.at(0).c_str()), atoi(tokens.at(1).c_str()), atoi(tokens.at(2).c_str()), atoi(tokens.at(3).c_str()));
+ ASSERT_EQ((size_t)4, tokens.size()) << "Incorrect ground truth file " << gtFile;
+
+ bbs.push_back(bb);
+ bbCounter2++;
+ }
+ gt2.close();
+
+ if (segmentIdx == numSegments)
+ endFrame = (int)bbs.size();
+}
+
+template <typename Tracker, typename ROI_t>
+void TrackerTest<Tracker, ROI_t>::run()
+{
+ srand(1); // FIXIT remove that, ensure that there is no "rand()" in implementation
+
+ ASSERT_TRUE(tracker);
+
+ checkDataTest();
+
+ //check for failure
+ if (::testing::Test::HasFatalFailure())
+ return;
+
+ distanceAndOverlapTest();
+}