track.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. #include "track.h"
  2. //#include "dat/dat_tracker.hpp"
  3. ///
  4. /// \brief CTrack
  5. /// \param pt
  6. /// \param region
  7. /// \param deltaTime
  8. /// \param accelNoiseMag
  9. /// \param trackID
  10. /// \param filterObjectSize
  11. /// \param externalTrackerForLost
  12. ///
  13. CTrack::CTrack(
  14. const CRegion& region,
  15. tracking::KalmanType kalmanType,
  16. track_t deltaTime,
  17. track_t accelNoiseMag,
  18. bool useAcceleration,
  19. size_t trackID,
  20. size_t regionID,
  21. bool filterObjectSize,
  22. tracking::LostTrackType externalTrackerForLost
  23. )
  24. :
  25. m_trackID(trackID),
  26. m_regionID(regionID),
  27. m_skippedFrames(0),
  28. m_lastRegion(region),
  29. m_predictionPoint(region.m_rrect.center),
  30. m_predictionRect(region.m_rrect),
  31. m_kalman(kalmanType, useAcceleration, deltaTime, accelNoiseMag),
  32. m_filterObjectSize(filterObjectSize),
  33. m_outOfTheFrame(false),
  34. m_externalTrackerForLost(externalTrackerForLost)
  35. {
  36. if (filterObjectSize)
  37. m_kalman.Update(region.m_brect, true);
  38. else
  39. m_kalman.Update(m_predictionPoint, true);
  40. m_trace.push_back(m_predictionPoint, m_predictionPoint);
  41. }
  42. ///
  43. /// \brief CTrack::CalcDistCenter
  44. /// \param reg
  45. /// \return
  46. ///
  47. track_t CTrack::CalcDistCenter(const CRegion& reg) const
  48. {
  49. Point_t diff = m_predictionPoint - reg.m_rrect.center;
  50. return sqrtf(sqr(diff.x) + sqr(diff.y));
  51. }
  52. ///
  53. /// \brief CTrack::CalcDistRect
  54. /// \param reg
  55. /// \return
  56. ///
  57. track_t CTrack::CalcDistRect(const CRegion& reg) const
  58. {
  59. std::array<track_t, 5> diff;
  60. diff[0] = reg.m_rrect.center.x - m_lastRegion.m_rrect.center.x;
  61. diff[1] = reg.m_rrect.center.y - m_lastRegion.m_rrect.center.y;
  62. diff[2] = static_cast<track_t>(m_lastRegion.m_rrect.size.width - reg.m_rrect.size.width);
  63. diff[3] = static_cast<track_t>(m_lastRegion.m_rrect.size.height - reg.m_rrect.size.height);
  64. diff[4] = static_cast<track_t>(m_lastRegion.m_rrect.angle - reg.m_rrect.angle);
  65. track_t dist = 0;
  66. for (size_t i = 0; i < diff.size(); ++i)
  67. {
  68. dist += sqr(diff[i]);
  69. }
  70. return sqrtf(dist);
  71. }
  72. ///
  73. /// \brief CTrack::CalcDistJaccard
  74. /// \param reg
  75. /// \return
  76. ///
  77. track_t CTrack::CalcDistJaccard(const CRegion& reg) const
  78. {
  79. track_t intArea = static_cast<track_t>((reg.m_brect & m_lastRegion.m_brect).area());
  80. track_t unionArea = static_cast<track_t>(reg.m_brect.area() + m_lastRegion.m_brect.area() - intArea);
  81. return 1 - intArea / unionArea;
  82. }
  83. ///
  84. /// \brief CTrack::CalcDistHist
  85. /// \param reg
  86. /// \return
  87. ///
  88. track_t CTrack::CalcDistHist(const CRegion& reg, cv::UMat currFrame) const
  89. {
  90. track_t res = 1;
  91. if (reg.m_hist.empty())
  92. {
  93. int bins = 64;
  94. std::vector<int> histSize;
  95. std::vector<float> ranges;
  96. std::vector<int> channels;
  97. for (int i = 0, stop = currFrame.channels(); i < stop; ++i)
  98. {
  99. histSize.push_back(bins);
  100. ranges.push_back(0);
  101. ranges.push_back(255);
  102. channels.push_back(i);
  103. }
  104. std::vector<cv::UMat> regROI = { currFrame(reg.m_brect) };
  105. cv::calcHist(regROI, channels, cv::Mat(), reg.m_hist, histSize, ranges, false);
  106. cv::normalize(reg.m_hist, reg.m_hist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
  107. }
  108. if (!reg.m_hist.empty() && !m_lastRegion.m_hist.empty())
  109. {
  110. #if (((CV_VERSION_MAJOR == 4) && (CV_VERSION_MINOR < 1)) || (CV_VERSION_MAJOR == 3))
  111. res = static_cast<track_t>(cv::compareHist(reg.m_hist, m_lastRegion.m_hist, CV_COMP_BHATTACHARYYA));
  112. //res = 1.f - static_cast<track_t>(cv::compareHist(reg.m_hist, m_lastRegion.m_hist, CV_COMP_CORREL));
  113. #else
  114. res = static_cast<track_t>(cv::compareHist(reg.m_hist, m_lastRegion.m_hist, cv::HISTCMP_BHATTACHARYYA));
  115. #endif
  116. }
  117. return res;
  118. }
  119. ///
  120. /// \brief CTrack::Update
  121. /// \*param region
  122. /// \param dataCorrect
  123. /// \param max_trace_length
  124. /// \param prevFrame
  125. /// \param currFrame
  126. /// \param trajLen
  127. ///
  128. void CTrack::Update(
  129. const CRegion& region,
  130. bool dataCorrect,
  131. size_t max_trace_length,
  132. cv::UMat prevFrame,
  133. cv::UMat currFrame,
  134. int trajLen
  135. )
  136. {
  137. if (m_filterObjectSize) // Kalman filter for object coordinates and size
  138. RectUpdate(region, dataCorrect, prevFrame, currFrame);
  139. else // Kalman filter only for object center
  140. PointUpdate(region.m_rrect.center, region.m_rrect.size, dataCorrect, currFrame.size());
  141. if (dataCorrect)
  142. {
  143. //std::cout << m_lastRegion.m_brect << " - " << region.m_brect << std::endl;
  144. m_lastRegion = region;
  145. m_trace.push_back(m_predictionPoint, region.m_rrect.center);
  146. CheckStatic(trajLen, currFrame, region);
  147. }
  148. else
  149. {
  150. m_trace.push_back(m_predictionPoint);
  151. }
  152. if (m_trace.size() > max_trace_length)
  153. m_trace.pop_front(m_trace.size() - max_trace_length);
  154. }
  155. ///
  156. /// \brief CTrack::IsStatic
  157. /// \return
  158. ///
  159. bool CTrack::IsStatic() const
  160. {
  161. return m_isStatic;
  162. }
  163. ///
  164. /// \brief CTrack::IsStaticTimeout
  165. /// \param framesTime
  166. /// \return
  167. ///
  168. bool CTrack::IsStaticTimeout(int framesTime) const
  169. {
  170. return (m_staticFrames > framesTime);
  171. }
  172. ///
  173. /// \brief CTrack::IsOutOfTheFrame
  174. /// \return
  175. ///
  176. bool CTrack::IsOutOfTheFrame() const
  177. {
  178. return m_outOfTheFrame;
  179. }
  180. ///
  181. cv::RotatedRect CTrack::CalcPredictionEllipse(cv::Size_<track_t> minRadius) const
  182. {
  183. // Move ellipse to velocity
  184. auto velocity = m_kalman.GetVelocity();
  185. Point_t d(3.f * velocity[0], 3.f * velocity[1]);
  186. cv::RotatedRect rrect(m_predictionPoint, cv::Size2f(std::max(minRadius.width, float(fabs(d.x))), std::max(minRadius.height, float(fabs(d.y)))), 0);
  187. if (fabs(d.x) + fabs(d.y) > 4) // pix
  188. {
  189. if (fabs(d.x) > 0.0001f)
  190. {
  191. track_t l = std::min(rrect.size.width, rrect.size.height) / 3;
  192. track_t p2_l = sqrtf(sqr(d.x) + sqr(d.y));
  193. rrect.center.x = l * d.x / p2_l + m_predictionPoint.x;
  194. rrect.center.y = l * d.y / p2_l + m_predictionPoint.y;
  195. rrect.angle = atanf(d.y / d.x);
  196. }
  197. else
  198. {
  199. rrect.center.y += d.y / 3;
  200. rrect.angle = static_cast<float>(CV_PI / 2.);
  201. }
  202. }
  203. return rrect;
  204. }
  205. ///
  206. /// \brief CTrack::IsInsideArea
  207. /// If result <= 1 then center of the object is inside ellipse with prediction and velocity
  208. /// \param pt
  209. /// \return
  210. ///
  211. track_t CTrack::IsInsideArea(const Point_t& pt, const cv::RotatedRect& rrect) const
  212. {
  213. Point_t pt_(pt.x - rrect.center.x, pt.y - rrect.center.y);
  214. track_t r = sqrtf(sqr(pt_.x) + sqr(pt_.y));
  215. track_t t = (r > 1) ? acosf(pt_.x / r) : 0;
  216. track_t t_ = t - rrect.angle;
  217. Point_t pt_rotated(r * cosf(t_), r * sinf(t_));
  218. return sqr(pt_rotated.x) / sqr(rrect.size.width) + sqr(pt_rotated.y) / sqr(rrect.size.height);
  219. }
  220. ///
  221. /// \brief CTrack::WidthDist
  222. /// \param reg
  223. /// \return
  224. ///
  225. track_t CTrack::WidthDist(const CRegion& reg) const
  226. {
  227. if (m_lastRegion.m_rrect.size.width < reg.m_rrect.size.width)
  228. return m_lastRegion.m_rrect.size.width / reg.m_rrect.size.width;
  229. else
  230. return reg.m_rrect.size.width / m_lastRegion.m_rrect.size.width;
  231. }
  232. ///
  233. /// \brief CTrack::HeightDist
  234. /// \param reg
  235. /// \return
  236. ///
  237. track_t CTrack::HeightDist(const CRegion& reg) const
  238. {
  239. if (m_lastRegion.m_rrect.size.height < reg.m_rrect.size.height)
  240. return m_lastRegion.m_rrect.size.height / reg.m_rrect.size.height;
  241. else
  242. return reg.m_rrect.size.height / m_lastRegion.m_rrect.size.height;
  243. }
  244. ///
  245. /// \brief CTrack::CheckStatic
  246. /// \param trajLen
  247. /// \return
  248. ///
  249. bool CTrack::CheckStatic(int trajLen, cv::UMat currFrame, const CRegion& region)
  250. {
  251. if (!trajLen || static_cast<int>(m_trace.size()) < trajLen)
  252. {
  253. m_isStatic = false;
  254. m_staticFrames = 0;
  255. m_staticFrame = cv::UMat();
  256. }
  257. else
  258. {
  259. track_t kx = 0;
  260. track_t bx = 0;
  261. track_t ky = 0;
  262. track_t by = 0;
  263. get_lin_regress_params(m_trace, m_trace.size() - trajLen, m_trace.size(), kx, bx, ky, by);
  264. track_t speed = sqrt(sqr(kx * trajLen) + sqr(ky * trajLen));
  265. const track_t speedThresh = 10;
  266. if (speed < speedThresh)
  267. {
  268. if (!m_isStatic)
  269. {
  270. m_staticFrame = currFrame.clone();
  271. m_staticRect = region.m_brect;
  272. #if 0
  273. #ifndef SILENT_WORK
  274. cv::namedWindow("m_staticFrame", cv::WINDOW_NORMAL);
  275. cv::Mat img = m_staticFrame.getMat(cv::ACCESS_READ).clone();
  276. cv::rectangle(img, m_staticRect, cv::Scalar(255, 0, 255), 1);
  277. for (size_t i = m_trace.size() - trajLen; i < m_trace.size() - 1; ++i)
  278. {
  279. cv::line(img, m_trace[i], m_trace[i + 1], cv::Scalar(0, 0, 0), 1, cv::LINE_8);
  280. }
  281. std::string label = "(" + std::to_string(kx) + ", " + std::to_string(ky) + ") = " + std::to_string(speed);
  282. cv::line(img,
  283. cv::Point(cvRound(bx), cvRound(by)),
  284. cv::Point(cvRound(kx * trajLen + bx), cvRound(ky * trajLen + by)),
  285. cv::Scalar(0, 0, 0), 1, cv::LINE_8);
  286. cv::putText(img, label, m_staticRect.tl(), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
  287. cv::imshow("m_staticFrame", img);
  288. std::cout << "m_staticRect = " << m_staticRect << std::endl;
  289. cv::waitKey(1);
  290. #endif
  291. #endif
  292. }
  293. ++m_staticFrames;
  294. m_isStatic = true;
  295. }
  296. else
  297. {
  298. m_isStatic = false;
  299. m_staticFrames = 0;
  300. m_staticFrame = cv::UMat();
  301. }
  302. }
  303. return m_isStatic;
  304. }
  305. ///
  306. /// \brief GetLastRect
  307. /// \return
  308. ///
  309. cv::RotatedRect CTrack::GetLastRect() const
  310. {
  311. if (m_filterObjectSize)
  312. {
  313. return m_predictionRect;
  314. }
  315. else
  316. {
  317. return cv::RotatedRect(cv::Point2f(m_predictionPoint.x, m_predictionPoint.y), m_predictionRect.size, m_predictionRect.angle);
  318. }
  319. }
  320. ///
  321. /// \brief CTrack::LastRegion
  322. /// \return
  323. ///
  324. const CRegion& CTrack::LastRegion() const
  325. {
  326. return m_lastRegion;
  327. }
  328. ///
  329. /// \brief CTrack::ConstructObject
  330. /// \return
  331. ///
  332. TrackingObject CTrack::ConstructObject() const
  333. {
  334. return TrackingObject(GetLastRect(), m_trackID, m_regionID, m_trace, IsStatic(), IsOutOfTheFrame(),
  335. m_lastRegion.m_type, m_lastRegion.m_confidence, m_kalman.GetVelocity());
  336. }
  337. ///
  338. /// \brief CTrack::SkippedFrames
  339. /// \return
  340. ///
  341. size_t CTrack::SkippedFrames() const
  342. {
  343. return m_skippedFrames;
  344. }
  345. ///
  346. /// \brief CTrack::SkippedFrames
  347. /// \return
  348. ///
  349. size_t& CTrack::SkippedFrames()
  350. {
  351. return m_skippedFrames;
  352. }
  353. ///
  354. /// \brief RectUpdate
  355. /// \param region
  356. /// \param dataCorrect
  357. /// \param prevFrame
  358. /// \param currFrame
  359. ///
  360. void CTrack::RectUpdate(
  361. const CRegion& region,
  362. bool dataCorrect,
  363. cv::UMat prevFrame,
  364. cv::UMat currFrame
  365. )
  366. {
  367. m_kalman.GetRectPrediction();
  368. bool recalcPrediction = true;
  369. auto Clamp = [](int& v, int& size, int hi) -> int
  370. {
  371. int res = 0;
  372. if (size < 1)
  373. size = 0;
  374. if (v < 0)
  375. {
  376. res = v;
  377. v = 0;
  378. return res;
  379. }
  380. else if (v + size > hi - 1)
  381. {
  382. res = v;
  383. v = hi - 1 - size;
  384. if (v < 0)
  385. {
  386. size += v;
  387. v = 0;
  388. }
  389. res -= v;
  390. return res;
  391. }
  392. return res;
  393. };
  394. auto UpdateRRect = [&](cv::Rect prevRect, cv::Rect newRect)
  395. {
  396. m_predictionRect.center.x += newRect.x - prevRect.x;
  397. m_predictionRect.center.y += newRect.y - prevRect.y;
  398. m_predictionRect.size.width *= newRect.width / static_cast<float>(prevRect.width);
  399. m_predictionRect.size.height *= newRect.height / static_cast<float>(prevRect.height);
  400. };
  401. switch (m_externalTrackerForLost)
  402. {
  403. case tracking::TrackNone:
  404. break;
  405. case tracking::TrackKCF:
  406. case tracking::TrackMIL:
  407. case tracking::TrackMedianFlow:
  408. case tracking::TrackGOTURN:
  409. case tracking::TrackMOSSE:
  410. case tracking::TrackCSRT:
  411. #ifdef USE_OCV_KCF
  412. if (!dataCorrect)
  413. {
  414. cv::Rect brect = m_predictionRect.boundingRect();
  415. cv::Size roiSize(std::max(2 * brect.width, currFrame.cols / 4), std::max(2 * brect.height, currFrame.rows / 4));
  416. if (roiSize.width > currFrame.cols)
  417. roiSize.width = currFrame.cols;
  418. if (roiSize.height > currFrame.rows)
  419. roiSize.height = currFrame.rows;
  420. cv::Point roiTL(brect.x + brect.width / 2 - roiSize.width / 2, brect.y + brect.height / 2 - roiSize.height / 2);
  421. cv::Rect roiRect(roiTL, roiSize);
  422. Clamp(roiRect.x, roiRect.width, currFrame.cols);
  423. Clamp(roiRect.y, roiRect.height, currFrame.rows);
  424. bool inited = false;
  425. if (!m_tracker || m_tracker.empty())
  426. {
  427. CreateExternalTracker(currFrame.channels());
  428. cv::Rect2d lastRect(brect.x - roiRect.x, brect.y - roiRect.y, brect.width, brect.height);
  429. if (m_staticFrame.empty())
  430. {
  431. int dx = 1;//m_predictionRect.width / 8;
  432. int dy = 1;//m_predictionRect.height / 8;
  433. lastRect = cv::Rect2d(brect.x - roiRect.x - dx, brect.y - roiRect.y - dy, brect.width + 2 * dx, brect.height + 2 * dy);
  434. }
  435. else
  436. {
  437. lastRect = cv::Rect2d(m_staticRect.x - roiRect.x, m_staticRect.y - roiRect.y, m_staticRect.width, m_staticRect.height);
  438. }
  439. if (lastRect.x >= 0 &&
  440. lastRect.y >= 0 &&
  441. lastRect.x + lastRect.width < roiRect.width &&
  442. lastRect.y + lastRect.height < roiRect.height &&
  443. lastRect.area() > 0)
  444. {
  445. if (m_staticFrame.empty())
  446. m_tracker->init(cv::UMat(prevFrame, roiRect), lastRect);
  447. else
  448. m_tracker->init(cv::UMat(m_staticFrame, roiRect), lastRect);
  449. #if 0
  450. #ifndef SILENT_WORK
  451. cv::Mat tmp = cv::UMat(prevFrame, roiRect).getMat(cv::ACCESS_READ).clone();
  452. cv::rectangle(tmp, lastRect, cv::Scalar(255, 255, 255), 2);
  453. cv::imshow("init", tmp);
  454. #endif
  455. #endif
  456. inited = true;
  457. m_outOfTheFrame = false;
  458. }
  459. else
  460. {
  461. m_tracker.release();
  462. m_outOfTheFrame = true;
  463. }
  464. }
  465. cv::Rect2d newRect;
  466. if (!inited && !m_tracker.empty() && m_tracker->update(cv::UMat(currFrame, roiRect), newRect))
  467. {
  468. #if 0
  469. #ifndef SILENT_WORK
  470. cv::Mat tmp2 = cv::UMat(currFrame, roiRect).getMat(cv::ACCESS_READ).clone();
  471. cv::rectangle(tmp2, newRect, cv::Scalar(255, 255, 255), 2);
  472. cv::imshow("track", tmp2);
  473. #endif
  474. #endif
  475. cv::Rect prect(cvRound(newRect.x) + roiRect.x, cvRound(newRect.y) + roiRect.y, cvRound(newRect.width), cvRound(newRect.height));
  476. UpdateRRect(brect, m_kalman.Update(prect, true));
  477. recalcPrediction = false;
  478. }
  479. }
  480. else
  481. {
  482. if (m_tracker && !m_tracker.empty())
  483. m_tracker.release();
  484. }
  485. #else
  486. std::cerr << "KCF tracker was disabled in CMAKE! Set lostTrackType = TrackNone in constructor." << std::endl;
  487. #endif
  488. break;
  489. // case tracking::TrackDAT:
  490. // case tracking::TrackSTAPLE:
  491. // case tracking::TrackLDES:
  492. // if (!dataCorrect)
  493. // {
  494. // bool inited = false;
  495. // cv::Rect brect = m_predictionRect.boundingRect();
  496. // if (!m_VOTTracker)
  497. // {
  498. // CreateExternalTracker(currFrame.channels());
  499. // cv::Rect2d lastRect(brect.x, brect.y, brect.width, brect.height);
  500. // if (!m_staticFrame.empty())
  501. // lastRect = cv::Rect2d(m_staticRect.x, m_staticRect.y, m_staticRect.width, m_staticRect.height);
  502. // if (lastRect.x >= 0 &&
  503. // lastRect.y >= 0 &&
  504. // lastRect.x + lastRect.width < prevFrame.cols &&
  505. // lastRect.y + lastRect.height < prevFrame.rows &&
  506. // lastRect.area() > 0)
  507. // {
  508. // if (m_staticFrame.empty())
  509. // {
  510. // cv::Mat mat = prevFrame.getMat(cv::ACCESS_READ);
  511. // m_VOTTracker->Initialize(mat, lastRect);
  512. // m_VOTTracker->Train(mat, true);
  513. // }
  514. // else
  515. // {
  516. // cv::Mat mat = m_staticFrame.getMat(cv::ACCESS_READ);
  517. // m_VOTTracker->Initialize(mat, lastRect);
  518. // m_VOTTracker->Train(mat, true);
  519. // }
  520. // inited = true;
  521. // m_outOfTheFrame = false;
  522. // }
  523. // else
  524. // {
  525. // m_VOTTracker = nullptr;
  526. // m_outOfTheFrame = true;
  527. // }
  528. // }
  529. // if (!inited && m_VOTTracker)
  530. // {
  531. // constexpr float confThresh = 0.3f;
  532. // cv::Mat mat = currFrame.getMat(cv::ACCESS_READ);
  533. // float confidence = 0;
  534. // cv::RotatedRect newRect = m_VOTTracker->Update(mat, confidence);
  535. // if (confidence > confThresh)
  536. // {
  537. // m_VOTTracker->Train(mat, false);
  538. // if (newRect.angle > 0.5f)
  539. // {
  540. // m_predictionRect = newRect;
  541. // m_kalman.Update(newRect.boundingRect(), true);
  542. // }
  543. // else
  544. // {
  545. // UpdateRRect(brect, m_kalman.Update(newRect.boundingRect(), true));
  546. // }
  547. // recalcPrediction = false;
  548. // }
  549. // }
  550. // }
  551. // else
  552. // {
  553. // if (m_VOTTracker)
  554. // m_VOTTracker = nullptr;
  555. // }
  556. // break;
  557. }
  558. if (recalcPrediction)
  559. UpdateRRect(m_predictionRect.boundingRect(), m_kalman.Update(region.m_brect, dataCorrect));
  560. cv::Rect brect = m_predictionRect.boundingRect();
  561. int dx = Clamp(brect.x, brect.width, currFrame.cols);
  562. int dy = Clamp(brect.y, brect.height, currFrame.rows);
  563. #if 0
  564. m_predictionRect.center.x += dx;
  565. m_predictionRect.center.y += dy;
  566. #endif
  567. m_outOfTheFrame = (dx != 0) || (dy != 0) || (brect.width < 2) || (brect.height < 2);
  568. m_predictionPoint = m_predictionRect.center;
  569. //std::cout << "brect = " << brect << ", dx = " << dx << ", dy = " << dy << ", outOfTheFrame = " << m_outOfTheFrame << ", predictionPoint = " << m_predictionPoint << std::endl;
  570. }
  571. ///
  572. /// \brief CreateExternalTracker
  573. ///
  574. void CTrack::CreateExternalTracker(int channels)
  575. {
  576. switch (m_externalTrackerForLost)
  577. {
  578. case tracking::TrackNone:
  579. if (m_VOTTracker)
  580. m_VOTTracker = nullptr;
  581. #ifdef USE_OCV_KCF
  582. if (m_tracker && !m_tracker.empty())
  583. m_tracker.release();
  584. #endif
  585. break;
  586. case tracking::TrackKCF:
  587. #ifdef USE_OCV_KCF
  588. if (!m_tracker || m_tracker.empty())
  589. {
  590. cv::TrackerKCF::Params params;
  591. if (channels == 1)
  592. {
  593. params.compressed_size = 1;
  594. params.desc_pca = cv::TrackerKCF::GRAY;
  595. params.desc_npca = cv::TrackerKCF::GRAY;
  596. }
  597. else
  598. {
  599. params.compressed_size = 3;
  600. params.desc_pca = cv::TrackerKCF::CN;
  601. params.desc_npca = cv::TrackerKCF::CN;
  602. }
  603. params.resize = true;
  604. params.detect_thresh = 0.7f;
  605. #if (((CV_VERSION_MAJOR == 3) && (CV_VERSION_MINOR >= 3)) || (CV_VERSION_MAJOR > 3))
  606. m_tracker = cv::TrackerKCF::create(params);
  607. #else
  608. m_tracker = cv::TrackerKCF::createTracker(params);
  609. #endif
  610. }
  611. #endif
  612. if (m_VOTTracker)
  613. m_VOTTracker = nullptr;
  614. break;
  615. case tracking::TrackMIL:
  616. #ifdef USE_OCV_KCF
  617. if (!m_tracker || m_tracker.empty())
  618. {
  619. cv::TrackerMIL::Params params;
  620. #if (((CV_VERSION_MAJOR == 3) && (CV_VERSION_MINOR >= 3)) || (CV_VERSION_MAJOR > 3))
  621. m_tracker = cv::TrackerMIL::create(params);
  622. #else
  623. m_tracker = cv::TrackerMIL::createTracker(params);
  624. #endif
  625. }
  626. #endif
  627. if (m_VOTTracker)
  628. m_VOTTracker = nullptr;
  629. break;
  630. case tracking::TrackMedianFlow:
  631. #ifdef USE_OCV_KCF
  632. if (!m_tracker || m_tracker.empty())
  633. {
  634. cv::TrackerMedianFlow::Params params;
  635. #if (((CV_VERSION_MAJOR == 3) && (CV_VERSION_MINOR >= 3)) || (CV_VERSION_MAJOR > 3))
  636. m_tracker = cv::TrackerMedianFlow::create(params);
  637. #else
  638. m_tracker = cv::TrackerMedianFlow::createTracker(params);
  639. #endif
  640. }
  641. #endif
  642. if (m_VOTTracker)
  643. m_VOTTracker = nullptr;
  644. break;
  645. case tracking::TrackGOTURN:
  646. #ifdef USE_OCV_KCF
  647. if (!m_tracker || m_tracker.empty())
  648. {
  649. cv::TrackerGOTURN::Params params;
  650. #if (((CV_VERSION_MAJOR == 3) && (CV_VERSION_MINOR >= 3)) || (CV_VERSION_MAJOR > 3))
  651. m_tracker = cv::TrackerGOTURN::create(params);
  652. #else
  653. m_tracker = cv::TrackerGOTURN::createTracker(params);
  654. #endif
  655. }
  656. #endif
  657. if (m_VOTTracker)
  658. m_VOTTracker = nullptr;
  659. break;
  660. case tracking::TrackMOSSE:
  661. #ifdef USE_OCV_KCF
  662. if (!m_tracker || m_tracker.empty())
  663. {
  664. #if (((CV_VERSION_MAJOR == 3) && (CV_VERSION_MINOR > 3)) || (CV_VERSION_MAJOR > 3))
  665. m_tracker = cv::TrackerMOSSE::create();
  666. #else
  667. m_tracker = cv::TrackerMOSSE::createTracker();
  668. #endif
  669. }
  670. #endif
  671. if (m_VOTTracker)
  672. m_VOTTracker = nullptr;
  673. break;
  674. case tracking::TrackCSRT:
  675. #ifdef USE_OCV_KCF
  676. if (!m_tracker || m_tracker.empty())
  677. {
  678. #if (CV_VERSION_MAJOR >= 4)
  679. cv::TrackerCSRT::Params params;
  680. params.psr_threshold = 0.04f; // 0.035f;
  681. if (channels == 1)
  682. {
  683. params.use_gray = true;
  684. params.use_rgb = false;
  685. }
  686. else
  687. {
  688. params.use_gray = false;
  689. params.use_rgb = true;
  690. }
  691. m_tracker = cv::TrackerCSRT::create(params);
  692. #endif
  693. }
  694. #endif
  695. if (m_VOTTracker)
  696. m_VOTTracker = nullptr;
  697. break;
  698. // case tracking::TrackDAT:
  699. //#ifdef USE_OCV_KCF
  700. // if (m_tracker && !m_tracker.empty())
  701. // m_tracker.release();
  702. //#endif
  703. // if (!m_VOTTracker)
  704. // m_VOTTracker = std::unique_ptr<DAT_TRACKER>(new DAT_TRACKER());
  705. // break;
  706. // case tracking::TrackSTAPLE:
  707. //#ifdef USE_OCV_KCF
  708. // if (m_tracker && !m_tracker.empty())
  709. // m_tracker.release();
  710. //#endif
  711. //#ifdef USE_STAPLE_TRACKER
  712. // if (!m_VOTTracker)
  713. // m_VOTTracker = std::unique_ptr<STAPLE_TRACKER>(new STAPLE_TRACKER());
  714. //#else
  715. // std::cerr << "Project was compiled without STAPLE tracking!" << std::endl;
  716. //#endif
  717. // break;
  718. //#if 1
  719. // case tracking::TrackLDES:
  720. //#ifdef USE_OCV_KCF
  721. // if (m_tracker && !m_tracker.empty())
  722. // m_tracker.release();
  723. //#endif
  724. //#ifdef USE_STAPLE_TRACKER
  725. // if (!m_VOTTracker)
  726. // m_VOTTracker = std::unique_ptr<LDESTracker>(new LDESTracker());
  727. //#else
  728. // std::cerr << "Project was compiled without STAPLE tracking!" << std::endl;
  729. //#endif
  730. // break;
  731. //#endif
  732. }
  733. }
  734. ///
  735. /// \brief PointUpdate
  736. /// \param pt
  737. /// \param dataCorrect
  738. ///
  739. void CTrack::PointUpdate(
  740. const Point_t& pt,
  741. const cv::Size& newObjSize,
  742. bool dataCorrect,
  743. const cv::Size& frameSize
  744. )
  745. {
  746. m_kalman.GetPointPrediction();
  747. m_predictionPoint = m_kalman.Update(pt, dataCorrect);
  748. if (dataCorrect)
  749. {
  750. const int a1 = 1;
  751. const int a2 = 9;
  752. m_predictionRect.size.width = (a1 * newObjSize.width + a2 * m_predictionRect.size.width) / (a1 + a2);
  753. m_predictionRect.size.height = (a1 * newObjSize.height + a2 * m_predictionRect.size.height) / (a1 + a2);
  754. }
  755. auto Clamp = [](track_t& v, int hi) -> bool
  756. {
  757. if (v < 0)
  758. {
  759. v = 0;
  760. return true;
  761. }
  762. else if (hi && v > hi - 1)
  763. {
  764. v = static_cast<track_t>(hi - 1);
  765. return true;
  766. }
  767. return false;
  768. };
  769. auto p = m_predictionPoint;
  770. m_outOfTheFrame = Clamp(p.x, frameSize.width) || Clamp(p.y, frameSize.height) || (m_predictionRect.size.width < 2) || (m_predictionRect.size.height < 2);
  771. //std::cout << "predictionRect = " << m_predictionRect.boundingRect() << ", outOfTheFrame = " << m_outOfTheFrame << ", predictionPoint = " << m_predictionPoint << std::endl;
  772. }