Exemplo n.º 1
0
  //
  // state_of_nodes()
  //
  boost::shared_ptr<std::vector< std::map<unsigned int, bool> > > state_of_nodes(const HypothesesGraph& g) {
    LOG(logDEBUG) << "detections(): entered";
    shared_ptr<vector< map<unsigned int, bool> > > ret(new vector< map<unsigned int, bool> >);

    // required node properties: timestep, traxel, active
    typedef property_map<node_timestep, HypothesesGraph::base_graph>::type node_timestep_map_t;
    node_timestep_map_t& node_timestep_map = g.get(node_timestep());
    typedef property_map<node_traxel, HypothesesGraph::base_graph>::type node_traxel_map_t;
    node_traxel_map_t& node_traxel_map = g.get(node_traxel());
    typedef property_map<node_active, HypothesesGraph::base_graph>::type node_active_map_t;
    node_active_map_t& node_active_map = g.get(node_active());


    // for every timestep
    for(int t = g.earliest_timestep(); t <= g.latest_timestep(); ++t) {
      ret->push_back(map<unsigned int, bool>());
      for(node_timestep_map_t::ItemIt node_at(node_timestep_map, t); node_at!=lemon::INVALID; ++node_at) {
	assert(node_traxel_map[node_at].Timestep == t);
	unsigned int id = node_traxel_map[node_at].Id;
	bool active = node_active_map[node_at];
	(*ret)[t-g.earliest_timestep()][id] = active;
      }
    }

    return ret;
  }
Exemplo n.º 2
0
  HypothesesGraph* SingleTimestepTraxel_HypothesesBuilder::add_edges_at(HypothesesGraph* graph, int timestep) const {
	const HypothesesGraph::node_timestep_map& timemap = graph->get(
			node_timestep());
	typedef property_map<node_traxel, HypothesesGraph::base_graph>::type traxelmap_t;
	const traxelmap_t& traxelmap = graph->get(node_traxel());
	const TraxelStoreByTimeid& traxels_by_timeid = ts_->get<by_timeid>();
	const TraxelStoreByTimestep& traxels_by_timestep = ts_->get<by_timestep>();

	//// find k nearest neighbors in next timestep
	// init nearest neighbor search
	pair<TraxelStoreByTimestep::const_iterator,
			TraxelStoreByTimestep::const_iterator> traxels_at =
			traxels_by_timestep.equal_range(timestep + 1);

	for (TraxelStoreByTimestep::const_iterator it = traxels_at.first;
			it != traxels_at.second; ++it) {
		assert(it->Timestep == (timestep+1));
	}

	NearestNeighborSearch nns(traxels_at.first, traxels_at.second);

	// establish transition edges between a current node and appropriate nodes in next timestep
	for (HypothesesGraph::node_timestep_map::ItemIt curr_node(timemap,
			timestep); curr_node != lemon::INVALID; ++curr_node) {
		assert(timemap[curr_node] == timestep);
		assert(traxelmap[curr_node].Timestep == timestep);

		// search
		map<unsigned int, double> nearest_neighbors = nns.knn_in_range(
				traxelmap[curr_node], options_.distance_threshold,
				options_.max_nearest_neighbors);

		//// connect current node with k nearest neighbor nodes
		for (map<unsigned int, double>::const_iterator neighbor =
				nearest_neighbors.begin(); neighbor != nearest_neighbors.end();
				++neighbor) {
			// connect with one of the neighbor nodes
			TraxelStoreByTimeid::iterator neighbor_traxel =
					traxels_by_timeid.find(
							boost::make_tuple(timestep + 1, neighbor->first));
			assert(neighbor_traxel->Timestep == (timestep + 1));
			assert(neighbor_traxel->Timestep != traxelmap[curr_node].Timestep);
			traxelmap_t::ItemIt neighbor_node(traxelmap, *neighbor_traxel);
			assert(curr_node != neighbor_node);
			graph->addArc(curr_node, neighbor_node);
		}
	}

	return graph;
  }
