trajectory.cc 15.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//   Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

W
wangguanzhong 已提交
15 16 17 18 19
// The code is based on:
// https://github.com/CnybTseng/JDE/blob/master/platforms/common/trajectory.cpp
// Ths copyright of CnybTseng/JDE is as follows:
// MIT License

20
#include "include/trajectory.h"
21
#include <algorithm>
22 23 24

namespace PaddleDetection {

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
void TKalmanFilter::init(const cv::Mat &measurement) {
  measurement.copyTo(statePost(cv::Rect(0, 0, 1, 4)));
  statePost(cv::Rect(0, 4, 1, 4)).setTo(0);
  statePost.copyTo(statePre);

  float varpos = 2 * std_weight_position * (*measurement.ptr<float>(3));
  varpos *= varpos;
  float varvel = 10 * std_weight_velocity * (*measurement.ptr<float>(3));
  varvel *= varvel;

  errorCovPost.setTo(0);
  *errorCovPost.ptr<float>(0, 0) = varpos;
  *errorCovPost.ptr<float>(1, 1) = varpos;
  *errorCovPost.ptr<float>(2, 2) = 1e-4f;
  *errorCovPost.ptr<float>(3, 3) = varpos;
  *errorCovPost.ptr<float>(4, 4) = varvel;
  *errorCovPost.ptr<float>(5, 5) = varvel;
  *errorCovPost.ptr<float>(6, 6) = 1e-10f;
  *errorCovPost.ptr<float>(7, 7) = varvel;
  errorCovPost.copyTo(errorCovPre);
45 46
}

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
const cv::Mat &TKalmanFilter::predict() {
  float varpos = std_weight_position * (*statePre.ptr<float>(3));
  varpos *= varpos;
  float varvel = std_weight_velocity * (*statePre.ptr<float>(3));
  varvel *= varvel;

  processNoiseCov.setTo(0);
  *processNoiseCov.ptr<float>(0, 0) = varpos;
  *processNoiseCov.ptr<float>(1, 1) = varpos;
  *processNoiseCov.ptr<float>(2, 2) = 1e-4f;
  *processNoiseCov.ptr<float>(3, 3) = varpos;
  *processNoiseCov.ptr<float>(4, 4) = varvel;
  *processNoiseCov.ptr<float>(5, 5) = varvel;
  *processNoiseCov.ptr<float>(6, 6) = 1e-10f;
  *processNoiseCov.ptr<float>(7, 7) = varvel;

  return cv::KalmanFilter::predict();
64 65
}

66 67 68 69 70 71 72 73 74 75 76
const cv::Mat &TKalmanFilter::correct(const cv::Mat &measurement) {
  float varpos = std_weight_position * (*measurement.ptr<float>(3));
  varpos *= varpos;

  measurementNoiseCov.setTo(0);
  *measurementNoiseCov.ptr<float>(0, 0) = varpos;
  *measurementNoiseCov.ptr<float>(1, 1) = varpos;
  *measurementNoiseCov.ptr<float>(2, 2) = 1e-2f;
  *measurementNoiseCov.ptr<float>(3, 3) = varpos;

  return cv::KalmanFilter::correct(measurement);
77 78
}

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
void TKalmanFilter::project(cv::Mat *mean, cv::Mat *covariance) const {
  float varpos = std_weight_position * (*statePost.ptr<float>(3));
  varpos *= varpos;

  cv::Mat measurementNoiseCov_ = cv::Mat::eye(4, 4, CV_32F);
  *measurementNoiseCov_.ptr<float>(0, 0) = varpos;
  *measurementNoiseCov_.ptr<float>(1, 1) = varpos;
  *measurementNoiseCov_.ptr<float>(2, 2) = 1e-2f;
  *measurementNoiseCov_.ptr<float>(3, 3) = varpos;

  *mean = measurementMatrix * statePost;
  cv::Mat temp = measurementMatrix * errorCovPost;
  gemm(temp,
       measurementMatrix,
       1,
       measurementNoiseCov_,
       1,
       *covariance,
       cv::GEMM_2_T);
98 99 100 101
}

int Trajectory::count = 0;

102 103 104
const cv::Mat &Trajectory::predict(void) {
  if (state != Tracked) *cv::KalmanFilter::statePost.ptr<float>(7) = 0;
  return TKalmanFilter::predict();
105 106
}

107 108 109 110 111 112 113 114 115 116 117 118
void Trajectory::update(Trajectory *traj,
                        int timestamp_,
                        bool update_embedding_) {
  timestamp = timestamp_;
  ++length;
  ltrb = traj->ltrb;
  xyah = traj->xyah;
  TKalmanFilter::correct(cv::Mat(traj->xyah));
  state = Tracked;
  is_activated = true;
  score = traj->score;
  if (update_embedding_) update_embedding(traj->current_embedding);
119 120
}

121 122 123 124 125 126 127 128 129 130
void Trajectory::activate(int timestamp_) {
  id = next_id();
  TKalmanFilter::init(cv::Mat(xyah));
  length = 0;
  state = Tracked;
  if (timestamp_ == 1) {
    is_activated = true;
  }
  timestamp = timestamp_;
  starttime = timestamp_;
131 132
}

133 134 135 136 137 138 139 140
void Trajectory::reactivate(Trajectory *traj, int timestamp_, bool newid) {
  TKalmanFilter::correct(cv::Mat(traj->xyah));
  update_embedding(traj->current_embedding);
  length = 0;
  state = Tracked;
  is_activated = true;
  timestamp = timestamp_;
  if (newid) id = next_id();
141 142
}

143 144 145 146 147 148 149 150
void Trajectory::update_embedding(const cv::Mat &embedding) {
  current_embedding = embedding / cv::norm(embedding);
  if (smooth_embedding.empty()) {
    smooth_embedding = current_embedding;
  } else {
    smooth_embedding = eta * smooth_embedding + (1 - eta) * current_embedding;
  }
  smooth_embedding = smooth_embedding / cv::norm(smooth_embedding);
151 152
}

153 154 155 156 157 158 159 160 161 162 163 164
TrajectoryPool operator+(const TrajectoryPool &a, const TrajectoryPool &b) {
  TrajectoryPool sum;
  sum.insert(sum.end(), a.begin(), a.end());

  std::vector<int> ids(a.size());
  for (size_t i = 0; i < a.size(); ++i) ids[i] = a[i].id;

  for (size_t i = 0; i < b.size(); ++i) {
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), b[i].id);
    if (iter == ids.end()) {
      sum.push_back(b[i]);
      ids.push_back(b[i].id);
165
    }
166 167 168
  }

  return sum;
169 170
}

171 172 173 174 175 176 177 178 179 180 181 182
TrajectoryPool operator+(const TrajectoryPool &a, const TrajectoryPtrPool &b) {
  TrajectoryPool sum;
  sum.insert(sum.end(), a.begin(), a.end());

  std::vector<int> ids(a.size());
  for (size_t i = 0; i < a.size(); ++i) ids[i] = a[i].id;

  for (size_t i = 0; i < b.size(); ++i) {
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), b[i]->id);
    if (iter == ids.end()) {
      sum.push_back(*b[i]);
      ids.push_back(b[i]->id);
183
    }
184 185 186
  }

  return sum;
187 188
}

189 190 191 192 193 194 195 196 197 198 199
TrajectoryPool &operator+=(TrajectoryPool &a,  // NOLINT
                           const TrajectoryPtrPool &b) {
  std::vector<int> ids(a.size());
  for (size_t i = 0; i < a.size(); ++i) ids[i] = a[i].id;

  for (size_t i = 0; i < b.size(); ++i) {
    if (b[i]->smooth_embedding.empty()) continue;
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), b[i]->id);
    if (iter == ids.end()) {
      a.push_back(*b[i]);
      ids.push_back(b[i]->id);
200
    }
201 202 203
  }

  return a;
204 205
}

206 207 208 209 210 211 212 213 214 215 216
TrajectoryPool operator-(const TrajectoryPool &a, const TrajectoryPool &b) {
  TrajectoryPool dif;
  std::vector<int> ids(b.size());
  for (size_t i = 0; i < b.size(); ++i) ids[i] = b[i].id;

  for (size_t i = 0; i < a.size(); ++i) {
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), a[i].id);
    if (iter == ids.end()) dif.push_back(a[i]);
  }

  return dif;
217 218
}

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
TrajectoryPool &operator-=(TrajectoryPool &a,  // NOLINT
                           const TrajectoryPool &b) {
  std::vector<int> ids(b.size());
  for (size_t i = 0; i < b.size(); ++i) ids[i] = b[i].id;

  TrajectoryPoolIterator piter;
  for (piter = a.begin(); piter != a.end();) {
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), piter->id);
    if (iter == ids.end())
      ++piter;
    else
      piter = a.erase(piter);
  }

  return a;
234 235
}

236 237 238 239 240 241 242 243 244 245 246 247 248
TrajectoryPtrPool operator+(const TrajectoryPtrPool &a,
                            const TrajectoryPtrPool &b) {
  TrajectoryPtrPool sum;
  sum.insert(sum.end(), a.begin(), a.end());

  std::vector<int> ids(a.size());
  for (size_t i = 0; i < a.size(); ++i) ids[i] = a[i]->id;

  for (size_t i = 0; i < b.size(); ++i) {
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), b[i]->id);
    if (iter == ids.end()) {
      sum.push_back(b[i]);
      ids.push_back(b[i]->id);
249
    }
