32 std::string config_file =
35 AERROR <<
"Read config failed: " << config_file;
51 std::string type_change_cost_file =
53 std::ifstream fin(type_change_cost_file);
55 kTypeAssociatedCost_.clear();
57 for (
int i = 0; i < n_type; ++i) {
58 kTypeAssociatedCost_.emplace_back(std::vector<float>(n_type, 0));
59 for (
int j = 0; j < n_type; ++j) {
60 fin >> kTypeAssociatedCost_[i][j];
71 feature_extractor_.reset(
72 BaseFeatureExtractorRegisterer::GetInstanceByName(plugin_param.
name()));
73 if (
nullptr == feature_extractor_) {
74 AERROR <<
"Failed to get tracking instance.";
83 feature_init_options.
gpu_id = gpu_id_;
87 if (!feature_extractor_->Init(feature_init_options)) {
88 AERROR <<
"feature_extracotr init false";
93 ACHECK(ObjectTemplateManager::Instance()->
Init());
99 if (
nullptr == frame) {
103 AERROR <<
"FeatureExtract failed!";
108 AERROR <<
"Predict failed!";
113 AERROR <<
"Associate2D failed!";
118 AERROR <<
"Associate3D failed!";
127 bool res = feature_extractor_->Extract(feature_options, frame);
148 for (
auto &target : targets_) {
151 target.Predict(frame);
152 auto obj = target.latest_object;
159bool OMTObstacleTracker::CombineDuplicateTargets() {
160 std::vector<Hypothesis> score_list;
162 for (
size_t i = 0; i < targets_.size(); ++i) {
163 if (targets_[i].Size() == 0) {
166 for (
size_t j = i + 1; j < targets_.size(); ++j) {
167 if (targets_[j].Size() == 0) {
174 while (index1 < targets_[i].Size() && index2 < targets_[j].Size()) {
175 auto p1 = targets_[i][index1];
176 auto p2 = targets_[j][index2];
177 if (std::abs(p1->timestamp - p2->timestamp) <
179 if (p1->indicator.sensor_name != p2->indicator.sensor_name) {
180 auto box1 = p1->projected_box;
181 auto box2 = p2->projected_box;
185 score -= std::abs((rect1.width - rect2.width) *
186 (rect1.height - rect2.height) /
187 (rect1.width * rect1.height));
193 if (p1->timestamp > p2->timestamp) {
200 ADEBUG <<
"Overlap: (" << targets_[i].id <<
"," << targets_[j].id
201 <<
") score " << score <<
" count " << count;
202 hypo.
target =
static_cast<int>(i);
203 hypo.
object =
static_cast<int>(j);
204 hypo.
score = (count > 0) ? score /
static_cast<float>(count) : 0;
208 score_list.push_back(hypo);
211 sort(score_list.begin(), score_list.end(), std::greater<Hypothesis>());
212 std::vector<bool> used_target(targets_.size(),
false);
213 for (
auto &pair : score_list) {
214 if (used_target[pair.target] || used_target[pair.object]) {
217 int index1 = pair.target;
218 int index2 = pair.object;
219 if (targets_[pair.target].id > targets_[pair.object].id) {
220 index1 = pair.object;
221 index2 = pair.target;
223 Target &target_save = targets_[index1];
224 Target &target_del = targets_[index2];
225 for (
int i = 0; i < target_del.Size(); i++) {
227 target_save.Add(target_del[i]);
230 target_save.tracked_objects.begin(), target_save.tracked_objects.end(),
232 return object1->indicator.frame_id < object2->indicator.frame_id;
234 target_save.latest_object = target_save.get_object(-1);
237 AINFO <<
"Target " << target_del.id <<
" is merged into Target "
238 << target_save.id <<
" with iou " << pair.score;
239 used_target[pair.object] =
true;
240 used_target[pair.target] =
true;
245void OMTObstacleTracker::GenerateHypothesis(
const TrackObjectPtrs &objects) {
246 std::vector<Hypothesis> score_list;
248 for (
size_t i = 0; i < targets_.size(); ++i) {
249 for (
size_t j = 0; j < objects.size(); ++j) {
250 hypo.
target =
static_cast<int>(i);
251 hypo.object =
static_cast<int>(j);
253 float sa = ScoreAppearance(targets_[i], objects[j]);
255 float sm = ScoreMotion(targets_[i], objects[j]);
257 float ss = ScoreShape(targets_[i], objects[j]);
259 float so = ScoreOverlap(targets_[i], objects[j]);
264 int change_from_type =
static_cast<int>(targets_[i].type);
265 int change_to_type =
static_cast<int>(objects[j]->object->sub_type);
266 hypo.score += -kTypeAssociatedCost_[change_from_type][change_to_type];
268 AINFO <<
"Detection " << objects[j]->indicator.frame_id <<
" object "
269 << objects[j]->object->id <<
" "
270 <<
"(" << j <<
") sa:" << sa <<
" sm: " << sm <<
" ss: " << ss
271 <<
" so: " << so <<
" score: " << hypo.score;
278 score_list.push_back(hypo);
282 sort(score_list.begin(), score_list.end(), std::greater<Hypothesis>());
283 std::vector<bool> used_target(targets_.size(),
false);
284 for (
auto &pair : score_list) {
285 if (used_target[pair.target] || used_[pair.object]) {
288 Target &target = targets_[pair.target];
289 auto det_obj = objects[pair.object];
291 used_[pair.object] =
true;
292 used_target[pair.target] =
true;
293 AINFO <<
"Target " << target.id <<
" match " << det_obj->indicator.frame_id
294 <<
" (" << pair.object <<
")"
295 <<
"at " << pair.score <<
" size: " << target.Size();
299float OMTObstacleTracker::ScoreMotion(
const Target &target,
301 Eigen::Vector4d x = target.image_center.get_state();
302 float target_centerx =
static_cast<float>(x[0]);
303 float target_centery =
static_cast<float>(x[1]);
306 float s =
gaussian(center.x, target_centerx, rect.width) *
307 gaussian(center.y, target_centery, rect.height);
311float OMTObstacleTracker::ScoreShape(
const Target &target,
313 Eigen::Vector2d shape = target.image_wh.get_state();
315 float s =
static_cast<float>((shape[1] - rect.height) *
316 (shape[0] - rect.width) / (shape[1] * shape[0]));
320float OMTObstacleTracker::ScoreAppearance(
const Target &target,
325 for (
int i = target.Size() - 1; i >= 0; --i) {
329 PatchIndicator p1 = target[i]->indicator;
330 PatchIndicator p2 = track_obj->indicator;
332 energy += similar_map_.
sim(p1, p2);
336 return energy / (0.1f +
static_cast<float>(count) * 0.9f);
340float OMTObstacleTracker::ScoreOverlap(
const Target &target,
342 Eigen::Vector4d center = target.image_center.get_state();
343 Eigen::VectorXd wh = target.image_wh.get_state();
345 box_target.
xmin =
static_cast<float>(center[0] - wh[0] * 0.5);
346 box_target.xmax =
static_cast<float>(center[0] + wh[0] * 0.5);
347 box_target.ymin =
static_cast<float>(center[1] - wh[1] * 0.5);
348 box_target.ymax =
static_cast<float>(center[1] + wh[1] * 0.5);
350 auto box_obj = track_obj->projected_box;
357 const Eigen::Matrix3d &transform,
359 Eigen::Vector3d point;
361 point << box_origin.
xmin, box_origin.
ymin, 1;
362 point = transform * point;
363 box_projected->
xmin =
static_cast<float>(point[0] / point[2]);
364 box_projected->
ymin =
static_cast<float>(point[1] / point[2]);
366 point << box_origin.
xmax, box_origin.
ymax, 1;
367 point = transform * point;
368 box_projected->
xmax =
static_cast<float>(point[0] / point[2]);
369 box_projected->
ymax =
static_cast<float>(point[1] / point[2]);
372int OMTObstacleTracker::CreateNewTarget(
const TrackObjectPtrs &objects) {
375 std::vector<base::RectF> target_rects;
376 for (
auto &&target : targets_) {
377 if (!target.isTracked() || target.isLost()) {
380 base::RectF target_rect(target[-1]->object->camera_supplement.box);
381 target_rects.push_back(target_rect);
383 int created_count = 0;
384 for (
size_t i = 0; i < objects.size(); ++i) {
386 bool is_covered =
false;
387 const auto &sub_type = objects[i]->object->sub_type;
388 base::RectF rect(objects[i]->object->camera_supplement.box);
389 auto &min_tmplt = kMinTemplateHWL.at(sub_type);
392 AINFO <<
"Out of valid region";
393 AINFO <<
"Rect x: " << rect.x <<
" Rect y: " << rect.y
394 <<
" Rect height: " << rect.height
395 <<
" Rect width: " << rect.width <<
" GT height_: " << height_
396 <<
" GT width_: " << width_;
399 for (
auto &&target_rect : target_rects) {
401 if (
IsCovered(rect, target_rect, 0.4f) ||
410 if (min_tmplt.empty()
413 target.Add(objects[i]);
414 targets_.push_back(target);
415 AINFO <<
"Target " << target.id <<
" is created by "
416 << objects[i]->indicator.frame_id <<
" ("
417 << objects[i]->indicator.patch_id <<
")";
422 return created_count;
426 std::shared_ptr<CameraTrackingFrame> frame) {
429 frame_buffer_.push_back(frame);
431 std::shared_ptr<CameraTrackingFrame> cur_frame_ptr = frame_buffer_.back();
432 for (
auto frame_ptr : frame_buffer_) {
433 int pre_frame_id = frame_ptr->frame_id;
434 int cur_frame_id = cur_frame_ptr->frame_id;
435 similar_->Calc(frame_ptr.get(), cur_frame_ptr.get(),
436 similar_map_.
get(pre_frame_id, cur_frame_id).get());
440 for (
auto &target : targets_) {
441 target.RemoveOld(frame_buffer_.front()->frame_id);
450 for (
size_t i = 0; i < frame->detected_objects.size(); ++i) {
452 track_ptr->object = frame->detected_objects[i];
453 track_ptr->object->id =
static_cast<int>(i);
454 track_ptr->timestamp = frame->timestamp;
455 track_ptr->indicator =
PatchIndicator(frame->frame_id,
static_cast<int>(i),
456 frame->data_provider->sensor_name());
457 track_ptr->object->camera_supplement.sensor_name =
458 frame->data_provider->sensor_name();
459 ProjectBox(frame->detected_objects[i]->camera_supplement.box,
460 frame->project_matrix, &(track_ptr->projected_box));
461 track_objects.push_back(track_ptr);
465 used_.resize(frame->detected_objects.size(),
false);
468 GenerateHypothesis(track_objects);
471 int new_count = CreateNewTarget(track_objects);
472 AINFO <<
"Create " << new_count <<
" new target";
474 for (
auto &target : targets_) {
477 AINFO <<
"Target " << target.id <<
" is lost";
481 target.UpdateType(frame.get());
483 target.Update2D(frame.get());
488 CombineDuplicateTargets();
491 Eigen::Matrix3d inverse_project = frame->project_matrix.inverse();
492 for (
auto &target : targets_) {
493 if (!target.isLost()) {
494 ProjectBox(target[-1]->projected_box, inverse_project,
495 &(target[-1]->object->camera_supplement.box));
496 RefineBox(target[-1]->object->camera_supplement.box, width_, height_,
497 &(target[-1]->object->camera_supplement.box));
503void OMTObstacleTracker::ClearTargets() {
505 int end =
static_cast<int>(targets_.size() - 1);
506 while (left <= end) {
507 if ((targets_[left].Size() == 0)) {
508 while ((left < end) && (targets_[end].Size() == 0)) {
514 targets_[left] = targets_[end];
519 targets_.erase(targets_.begin() + left, targets_.end());
523 std::shared_ptr<CameraTrackingFrame> frame) {
525 frame->tracked_objects.clear();
529 for (
auto &target : targets_) {
530 if (target.isLost() || target.Size() == 1) {
533 auto obj = target[-1]->object;
535 Eigen::VectorXd x = target.world_center.get_state();
536 double move =
sqr(x[0] - obj->center[0]) +
sqr(x[1] - obj->center[1]);
537 float obj_2_car_x = obj->camera_supplement.local_center[0];
538 float obj_2_car_y = obj->camera_supplement.local_center[2];
539 float dis = obj_2_car_x * obj_2_car_x + obj_2_car_y * obj_2_car_y;
541 AINFO <<
"Target " << target.id <<
" is removed for abnormal movement";
542 track_objects.push_back(target.latest_object);
549 used_.resize(track_objects.size(),
false);
550 int new_count = CreateNewTarget(track_objects);
551 AINFO <<
"Create " << new_count <<
" new target";
552 for (
int j = 0; j < new_count; ++j) {
553 targets_[targets_.size() - j - 1].Update2D(frame.get());
554 targets_[targets_.size() - j - 1].UpdateType(frame.get());
556 for (
Target &target : targets_) {
557 target.Update3D(frame.get());
558 if (!target.isLost()) {
559 frame->tracked_objects.push_back(target[-1]->
object);
560 ADEBUG <<
"Target " << target.id
561 <<
" velocity: " << target.world_center.get_state().transpose()
562 <<
" % " << target.world_center.variance_.diagonal().transpose()
563 <<
" % " << target[-1]->object->velocity.transpose();
#define REGISTER_OBSTACLE_TRACKER(name)
bool Init(const ObstacleTrackerInitOptions &options) override
initialize omt obstacle tracker with options
ObjectTemplateManager * object_template_manager_
bool Associate3D(std::shared_ptr< CameraTrackingFrame > frame) override
associate obstales by 3D information associated obstacles with tracking id should be filled,...
bool FeatureExtract(CameraTrackingFrame *frame) override
extract features from the new frame
bool Associate2D(std::shared_ptr< CameraTrackingFrame > frame) override
calculate similarity of two objects
bool Process(std::shared_ptr< CameraTrackingFrame > camera_frame)
main function for tracking
bool Predict(CameraTrackingFrame *frame) override
predict candidate obstales in the new frame candidate obstacle 2D boxes should be filled,...
const TemplateMap & MinTemplateHWL()
void CorrectSize(CameraTrackingFrame *frame)
EIGEN_MAKE_ALIGNED_OPERATOR_NEW void Init(const ReferenceParam &ref_param, float width, float height)
void UpdateReference(const CameraTrackingFrame *frame, const apollo::common::EigenVector< Target > &targets)
static bool set_device_id(int device_id)
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Type CalculateIOUBBox(const base::BBox2D< Type > &box1, const base::BBox2D< Type > &box2)
std::shared_ptr< Object > ObjectPtr
Point2D< float > Point2DF
std::vector< TrackObjectPtr > TrackObjectPtrs
Dtype gaussian(Dtype x, Dtype mu, Dtype sigma)
bool IsCoveredHorizon(const base::Rect< T > &rect1, const base::Rect< T > &rect2, float thresh)
std::shared_ptr< TrackObject > TrackObjectPtr
bool OutOfValidRegion(const base::BBox2D< T > box, const T width, const T height, const T border_size=0)
void ProjectBox(const base::BBox2DF &box_origin, const Eigen::Matrix3d &transform, base::BBox2DF *box_projected)
void RefineBox(const base::Rect< T > &box_in, const T width, const T height, base::Rect< T > *box_out)
bool IsCovered(const base::Rect< T > &rect1, const base::Rect< T > &rect2, float thresh)
std::map< base::ObjectSubType, std::vector< float > > TemplateMap
std::string GetConfigFile(const std::string &config_path, const std::string &config_file)
optional string config_file
optional string config_path
std::vector< base::ObjectPtr > proposed_objects
EIGEN_MAKE_ALIGNED_OPERATOR_NEW int target
optional float min_init_height_ratio
optional ReferenceParam reference
optional WeightParam weight_same_camera
optional TargetParam target_param
optional double same_ts_eps
optional int32 feature_input_height
optional float target_combine_iou_threshold
optional float target_thresh
optional perception::PluginParam plugin_param
optional float abnormal_movement
optional int32 feature_input_width
optional string type_change_cost_file
optional int32 reserve_age
optional int32 img_capability
float sim(const PatchIndicator &p1, const PatchIndicator &p2) const
const std::shared_ptr< base::Blob< float > > get(int frame1, int frame2) const
EIGEN_MAKE_ALIGNED_OPERATOR_NEW bool Init(int dim, int gpu_id=0, int init_size=128)
optional float appearance