Exemplo n.º 3
0
  boost::shared_ptr<std::vector< std::vector<Event> > > events(const HypothesesGraph& g) {
    LOG(logDEBUG) << "events(): entered";
    shared_ptr<std::vector< std::vector<Event> > > ret(new vector< vector<Event> >);
    typedef property_map<node_timestep, HypothesesGraph::base_graph>::type node_timestep_map_t;
    node_timestep_map_t& node_timestep_map = g.get(node_timestep());
    typedef property_map<node_traxel, HypothesesGraph::base_graph>::type node_traxel_map_t;
    node_traxel_map_t& node_traxel_map = g.get(node_traxel());



    // for every timestep
    LOG(logDEBUG1) << "events(): earliest_timestep: " << g.earliest_timestep();
    LOG(logDEBUG1) << "events(): latest_timestep: " << g.latest_timestep();
    for(int t = g.earliest_timestep(); t < g.latest_timestep(); ++t) {
        LOG(logDEBUG2) << "events(): processing timestep: " << t;
	ret->push_back(vector<Event>());

	// for every node: destiny
	LOG(logDEBUG2) << "events(): for every node: destiny";
	for(node_timestep_map_t::ItemIt node_at(node_timestep_map, t); node_at!=lemon::INVALID; ++node_at) {
	    assert(node_traxel_map[node_at].Timestep == t);
	    // count ougoing arcs
	    int count = 0;
	    for(HypothesesGraph::base_graph::OutArcIt a(g, node_at); a!=lemon::INVALID; ++a) ++count;
	    LOG(logDEBUG3) << "events(): counted outgoing arcs: " << count;
	    // construct suitable Event object
	    switch(count) {
		// Disappearance
		case 0: {
		    Event e;
		    e.type = Event::Disappearance;
		    e.traxel_ids.push_back(node_traxel_map[node_at].Id);
		    (*ret)[t-g.earliest_timestep()].push_back(e);
		    LOG(logDEBUG3) << e;
		    break;
		    }
		// Move
		case 1: {
		    Event e;
		    e.type = Event::Move;
		    e.traxel_ids.push_back(node_traxel_map[node_at].Id);
		    HypothesesGraph::base_graph::OutArcIt a(g, node_at);
		    e.traxel_ids.push_back(node_traxel_map[g.target(a)].Id);
		    (*ret)[t-g.earliest_timestep()].push_back(e);
		    LOG(logDEBUG3) << e;
		    break;
		    }
		// Division
		case 2: {
		    Event e;
		    e.type = Event::Division;
		    e.traxel_ids.push_back(node_traxel_map[node_at].Id);
		    HypothesesGraph::base_graph::OutArcIt a(g, node_at);
		    e.traxel_ids.push_back(node_traxel_map[g.target(a)].Id);
		    ++a;
		    e.traxel_ids.push_back(node_traxel_map[g.target(a)].Id);
		    (*ret)[t-g.earliest_timestep()].push_back(e);
		    LOG(logDEBUG3) << e;
		break;
	        }
		default:
		    throw runtime_error("events(): encountered node dividing in three or more nodes in graph");
		break;
	    }
	}

	// appearances in next timestep
	LOG(logDEBUG2) << "events(): appearances in next timestep";
	for(node_timestep_map_t::ItemIt node_at(node_timestep_map, t+1); node_at!=lemon::INVALID; ++node_at) {
	    // count incoming arcs
	    int count = 0;
	    for(HypothesesGraph::base_graph::InArcIt a(g, node_at); a!=lemon::INVALID; ++a) ++count;
    	    LOG(logDEBUG3) << "events(): counted incoming arcs in next timestep: " << count;
	   
	    // no incoming arcs => appearance
	    if(count == 0) {
		    Event e;
		    e.type = Event::Appearance;
		    e.traxel_ids.push_back(node_traxel_map[node_at].Id);
		    (*ret)[t-g.earliest_timestep()].push_back(e);
		    LOG(logDEBUG3) << e;	      
	    }
	}
    }

    return ret;
  }
Exemplo n.º 4
0
  HypothesesGraph* SingleTimestepTraxel_HypothesesBuilder::add_nodes(HypothesesGraph* graph) const {
    LOG(logDEBUG) << "SingleTimestepTraxel_HypothesesBuilder::add_nodes(): entered";
    property_map<node_traxel, HypothesesGraph::base_graph>::type& traxel_m = graph->get(node_traxel());

    for(TraxelStoreByTimestep::const_iterator it = ts_->begin(); it!= ts_->end(); ++it) {
      HypothesesGraph::Node node = graph->add_node(it->Timestep);
      traxel_m.set(node, *it);
    }

    return graph;
  }
Exemplo n.º 5
0
 ////
 //// class SingleTimestepTraxel_HypothesesBuilder
 ////
 HypothesesGraph* SingleTimestepTraxel_HypothesesBuilder::construct() const {
   HypothesesGraph* graph = new HypothesesGraph();
   // store traxels inside the graph data structure
   graph->add(node_traxel());
   return graph;
 }
Exemplo n.º 6
0
////
//// class ConsTracking
////
vector<vector<Event> > ConsTracking::operator()(TraxelStore& ts) {
	cout << "-> building energy functions " << endl;

	double detection_weight = 10;
	Traxels empty;
	boost::function<double(const Traxel&, const size_t)> detection, division;
	boost::function<double(const double)> transition;

	bool use_classifier_prior = false;
	Traxel trax = *(ts.begin());
	FeatureMap::const_iterator it = trax.features.find("detProb");
	if(it != trax.features.end()) {
		use_classifier_prior = true;
	}
	if (use_classifier_prior) {
		LOG(logINFO) << "Using classifier prior";
		detection = NegLnDetection(detection_weight);
	} else if (use_size_dependent_detection_) {
		LOG(logINFO) << "Using size dependent prior";
		vector<double> means;
		if (means_.size() == 0 ) {
			for(int i = 0; i<max_number_objects_+1; ++i) {
				means.push_back(i*avg_obj_size_);
				LOG(logINFO) << "mean[" << i << "] = " << means[i];
			}
		} else {
			assert(sigmas_.size() != 0);
			for(int i = 0; i<max_number_objects_+1; ++i) {
				means.push_back(means_[i]);
				LOG(logINFO) << "mean[" << i << "] = " << means[i];
			}
		}

		vector<double> sigma2;
		if (sigmas_.size() == 0) {
			double s2 = (avg_obj_size_*avg_obj_size_)/4.0;
			if (s2 < 0.0001) {
				s2 = 0.0001;
			}
			for(int i = 0; i<max_number_objects_+1; ++i) {
				sigma2.push_back(s2);
				LOG(logINFO) << "sigma2[" << i << "] = "  << sigma2[i];
			}
		} else {
			for (int i = 0; i<max_number_objects_+1; ++i) {
				sigma2.push_back(sigmas_[i]);
				LOG(logINFO) << "sigma2[" << i << "] = "  << sigma2[i];
			}
		}

		for(TraxelStore::iterator tr = ts.begin(); tr != ts.end(); ++tr) {
			Traxel trax = *tr;
			FeatureMap::const_iterator it = trax.features.find("count");
			if(it == trax.features.end()) {
				throw runtime_error("get_detection_prob(): cellness feature not in traxel");
			}
			double vol = it->second[0];
			vector<double> detProb;
			detProb = computeDetProb(vol,means,sigma2);
			feature_array detProbFeat(feature_array::difference_type(max_number_objects_+1));
			for(int i = 0; i<=max_number_objects_; ++i) {
				double d = detProb[i];
				if (d < 0.01) {
					d = 0.01;
				} else if (d > 0.99) {
					d = 0.99;
				}
				LOG(logDEBUG2) << "detection probability for " << trax.Id << "[" << i << "] = " << d;
				detProbFeat[i] = d;
			}
			trax.features["detProb"] = detProbFeat;
			ts.replace(tr, trax);
		}
		detection = NegLnDetection(detection_weight); // weight 1
	} else {
		LOG(logINFO) << "Using hard prior";
		// assume a quasi geometric distribution
		vector<double> prob_vector;
		double p = 0.7; // e.g. for max_number_objects_=3, p=0.7: P(X=(0,1,2,3)) = (0.027, 0.7, 0.21, 0.063)
		double sum = 0;
		for(double state = 0; state < max_number_objects_; ++state) {
			double prob = p*pow(1-p,state);
			prob_vector.push_back(prob);
			sum += prob;
		}
		prob_vector.insert(prob_vector.begin(), 1-sum);

		detection = bind<double>(NegLnConstant(detection_weight,prob_vector), _2);
	}

	LOG(logDEBUG1) << "division_weight_ = " << division_weight_;
	LOG(logDEBUG1) << "transition_weight_ = " << transition_weight_;
	division = NegLnDivision(division_weight_);
	transition = NegLnTransition(transition_weight_);

	cout << "-> building hypotheses" << endl;
	SingleTimestepTraxel_HypothesesBuilder::Options builder_opts(1, // max_nearest_neighbors
				max_dist_,
				true, // forward_backward
				with_divisions_, // consider_divisions
				division_threshold_
				);
	SingleTimestepTraxel_HypothesesBuilder hyp_builder(&ts, builder_opts);
	HypothesesGraph* graph = hyp_builder.build();


	LOG(logDEBUG1) << "ConsTracking(): adding distance property to edges";
	HypothesesGraph& g = *graph;
	g.add(arc_distance()).add(tracklet_intern_dist()).add(node_tracklet()).add(tracklet_intern_arc_ids()).add(traxel_arc_id());
	property_map<arc_distance, HypothesesGraph::base_graph>::type& arc_distances = g.get(arc_distance());
	property_map<node_traxel, HypothesesGraph::base_graph>::type& traxel_map = g.get(node_traxel());
	bool with_optical_correction = false;
	Traxel some_traxel = (*traxel_map.beginValue());
	if (some_traxel.features.find("com_corrected") != some_traxel.features.end()) {
		LOG(logINFO) << "optical correction enabled";
		with_optical_correction = true;
	}

	for(HypothesesGraph::ArcIt a(g); a!=lemon::INVALID; ++a) {
		HypothesesGraph::Node from = g.source(a);
		HypothesesGraph::Node to = g.target(a);
		Traxel from_tr = traxel_map[from];
		Traxel to_tr = traxel_map[to];

		if (with_optical_correction) {
			arc_distances.set(a, from_tr.distance_to_corr(to_tr));
		} else {
			arc_distances.set(a, from_tr.distance_to(to_tr));
		}
	}
	//border_width_ is given in normalized scale, 1 corresponds to a maximal distance of dim_range/2
	boost::function<double(const Traxel&)> appearance_cost_fn, disappearance_cost_fn;
	LOG(logINFO) << "using border-aware appearance and disappearance costs, with absolute margin: " << border_width_;
	appearance_cost_fn = SpatialBorderAwareWeight(appearance_cost_,
												border_width_,
												false, // true if relative margin to border
												fov_);
	disappearance_cost_fn = SpatialBorderAwareWeight(disappearance_cost_,
												border_width_,
												false, // true if relative margin to border
												fov_);

	cout << "-> init ConservationTracking reasoner" << endl;
	ConservationTracking pgm(
			max_number_objects_,
			detection,
			division,
			transition,
			forbidden_cost_,
			ep_gap_,
			with_tracklets_,
			with_divisions_,
			disappearance_cost_fn,
			appearance_cost_fn,
			true, // with_misdetections_allowed
			true, // with_appearance
			true, // with_disappearance
			transition_parameter_,
			with_constraints_
			);

	cout << "-> formulate ConservationTracking model" << endl;
	pgm.formulate(*graph);

	cout << "-> infer" << endl;
	pgm.infer();

	cout << "-> conclude" << endl;
	pgm.conclude(*graph);

	cout << "-> storing state of detection vars" << endl;
	last_detections_ = state_of_nodes(*graph);

	cout << "-> pruning inactive hypotheses" << endl;
	prune_inactive(*graph);

    cout << "-> constructing unresolved events" << endl;
    boost::shared_ptr<std::vector< std::vector<Event> > > ev = events(*graph);


    if (max_number_objects_ > 1 && with_merger_resolution_ && all_true(ev->begin(), ev->end(), has_data<Event>)) {
      cout << "-> resolving mergers" << endl;
      MergerResolver m(graph);
      FeatureExtractorMCOMsFromMCOMs extractor;
      DistanceFromCOMs distance;
      FeatureHandlerFromTraxels handler(extractor, distance);
      calculate_gmm_beforehand(*graph, 1, number_of_dimensions_);
      m.resolve_mergers(handler);

      HypothesesGraph g_res;
      resolve_graph(*graph, g_res, transition, ep_gap_, with_tracklets_, transition_parameter_, with_constraints_);
      prune_inactive(*graph);

      cout << "-> constructing resolved events" << endl;
      boost::shared_ptr<std::vector< std::vector<Event> > > multi_frame_moves = multi_frame_move_events(*graph);

      cout << "-> merging unresolved and resolved events" << endl;
      return *merge_event_vectors(*ev, *multi_frame_moves);
    }

    else {
      return *ev;
    }

        

	

	
}