250 251 252
  }

  return sum;
253 254
}

255 256 257 258 259 260 261 262 263 264 265 266
TrajectoryPtrPool operator+(const TrajectoryPtrPool &a, TrajectoryPool *b) {
  TrajectoryPtrPool sum;
  sum.insert(sum.end(), a.begin(), a.end());

  std::vector<int> ids(a.size());
  for (size_t i = 0; i < a.size(); ++i) ids[i] = a[i]->id;

  for (size_t i = 0; i < b->size(); ++i) {
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), (*b)[i].id);
    if (iter == ids.end()) {
      sum.push_back(&(*b)[i]);
      ids.push_back((*b)[i].id);
267
    }
268 269 270
  }

  return sum;
271 272
}

273 274 275 276 277 278 279 280 281 282 283 284
TrajectoryPtrPool operator-(const TrajectoryPtrPool &a,
                            const TrajectoryPtrPool &b) {
  TrajectoryPtrPool dif;
  std::vector<int> ids(b.size());
  for (size_t i = 0; i < b.size(); ++i) ids[i] = b[i]->id;

  for (size_t i = 0; i < a.size(); ++i) {
    std::vector<int>::iterator iter = find(ids.begin(), ids.end(), a[i]->id);
    if (iter == ids.end()) dif.push_back(a[i]);
  }

  return dif;
285 286
}

287 288 289 290 291 292 293 294 295 296 297 298 299 300
cv::Mat embedding_distance(const TrajectoryPool &a, const TrajectoryPool &b) {
  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      cv::Mat u = a[i].smooth_embedding;
      cv::Mat v = b[j].smooth_embedding;
      double uv = u.dot(v);
      double uu = u.dot(u);
      double vv = v.dot(v);
      double dist = std::abs(1. - uv / std::sqrt(uu * vv));
      // double dist = cv::norm(a[i].smooth_embedding, b[j].smooth_embedding,
      // cv::NORM_L2);
      distsi[j] = static_cast<float>(std::max(std::min(dist, 2.), 0.));
301
    }
302 303
  }
  return dists;
304 305
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
cv::Mat embedding_distance(const TrajectoryPtrPool &a,
                           const TrajectoryPtrPool &b) {
  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      // double dist = cv::norm(a[i]->smooth_embedding, b[j]->smooth_embedding,
      // cv::NORM_L2);
      // distsi[j] = static_cast<float>(dist);
      cv::Mat u = a[i]->smooth_embedding;
      cv::Mat v = b[j]->smooth_embedding;
      double uv = u.dot(v);
      double uu = u.dot(u);
      double vv = v.dot(v);
      double dist = std::abs(1. - uv / std::sqrt(uu * vv));
      distsi[j] = static_cast<float>(std::max(std::min(dist, 2.), 0.));
322
    }
323 324 325
  }

  return dists;
326 327
}

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
cv::Mat embedding_distance(const TrajectoryPtrPool &a,
                           const TrajectoryPool &b) {
  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      // double dist = cv::norm(a[i]->smooth_embedding, b[j].smooth_embedding,
      // cv::NORM_L2);
      // distsi[j] = static_cast<float>(dist);
      cv::Mat u = a[i]->smooth_embedding;
      cv::Mat v = b[j].smooth_embedding;
      double uv = u.dot(v);
      double uu = u.dot(u);
      double vv = v.dot(v);
      double dist = std::abs(1. - uv / std::sqrt(uu * vv));
      distsi[j] = static_cast<float>(std::max(std::min(dist, 2.), 0.));
344
    }
345 346 347
  }

  return dists;
348 349
}

350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
cv::Mat mahalanobis_distance(const TrajectoryPool &a, const TrajectoryPool &b) {
  std::vector<cv::Mat> means(a.size());
  std::vector<cv::Mat> icovariances(a.size());
  for (size_t i = 0; i < a.size(); ++i) {
    cv::Mat covariance;
    a[i].project(&means[i], &covariance);
    cv::invert(covariance, icovariances[i]);
  }

  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      const cv::Mat x(b[j].xyah);
      float dist =
          static_cast<float>(cv::Mahalanobis(x, means[i], icovariances[i]));
      distsi[j] = dist * dist;
367
    }
368
  }
369

370
  return dists;
371 372
}

373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
cv::Mat mahalanobis_distance(const TrajectoryPtrPool &a,
                             const TrajectoryPtrPool &b) {
  std::vector<cv::Mat> means(a.size());
  std::vector<cv::Mat> icovariances(a.size());
  for (size_t i = 0; i < a.size(); ++i) {
    cv::Mat covariance;
    a[i]->project(&means[i], &covariance);
    cv::invert(covariance, icovariances[i]);
  }

  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      const cv::Mat x(b[j]->xyah);
      float dist =
          static_cast<float>(cv::Mahalanobis(x, means[i], icovariances[i]));
      distsi[j] = dist * dist;
391
    }
