30 TrackBase::TrackBase(std::unordered_map<
size_t, std::shared_ptr<CamBase>> cameras,
int numfeats,
int numaruco,
bool stereo,
32 : camera_calib(cameras), database(new
FeatureDatabase()), num_features(numfeats), use_stereo(stereo), histogram_method(histmethod) {
34 currid = 4 * (size_t)numaruco + 1;
46 std::map<size_t, cv::Mat> img_last_cache, img_mask_last_cache;
47 std::unordered_map<size_t, std::vector<cv::KeyPoint>> pts_last_cache;
58 for (
auto const &pair : img_last_cache) {
59 if (max_width < pair.second.cols)
60 max_width = pair.second.cols;
61 if (max_height < pair.second.rows)
62 max_height = pair.second.rows;
66 if (img_last_cache.empty() || max_width == -1 || max_height == -1)
70 bool is_small = (std::min(max_width, max_height) < 400);
74 bool image_new = ((int)img_last_cache.size() * max_width != img_out.cols || max_height != img_out.rows);
78 img_out = cv::Mat(max_height, (
int)img_last_cache.size() * max_width, CV_8UC3, cv::Scalar(0, 0, 0));
82 for (
auto const &pair : img_last_cache) {
86 cv::cvtColor(img_last_cache[pair.first], img_temp, cv::COLOR_GRAY2RGB);
88 img_temp = img_out(cv::Rect(max_width * index_cam, 0, max_width, max_height));
90 for (
size_t i = 0; i < pts_last_cache[pair.first].size(); i++) {
92 cv::Point2f pt_l = pts_last_cache[pair.first].at(i).pt;
94 cv::circle(img_temp, pt_l, (is_small) ? 1 : 2, cv::Scalar(r1, g1, b1), cv::FILLED);
97 cv::Point2f pt_l_top = cv::Point2f(pt_l.x - 3, pt_l.y - 3);
98 cv::Point2f pt_l_bot = cv::Point2f(pt_l.x + 3, pt_l.y + 3);
99 cv::rectangle(img_temp, pt_l_top, pt_l_bot, cv::Scalar(r2, g2, b2), 1);
102 auto txtpt = (is_small) ? cv::Point(10, 30) : cv::Point(30, 60);
104 cv::putText(img_temp,
"CAM:" + std::to_string((
int)pair.first), txtpt, cv::FONT_HERSHEY_COMPLEX_SMALL, (is_small) ? 1.5 : 3.0,
105 cv::Scalar(0, 255, 0), 3);
107 cv::putText(img_temp, overlay, txtpt, cv::FONT_HERSHEY_COMPLEX_SMALL, (is_small) ? 1.5 : 3.0, cv::Scalar(0, 0, 255), 3);
110 cv::Mat mask = cv::Mat::zeros(img_mask_last_cache[pair.first].rows, img_mask_last_cache[pair.first].cols, CV_8UC3);
111 mask.setTo(cv::Scalar(0, 0, 255), img_mask_last_cache[pair.first]);
112 cv::addWeighted(mask, 0.1, img_temp, 1.0, 0.0, img_temp);
114 img_temp.copyTo(img_out(cv::Rect(max_width * index_cam, 0, img_last_cache[pair.first].cols, img_last_cache[pair.first].rows)));
120 std::string overlay) {
123 std::map<size_t, cv::Mat> img_last_cache, img_mask_last_cache;
124 std::unordered_map<size_t, std::vector<cv::KeyPoint>> pts_last_cache;
125 std::unordered_map<size_t, std::vector<size_t>> ids_last_cache;
137 for (
auto const &pair : img_last_cache) {
138 if (max_width < pair.second.cols)
139 max_width = pair.second.cols;
140 if (max_height < pair.second.rows)
141 max_height = pair.second.rows;
145 if (img_last_cache.empty() || max_width == -1 || max_height == -1)
149 bool is_small = (std::min(max_width, max_height) < 400);
153 bool image_new = ((int)img_last_cache.size() * max_width != img_out.cols || max_height != img_out.rows);
157 img_out = cv::Mat(max_height, (
int)img_last_cache.size() * max_width, CV_8UC3, cv::Scalar(0, 0, 0));
160 size_t maxtracks = 50;
164 for (
auto const &pair : img_last_cache) {
168 cv::cvtColor(img_last_cache[pair.first], img_temp, cv::COLOR_GRAY2RGB);
170 img_temp = img_out(cv::Rect(max_width * index_cam, 0, max_width, max_height));
172 for (
size_t i = 0; i < ids_last_cache[pair.first].size(); i++) {
174 if (std::find(highlighted.begin(), highlighted.end(), ids_last_cache[pair.first].at(i)) != highlighted.end()) {
175 cv::Point2f pt_c = pts_last_cache[pair.first].at(i).pt;
176 cv::Point2f pt_l_top = cv::Point2f(pt_c.x - ((is_small) ? 3 : 5), pt_c.y - ((is_small) ? 3 : 5));
177 cv::Point2f pt_l_bot = cv::Point2f(pt_c.x + ((is_small) ? 3 : 5), pt_c.y + ((is_small) ? 3 : 5));
178 cv::rectangle(img_temp, pt_l_top, pt_l_bot, cv::Scalar(0, 255, 0), 1);
179 cv::circle(img_temp, pt_c, (is_small) ? 1 : 2, cv::Scalar(0, 255, 0), cv::FILLED);
183 if (!
database->get_feature_clone(ids_last_cache[pair.first].at(i), feat))
185 if (feat.
uvs.empty() || feat.
uvs[pair.first].empty() || feat.
to_delete)
188 for (
size_t z = feat.
uvs[pair.first].size() - 1; z > 0; z--) {
190 if (feat.
uvs[pair.first].size() - z > maxtracks)
193 bool is_stereo = (feat.
uvs.size() > 1);
194 int color_r = (is_stereo ? b2 : r2) - (
int)(1.0 * (is_stereo ? b1 : r1) / feat.
uvs[pair.first].size() * z);
195 int color_g = (is_stereo ? r2 : g2) - (
int)(1.0 * (is_stereo ? r1 : g1) / feat.
uvs[pair.first].size() * z);
196 int color_b = (is_stereo ? g2 : b2) - (
int)(1.0 * (is_stereo ? g1 : b1) / feat.
uvs[pair.first].size() * z);
198 cv::Point2f pt_c(feat.
uvs[pair.first].at(z)(0), feat.
uvs[pair.first].at(z)(1));
199 cv::circle(img_temp, pt_c, (is_small) ? 1 : 2, cv::Scalar(color_r, color_g, color_b), cv::FILLED);
201 if (z + 1 < feat.
uvs[pair.first].size()) {
202 cv::Point2f pt_n(feat.
uvs[pair.first].at(z + 1)(0), feat.
uvs[pair.first].at(z + 1)(1));
203 cv::line(img_temp, pt_c, pt_n, cv::Scalar(color_r, color_g, color_b));
206 if (z == feat.
uvs[pair.first].size() - 1) {
213 auto txtpt = (is_small) ? cv::Point(10, 30) : cv::Point(30, 60);
215 cv::putText(img_temp,
"CAM:" + std::to_string((
int)pair.first), txtpt, cv::FONT_HERSHEY_COMPLEX_SMALL, (is_small) ? 1.5 : 3.0,
216 cv::Scalar(0, 255, 0), 3);
218 cv::putText(img_temp, overlay, txtpt, cv::FONT_HERSHEY_COMPLEX_SMALL, (is_small) ? 1.5 : 3.0, cv::Scalar(0, 0, 255), 3);
221 cv::Mat mask = cv::Mat::zeros(img_mask_last_cache[pair.first].rows, img_mask_last_cache[pair.first].cols, CV_8UC3);
222 mask.setTo(cv::Scalar(0, 0, 255), img_mask_last_cache[pair.first]);
223 cv::addWeighted(mask, 0.1, img_temp, 1.0, 0.0, img_temp);
225 img_temp.copyTo(img_out(cv::Rect(max_width * index_cam, 0, img_last_cache[pair.first].cols, img_last_cache[pair.first].rows)));
233 if (
database->get_internal_data().find(id_old) !=
database->get_internal_data().end()) {
234 std::shared_ptr<Feature> feat =
database->get_internal_data().at(id_old);
235 database->get_internal_data().erase(id_old);
236 feat->featid = id_new;
237 database->get_internal_data().insert({id_new, feat});
241 for (
auto &cam_ids_pair :
ids_last) {
242 for (
size_t i = 0; i < cam_ids_pair.second.size(); i++) {
243 if (cam_ids_pair.second.at(i) == id_old) {
244 ids_last.at(cam_ids_pair.first).at(i) = id_new;