📄 activeshapetracker.cc
字号:
// if track is fairly new and the fit is poor then kill it if ((frame_id - curr_prf->frame_first_detected < SMALL_NO_FRAMES) && (curr_prf->fitness < FITNESS_THRESHOLD)) is_ok = false; // if the positional uncertainty has grown too large, kill it if (curr_prf->track_error > terminate_thresh) is_ok = false; // if the fit is really bad and a significant part of the // contour is observable (unoccluded), kill it if ((curr_prf->fitness < VERY_POOR_FIT) && (active_model->get_significance() > MIN_SIGNIFICANCE)) is_ok = false; if (is_ok == false) { if (frame_id - curr_prf->frame_first_detected < SMALL_NO_FRAMES) { cdebug << "AST: Killing object " << curr_obj->dat->id << " (alive " << frame_id - curr_prf->frame_first_detected << ") :" << " track error = " << curr_prf->track_error << ", fitness = " << curr_prf->fitness << endl << "AST: observed " << active_model->no_observed << " out of " << active_model->no_looks << endl; curr = curr->next; profiles->destroy(curr_prf); } else { cdebug << "AST: Disabling object " << curr_obj->dat->id << " (alive " << frame_id - curr_prf->frame_first_detected << ") :" << " track error = " << curr_prf->track_error << ", fitness = " << curr_prf->fitness << endl << "AST: observed " << active_model->no_observed << " out of " << active_model->no_looks << endl; curr_prf->is_visible = false; curr_prf->source = PREDICTION; // stay at predicted curr = curr->next; } } else { // track is ok and visible now // store tracking status in profile curr_prf->source = MEASUREMENT; curr_prf->is_visible = true; curr_prf->frame_last_detected = frame_id; curr_prf->time_last_detected = frame_time; // this means that the corresponding TrackedObject is also visible curr_obj->dat->is_visible = true; // increment curr = curr->next; } } }}void ActiveShapeTracker::detect_new_objects(Inputs *inputs, Results *results){ TrackedObjectSet *objects = results->get_tracked_objects(); if (objects->no_items >= max_objects) { cdebug << " ActiveShapeTracker::detect_new_objects: " << " no more detection because we already have max_objects == " << max_objects; return; } #ifdef DEBUG inputs->get_video_image()->draw_in_image(); ////////////#endif // get regions from tracked object set, applying a shape to and tracking each for (objects->start(); objects->current_ok(); objects->forward()) { RegionSet *regions = objects->get_current()->regions; ProfileSet *new_profiles; // first check whether the surrounding region is incorporated into the background if ((regions->no_items > 0) && (regions->first->dat->incorporated_into_background)) continue; // ignore! // // 1 - get regions and convert them into profiles using RegionSet::to_profiles() // // if there are new regions convert them to profiles... if (regions->no_items > 0) { // convert regions to profile by tracing outline new_profiles = regions->to_profiles(); // FIXME: not available // // scale coordinates if motion image is subsampled// new_profiles->scale_coords (tracking->get_motion_detector()->sample_skip);// // // filter all profiles for this object according to height/width ratio// height_width_ratio_filter_profiles(new_profiles); // assert(curr_obj->dat->profiles->no_items == 0); // add observations temporarily to tracked object (removed later if not ok) objects->get_current()->profiles->concat(new_profiles); delete /* the now emptied */ new_profiles; } // // 2 - get heads from human features and initialise profiles from them // HumanFeatureSet *features = objects->get_current()->features; if (features->no_items > 0) { new_profiles = new ProfileSet; for (features->start(); features->current_ok(); features->forward()) { HeadInfo *head_info = features->get_current()->head; realno height; // new Profile's height if (use_calibration) { NagVector nag_origin(3); // centre of the head in the image, NAG vector format, homogeneous nag_origin[0] = head_info->x_abs; nag_origin[1] = head_info->y_abs; nag_origin[2] = 1; height = calibration->get_image_distance_from_height_in_cm (nag_origin, TYPICAL_WORLD_HEIGHT, TYPICAL_WORLD_HEIGHT); } else { // get the new profile's height from the first region // FIXME: why first??? assert (objects->get_current()->regions->no_items == 1); height = objects->get_current()->regions->first->dat->height; } // create new profile from head info Profile *new_profile; // check ImageAdressing mode before adding up coordinates... if (Image::image_addressing_mode == IA_BOTTOM_TO_TOP) new_profile = new Profile(head_info->x_abs, head_info->y_abs + head_info->y - height/2, head_info->width, // width does not matter here height); else new_profile = new Profile(head_info->x_abs, head_info->y_abs - head_info->y + height/2, head_info->width, // width does not matter here height); cdebug << "ActiveShapeTracker::detect_new_objects() : new profile from head! " << endl; // adjust status new_profile->source = features->get_current()->source; // ie MEASUREMENT // if we have Calibration the size will be corrected further down new_profiles->add(new_profile); } objects->get_current()->profiles->concat(new_profiles); delete /* the now emptied */ new_profiles; } ProfileSet *profiles = objects->get_current()->profiles; signed int index; // index into profiles // // 3 - use calibration to create new hypotheses for each profile // if (use_calibration) { int no_items = profiles->no_items; // to avoid recursion when appending for (index = 0; index < no_items; index++) { Profile *curr_prf = (*profiles)[index]; // ignore old objects (already tracked in track_old_objects()) if (curr_prf->filters_initialised) continue; // non-measurements should not be here assert (curr_prf->source == MEASUREMENT); create_hypotheses_using_calibration(curr_prf, profiles); } } // // 4 - track these new and any other uninitialised profiles for this object // for (index = 0; index < profiles->no_items; index++) { Profile *curr_prf = (*profiles)[index]; // ignore old objects (already tracked in track_old_objects()) if (curr_prf->filters_initialised) continue; // non-measurements should be ignored in regions->to_profiles(), assert (curr_prf->source == MEASUREMENT); // initialise filters and get model hypothesis from our ActiveModel initialise_track(curr_prf); // convert coordinates active_model->b_to_x(); // track profile using our ActiveModel curr_prf->fitness = active_model->track_profile(objects->get_current()->id); curr_prf->track_error = sqrt(curr_prf->pos_filter->get_uncertainty()); // update variables like xlo, xhi, width etc curr_prf->update_size_variables(); if ((curr_prf->track_error < terminate_thresh) && (curr_prf->fitness > FITNESS_THRESHOLD)) { // accept track // store tracking status in profile curr_prf->source = MEASUREMENT; curr_prf->is_visible = true; curr_prf->frame_first_detected = curr_prf->frame_last_detected = inputs->get_frame_id(); curr_prf->time_first_detected = curr_prf->time_last_detected = inputs->get_frame_time_in_ms(); // remember that the corresponding TrackedObject is thereby visible objects->get_current()->is_visible = true; } else { // reject track profiles->destroy(index); index--; // no increment necessary to get to next profile } } }}// clean up old tracks from multiple hypotheses of the same tracked person etcvoid ActiveShapeTracker::post_process_frame(Inputs *inputs, Results *results){ // check all tracked objects for multiple occurances of tracked profiles. // if there is more than one and they resemble the same person then remove // all but the best track. // FIXME: ...and set all tracker pointers to sensible values TrackedObjectSet *objects = results->get_tracked_objects(); ProfileSet *profiles; // profiles for one object to be checked signed int index1, index2; // indices into profiles or objects Profile *prf1, *prf2; // the actual profiles indexed TrackedObject *obj1, *obj2; // the actual objects indexed ListNode<TrackedObject> *curr_obj; // tracked object item to be checked // // 1 - clean up profiles within each tracked object // // get profiles from tracked object set and keep only the best for (curr_obj = objects->first; curr_obj != NULL; curr_obj = curr_obj->next) { // get profile(s) for this tracked object (might well be more than one) profiles = curr_obj->dat->profiles; // ignore object unless there are at least two profiles here if (profiles->no_items < 2) continue; // ignore background objects here if ((curr_obj->dat->regions->no_items > 0) && (curr_obj->dat->regions->first->dat->incorporated_into_background)) continue; // check each combination of profiles doing pair-wise comparisons for (index1 = 0; index1 + 1 < profiles->no_items; index1++) { prf1 = (*profiles)[index1]; // ignore disabled profiles if (prf1->fitness <= 0) continue; for (index2 = index1 + 1; index2 < profiles->no_items; index2++) { prf2 = (*profiles)[index2]; // ignore disabled profiles if (prf2->fitness <= 0) continue; // do the actual comparison: if the two profiles match disable // the worse fitting profile by setting its fitness to 0 compare_two_and_disable_bad_profile(prf1, prf2); } } } // after marking profiles for deletion destroy all these and other bad profiles for (index1 = 0; index1 < objects->no_items; index1++) // look in all objects: { obj1 = (*objects)[index1]; for (index2 = 0; index2 < obj1->profiles->no_items; ) // all profiles in object: { prf1 = (*obj1->profiles)[index2]; if (prf1->fitness <= 0) { obj1->profiles->destroy(prf1); cdebug << "ActiveShapeTracker::post_process_frame() 1: " << "cleaned away bad/duplicate profile within object " << obj1->id << " because its fitness was " << prf1->fitness << " " << endl; // NB: The TrackedObject will be cleaned away elsewhere if it is empty now } else index2++; } } // // 2 - split objects containing more than one (distinct after the above) person // // check each object for the number of profiles for (index1 = 0; index1 + 1 < objects->no_items; index1++) { obj1 = (*objects)[index1]; // only check objects which have 1 region and at least 2 profiles if (obj1->regions->no_items != 1) continue; if (obj1->profiles->no_items < 2) continue; if (obj1->profiles->no_items > 2) cdebug << " ActiveShapeTracker::post_process_frame() 2: Warning: " << obj1->profiles->no_items << " profiles (can only handle 2) " << endl; // assert (obj1->profiles->no_items == 2); // cannot handle more for now // FIXME: use a while loop if (obj1->profiles->first->dat->source != MEASUREMENT) // FIXME: do not check 1st only continue; // do not work on background objects if (obj1->regions->first->dat->incorporated_into_background) continue; // split object into two by copying data over TrackedObject *new_obj = new TrackedObject; *new_obj = *obj1; // disable one profile in one object, the other one in the other obj1->profiles->destroy(obj1->profiles->last->dat); new_obj->profiles->destroy(new_obj->profiles->first->dat); // get the two remaining (distinct) profiles prf1 = obj1->profiles->first->dat; prf2 = new_obj->profiles->first->dat; // adjust associated regions Region *reg1 = obj1->regions->first->dat; Region *reg2 = new_obj->regions->first->dat; // now correct position, size and status of the regions matched to the profiles reg1->Observation::operator=(*prf1); reg1->old_origin = reg1->origin; reg1->direction.x = reg1->direction.y = 0; reg2->Observation::operator=(*prf2); reg2->old_origin = reg2->origin; reg2->direction.x = reg2->direction.y = 0; new_obj->frames_static = obj1->frames_static; // create a new id for the newly created object and add it to the tracked objects new_obj->id = PeopleTracker::create_new_id(); objects->add(new_obj); cdebug << "ActiveShapeTracker::post_process_frame() 2: split object " << obj1->id << " into two objects, new object id " << new_obj->id << " " << endl; } // // 3 - clean up tracked objects if they correspond to the same tracked person // // check each combination of profiles doing pairwise comparisons for (index1 = 0; index1 + 1 < objects->no_items; index1++) { obj1 = (*objects)[index1]; // only check objects which have a Profile if (obj1->profiles->no_items == 0) continue; // FIXME: put an if assert (obj1->profiles->no_items == 1); // should be ok after the above clean-up // ignore background objects here if ((obj1->regions->no_items > 0) && (obj1->regions->first->dat->incorporated_into_background)) continue; prf1 = obj1->profiles->first->dat; for (index2 = index1 + 1; index2 < objects->no_items; index2++) { obj2 = (*objects)[index2]; // only check objects which have a Profile if (obj2->profiles->no_items == 0) continue; // FIXME: put an if assert (obj2->profiles->no_items == 1); // should be ok after the above clean-up
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -