Esempio n. 1
0
/** 将最新的轮廓合并到已有的“活动区域中”,如果没有重叠,则新建“活动区域”
 */
void DetectWithOF5::merge_motions(const CONTOURS &regions)
{
	remove_timeout_motions();

	/** 检查 regions 是否属于某个 motions ...
	 */
	std::set<size_t> merged_idxs;	// regions 中,被合并的idx
	std::vector<size_t> exp_idxs;
	for (size_t i = 0; i < motions_.size(); i++) {
		/** 针对每个 motion,合并所有与最后位置相交的轮廓 */
		Motion &m = motions_[i];
		exp_idxs.clear();

		// motion 仅仅保留最后 M 帧
		if (m.history.size() > m.M) {
			m.history.pop_front();	// FIXME: 有可能 history 中剩下的都是“空”轮廓了,但一般情况下不会的 ...
			if (m.tracking_inited_) {
				m.tracking_pts.pop_front();	// FIXME: 保证 size() ...
			}

			m.dense_of_poss.pop_front();
			m.dense_of_xs.pop_front();
			m.dense_of_ys.pop_front();

			m.frame_idx_ ++;
		}

		assert(!m.tracking_inited_ || m.history.size() == m.tracking_pts.size());

		// 最后一个有效轮廓的外接圆 ..
		cv::Point2f c0;
		float r0;
		cv::minEnclosingCircle(m.last_contour, c0, r0);	// 最后轮廓的外接圆

		for (size_t j = 0; j < regions.size(); j++) {
			cv::Point2f c;
			float r;
			cv::minEnclosingCircle(regions[j], c, r);
			if (::is_cross(c0, r0, c, r)) {
				exp_idxs.push_back(j);
				merged_idxs.insert(j);
			}
		}

		/** FIXME: 如果需要扩展两个以上轮廓,而且两个轮廓距离还比较远,如何合并?
				可能更好的方法是,根据历史运动的方向,选择其中某个轮廓,但 ....
		 */

		bool update = false;
		if (exp_idxs.size() == 1) {
			// 保存被合并的轮廓 ..
			m.last_contour = regions[exp_idxs[0]];
			motions_[i].history.push_back(m.last_contour);
			motions_[i].stamp = curr_;
			update = true;
		}
		else if (exp_idxs.size() == 0) {
			// 此时说明 motion 没有活动 ???
			motions_[i].history.push_back(CONTOUR());	//
		}
		else {
			// TODO: 应该根据历史轨迹方向,选择更有可能的一个 ...
			m.last_contour = regions[exp_idxs[0]];
			motions_[i].history.push_back(m.last_contour);
			motions_[i].stamp = curr_;
			update = true;
		}

		if (update) {
			// 重新计算外界矩形 ...
			m.update_bounding_rc();
		}

		if (m.dense_of_poss.size() > 0) {
			// 更新稠密光流
			cv::Mat x, y;
			if (calc_dense_of(m.brc, x, y)) {
				m.dense_of_poss.push_back(m.brc);
				m.dense_of_xs.push_back(x);
				m.dense_of_ys.push_back(y);
			}
		}

		if (!m.tracking_inited_) {
			m.init_tracking(cc_);
		}
	}

	// 合并重叠的 motions
	merge_overlapped_motions();

	// 创建新的 motions
	for (size_t i = 0; i < regions.size(); i++) {
		if (merged_idxs.find(i) == merged_idxs.end()) { // 所有未被合并的轮廓都应该创建为新的 motions ??
			const CONTOUR &c = regions[i];

			/** 使用不同颜色标识motion,方便调试 ...
			 */
			const cv::Scalar _colors[] = { cv::Scalar(0, 128, 0), cv::Scalar(0, 0, 128), cv::Scalar(0, 128, 128), cv::Scalar(0, 255, 128), cv::Scalar(0, 255, 0),
				cv::Scalar(128, 255, 0), cv::Scalar(128, 128, 0), cv::Scalar(255, 0, 0) };
			const size_t _colors_cnt = sizeof(_colors) / sizeof(cv::Scalar);
			static int _mid = 0;

			Motion m;
			m.parent = this;
			m.discard_ = false;
			m.id = _mid++;
			m.M = motion_M_;
			m.history.push_back(c);
			m.last_contour = c;
			m.brc = cv::boundingRect(c);
			m.stamp = curr_;
			m.frame_idx_ = hist_.frame_idx_ + hist_.frames.size() - 1;	// FIXME: 对应着历史中最后一帧图像 ...
			m.color = _colors[m.id % _colors_cnt];
			m.tracking_inited_ = false;
			m.init_tracking(cc_);

			// 启用稠密光流 ...
			cv::Mat x, y;
			if (calc_dense_of(m.brc, x, y)) {
				m.dense_of_poss.push_back(m.brc);
				m.dense_of_xs.push_back(x);
				m.dense_of_ys.push_back(y);
			}

			motions_.push_back(m);
		}
	}
}