Ctracker.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include "Ctracker.h"
  2. ///
  3. /// \brief CTracker::CTracker
  4. /// Tracker. Manage tracks. Create, remove, update.
  5. /// \param settings
  6. ///
  7. CTracker::CTracker(TrackerSettings& settings)
  8. {
  9. m_settings = settings;
  10. }
  11. ///
  12. /// \brief CTracker::CTracker
  13. /// Tracker. Manage tracks. Create, remove, update.
  14. /// \param settings
  15. ///
  16. CTracker::CTracker(const TrackerSettings& settings)
  17. :
  18. m_settings(settings),
  19. m_nextTrackID(0)
  20. {
  21. ShortPathCalculator* spcalc = nullptr;
  22. SPSettings spSettings = { settings.m_distThres, 12 };
  23. switch (m_settings.m_matchType)
  24. {
  25. case tracking::MatchHungrian:
  26. spcalc = new SPHungrian(spSettings);
  27. break;
  28. // case tracking::MatchBipart:
  29. // spcalc = new SPBipart(spSettings);
  30. // break;
  31. }
  32. assert(spcalc != nullptr);
  33. m_SPCalculator = std::unique_ptr<ShortPathCalculator>(spcalc);
  34. }
  35. ///
  36. /// \brief CTracker::~CTracker
  37. ///
  38. CTracker::~CTracker(void)
  39. {
  40. }
  41. ///
  42. /// \brief CTracker::setSettings
  43. /// Tracker. Manage tracks. Create, remove, update.
  44. /// \param settings
  45. ///
  46. void CTracker::setSettings(TrackerSettings& settings)
  47. {
  48. m_settings = settings;
  49. m_nextTrackID = 0;
  50. ShortPathCalculator* spcalc = nullptr;
  51. SPSettings spSettings = { settings.m_distThres, 12 };
  52. switch (m_settings.m_matchType)
  53. {
  54. case tracking::MatchHungrian:
  55. spcalc = new SPHungrian(spSettings);
  56. break;
  57. // case tracking::MatchBipart:
  58. // spcalc = new SPBipart(spSettings);
  59. // break;
  60. }
  61. assert(spcalc != nullptr);
  62. m_SPCalculator = std::unique_ptr<ShortPathCalculator>(spcalc);
  63. }
  64. ///
  65. /// \brief CTracker::Update
  66. /// \param regions
  67. /// \param currFrame
  68. /// \param fps
  69. ///
  70. void CTracker::Update(
  71. const regions_t& regions,
  72. cv::UMat currFrame,
  73. float fps
  74. )
  75. {
  76. UpdateTrackingState(regions, currFrame, fps);
  77. currFrame.copyTo(m_prevFrame);
  78. }
  79. ///
  80. /// \brief CTracker::UpdateTrackingState
  81. /// \param regions
  82. /// \param currFrame
  83. /// \param fps
  84. ///
  85. void CTracker::UpdateTrackingState(
  86. const regions_t& regions,
  87. cv::UMat currFrame,
  88. float fps
  89. )
  90. {
  91. const size_t N = m_tracks.size(); // Tracking objects
  92. const size_t M = regions.size(); // Detections or regions
  93. assignments_t assignment(N, -1); // Assignments regions -> tracks
  94. if (!m_tracks.empty())
  95. {
  96. // Distance matrix between all tracks to all regions
  97. distMatrix_t costMatrix(N * M);
  98. const track_t maxPossibleCost = 1e3;//static_cast<track_t>(currFrame.cols * currFrame.rows);
  99. track_t maxCost = 0;
  100. CreateDistaceMatrix(regions, costMatrix, maxPossibleCost, maxCost, currFrame);
  101. // Solving assignment problem (shortest paths)
  102. m_SPCalculator->Solve(costMatrix, N, M, assignment, maxCost);//row->col(trackid->regionid)
  103. // clean assignment from pairs with large distance
  104. for (size_t i = 0; i < assignment.size(); i++)
  105. {
  106. if (assignment[i] != -1)
  107. {
  108. #ifdef DEBUG_SHOW
  109. std::cout<<costMatrix[i + assignment[i] * N]<<", ";
  110. #endif
  111. if (costMatrix[i + assignment[i] * N] > m_settings.m_distThres)
  112. {
  113. assignment[i] = -1;
  114. m_tracks[i]->SkippedFrames()++;
  115. }
  116. }
  117. else
  118. {
  119. #ifdef DEBUG_SHOW
  120. std::cout<<-1<<", ";
  121. #endif
  122. // If track have no assigned detect, then increment skipped frames counter.
  123. m_tracks[i]->SkippedFrames()++;
  124. }
  125. }
  126. #ifdef DEBUG_SHOW
  127. std::cout<<std::endl;
  128. #endif
  129. // If track didn't get detects long time, remove it.
  130. for (size_t i = 0; i < m_tracks.size();)
  131. {
  132. if (m_tracks[i]->SkippedFrames() > m_settings.m_maximumAllowedSkippedFrames ||
  133. m_tracks[i]->IsStaticTimeout(cvRound(fps * (m_settings.m_maxStaticTime - m_settings.m_minStaticTime))))
  134. {
  135. m_tracks.erase(m_tracks.begin() + i);
  136. assignment.erase(assignment.begin() + i);
  137. }
  138. else
  139. {
  140. ++i;
  141. }
  142. }
  143. }
  144. // Search for unassigned detects and start new tracks for them.
  145. for (size_t i = 0; i < regions.size(); ++i)
  146. {
  147. if (find(assignment.begin(), assignment.end(), i) == assignment.end())
  148. {
  149. m_tracks.push_back(std::make_unique<CTrack>(regions[i],
  150. m_settings.m_kalmanType,
  151. m_settings.m_dt,
  152. m_settings.m_accelNoiseMag,
  153. m_settings.m_useAcceleration,
  154. m_nextTrackID++%500,
  155. i,
  156. m_settings.m_filterGoal,
  157. m_settings.m_lostTrackType));
  158. }
  159. }
  160. // Update Kalman Filters state
  161. const ptrdiff_t stop_i = static_cast<ptrdiff_t>(assignment.size());
  162. #pragma omp parallel for
  163. for (ptrdiff_t i = 0; i < stop_i; ++i)
  164. {
  165. // If track updated less than one time, than filter state is not correct.
  166. if (assignment[i] != -1) // If we have assigned detect, then update using its coordinates,
  167. {
  168. m_tracks[i]->DetectedFrames()++;
  169. m_tracks[i]->SkippedFrames() = 0;
  170. m_tracks[i]->Update(
  171. regions[assignment[i]], true,
  172. m_settings.m_maxTraceLength,
  173. m_prevFrame, currFrame,
  174. m_settings.m_useAbandonedDetection ? cvRound(m_settings.m_minStaticTime * fps) : 0);
  175. }
  176. else // if not continue using predictions
  177. {
  178. m_tracks[i]->Update(CRegion(), false, m_settings.m_maxTraceLength, m_prevFrame, currFrame, 0);
  179. }
  180. m_tracks[i]->m_regionID = assignment[i];
  181. }
  182. }
  183. ///
  184. /// \brief CTracker::CreateDistaceMatrix
  185. /// \param regions
  186. /// \param costMatrix
  187. /// \param maxPossibleCost
  188. /// \param maxCost
  189. ///
  190. void CTracker::CreateDistaceMatrix(const regions_t& regions, distMatrix_t& costMatrix, track_t maxPossibleCost, track_t& maxCost, cv::UMat currFrame)
  191. {
  192. const size_t N = m_tracks.size(); // Tracking objects
  193. maxCost = 0;
  194. for (size_t i = 0; i < N; ++i)
  195. {
  196. const auto& track = m_tracks[i];
  197. // Calc predicted area for track
  198. // cv::Size_<track_t> minRadius;
  199. // if (m_settings.m_minAreaRadiusPix < 0)
  200. // {
  201. // minRadius.width = m_settings.m_minAreaRadiusK * track->LastRegion().m_rect.size.width;
  202. // minRadius.height = m_settings.m_minAreaRadiusK * track->LastRegion().m_rect.size.height;
  203. // }
  204. // else
  205. // {
  206. // minRadius.width = m_settings.m_minAreaRadiusPix;
  207. // minRadius.height = m_settings.m_minAreaRadiusPix;
  208. // }
  209. //cv::RotatedRect predictedArea = track->CalcPredictionEllipse(minRadius);
  210. // Calc distance between track and regions
  211. for (size_t j = 0; j < regions.size(); ++j)
  212. {
  213. const auto& reg = regions[j];
  214. auto dist = maxPossibleCost;
  215. if (reg.m_type==-1?(m_settings.CheckType(m_tracks[i]->LastRegion().m_type_name, reg.m_type_name)):(m_settings.CheckType(m_tracks[i]->LastRegion().m_type, reg.m_type)))
  216. {
  217. dist = 0;
  218. size_t ind = 0;
  219. if (m_settings.m_distType[ind] > 0.0f && ind == tracking::DistCenters)
  220. {
  221. #if 0
  222. track_t ellipseDist = track->IsInsideArea(reg.m_rrect.center, predictedArea);
  223. if (ellipseDist > 1)
  224. dist += m_settings.m_distType[ind];
  225. else
  226. dist += ellipseDist * m_settings.m_distType[ind];
  227. #else
  228. dist += m_settings.m_distType[ind] * track->CalcDistCenter(reg);
  229. #endif
  230. }
  231. ++ind;
  232. if (m_settings.m_distType[ind] > 0.0f && ind == tracking::DistRects)
  233. {
  234. #if 0
  235. track_t ellipseDist = track->IsInsideArea(reg.m_rect.center, predictedArea);
  236. if (ellipseDist < 1)
  237. {
  238. track_t dw = track->WidthDist(reg);
  239. track_t dh = track->HeightDist(reg);
  240. dist += m_settings.m_distType[ind] * (1 - (1 - ellipseDist) * (dw + dh) * 0.5f);
  241. }
  242. else
  243. {
  244. dist += m_settings.m_distType[ind];
  245. }
  246. //std::cout << "dist = " << dist << ", ed = " << ellipseDist << ", dw = " << dw << ", dh = " << dh << std::endl;
  247. #else
  248. dist += m_settings.m_distType[ind] * track->CalcDistRect(reg);
  249. #endif
  250. }
  251. ++ind;
  252. if (m_settings.m_distType[ind] > 0.0f && ind == tracking::DistRect3Ds)
  253. {
  254. #if 0
  255. track_t ellipseDist = track->IsInsideArea(reg.m_rect.center, predictedArea);
  256. if (ellipseDist < 1)
  257. {
  258. track_t dw = track->WidthDist(reg);
  259. track_t dh = track->HeightDist(reg);
  260. dist += m_settings.m_distType[ind] * (1 - (1 - ellipseDist) * (dw + dh) * 0.5f);
  261. }
  262. else
  263. {
  264. dist += m_settings.m_distType[ind];
  265. }
  266. //std::cout << "dist = " << dist << ", ed = " << ellipseDist << ", dw = " << dw << ", dh = " << dh << std::endl;
  267. #else
  268. dist += m_settings.m_distType[ind] * track->CalcDistRect3D(reg);
  269. #endif
  270. }
  271. ++ind;
  272. assert(ind == tracking::DistsCount);
  273. }
  274. costMatrix[i + j * N] = dist;
  275. if (dist > maxCost)
  276. maxCost = dist;
  277. }
  278. }
  279. }