392
  }
393

394
  return dists;
395 396
}

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
cv::Mat mahalanobis_distance(const TrajectoryPtrPool &a,
                             const TrajectoryPool &b) {
  std::vector<cv::Mat> means(a.size());
  std::vector<cv::Mat> icovariances(a.size());

  for (size_t i = 0; i < a.size(); ++i) {
    cv::Mat covariance;
    a[i]->project(&means[i], &covariance);
    cv::invert(covariance, icovariances[i]);
  }

  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      const cv::Mat x(b[j].xyah);
      float dist =
          static_cast<float>(cv::Mahalanobis(x, means[i], icovariances[i]));
      distsi[j] = dist * dist;
416
    }
417 418 419
  }

  return dists;
420 421
}

422 423 424 425 426 427
static inline float calc_inter_area(const cv::Vec4f &a, const cv::Vec4f &b) {
  if (a[2] < b[0] || a[0] > b[2] || a[3] < b[1] || a[1] > b[3]) return 0.f;

  float w = std::min(a[2], b[2]) - std::max(a[0], b[0]);
  float h = std::min(a[3], b[3]) - std::max(a[1], b[1]);
  return w * h;
428 429
}

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
cv::Mat iou_distance(const TrajectoryPool &a, const TrajectoryPool &b) {
  std::vector<float> areaa(a.size());
  for (size_t i = 0; i < a.size(); ++i) {
    float w = a[i].ltrb[2] - a[i].ltrb[0];
    float h = a[i].ltrb[3] - a[i].ltrb[1];
    areaa[i] = w * h;
  }

  std::vector<float> areab(b.size());
  for (size_t j = 0; j < b.size(); ++j) {
    float w = b[j].ltrb[2] - b[j].ltrb[0];
    float h = b[j].ltrb[3] - b[j].ltrb[1];
    areab[j] = w * h;
  }

  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    const cv::Vec4f &boxa = a[i].ltrb;
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      const cv::Vec4f &boxb = b[j].ltrb;
      float inters = calc_inter_area(boxa, boxb);
      distsi[j] = 1.f - inters / (areaa[i] + areab[j] - inters);
453
    }
454 455 456
  }

  return dists;
457 458
}

459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
cv::Mat iou_distance(const TrajectoryPtrPool &a, const TrajectoryPtrPool &b) {
  std::vector<float> areaa(a.size());
  for (size_t i = 0; i < a.size(); ++i) {
    float w = a[i]->ltrb[2] - a[i]->ltrb[0];
    float h = a[i]->ltrb[3] - a[i]->ltrb[1];
    areaa[i] = w * h;
  }

  std::vector<float> areab(b.size());
  for (size_t j = 0; j < b.size(); ++j) {
    float w = b[j]->ltrb[2] - b[j]->ltrb[0];
    float h = b[j]->ltrb[3] - b[j]->ltrb[1];
    areab[j] = w * h;
  }

  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    const cv::Vec4f &boxa = a[i]->ltrb;
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      const cv::Vec4f &boxb = b[j]->ltrb;
      float inters = calc_inter_area(boxa, boxb);
      distsi[j] = 1.f - inters / (areaa[i] + areab[j] - inters);
482
    }
483 484 485
  }

  return dists;
486 487
}

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
cv::Mat iou_distance(const TrajectoryPtrPool &a, const TrajectoryPool &b) {
  std::vector<float> areaa(a.size());
  for (size_t i = 0; i < a.size(); ++i) {
    float w = a[i]->ltrb[2] - a[i]->ltrb[0];
    float h = a[i]->ltrb[3] - a[i]->ltrb[1];
    areaa[i] = w * h;
  }

  std::vector<float> areab(b.size());
  for (size_t j = 0; j < b.size(); ++j) {
    float w = b[j].ltrb[2] - b[j].ltrb[0];
    float h = b[j].ltrb[3] - b[j].ltrb[1];
    areab[j] = w * h;
  }

  cv::Mat dists(a.size(), b.size(), CV_32F);
  for (size_t i = 0; i < a.size(); ++i) {
    const cv::Vec4f &boxa = a[i]->ltrb;
    float *distsi = dists.ptr<float>(i);
    for (size_t j = 0; j < b.size(); ++j) {
      const cv::Vec4f &boxb = b[j].ltrb;
      float inters = calc_inter_area(boxa, boxb);
      distsi[j] = 1.f - inters / (areaa[i] + areab[j] - inters);
511
    }
512 513 514
  }

  return dists;
515 516
}

517
}  // namespace PaddleDetection