Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 1 | #include <endian.h> |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 2 | #include <gdk/gdk.h> |
| 3 | #include <gtk/gtk.h> |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 4 | #include <sys/stat.h> |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 5 | |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 6 | #include <cstdio> |
| 7 | #include <cstdlib> |
| 8 | #include <fstream> |
| 9 | #include <memory> |
| 10 | #include <vector> |
| 11 | |
| 12 | #include "aos/vision/blob/stream_view.h" |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 13 | #include "aos/vision/events/epoll_events.h" |
| 14 | #include "aos/vision/events/tcp_server.h" |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 15 | #include "aos/vision/image/image_stream.h" |
| 16 | #include "aos/vision/image/jpeg_routines.h" |
| 17 | #include "aos/vision/image/reader.h" |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 18 | #include "y2016/vision/blob_filters.h" |
| 19 | // #include "y2016/vision/process_targets.h" |
| 20 | |
| 21 | namespace y2016 { |
| 22 | namespace vision { |
| 23 | using namespace aos::vision; |
| 24 | |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 25 | ::aos::vision::Vector<2> CreateCenterFromTarget(double lx, double ly, double rx, |
| 26 | double ry) { |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 27 | return ::aos::vision::Vector<2>((lx + rx) / 2.0, (ly + ry) / 2.0); |
| 28 | } |
| 29 | |
| 30 | double TargetWidth(double lx, double ly, double rx, double ry) { |
| 31 | double dx = lx - rx; |
| 32 | double dy = ly - ry; |
| 33 | return ::std::hypot(dx, dy); |
| 34 | } |
| 35 | |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 36 | void SelectTargets(std::vector<std::pair<Vector<2>, Vector<2>>> &left_target, |
| 37 | std::vector<std::pair<Vector<2>, Vector<2>>> &right_target, |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 38 | ::aos::vision::Vector<2> *center_left, |
| 39 | ::aos::vision::Vector<2> *center_right) { |
| 40 | // No good targets. Let the caller decide defaults. |
| 41 | if (right_target.size() == 0 || left_target.size() == 0) { |
| 42 | return; |
| 43 | } |
| 44 | |
| 45 | // Only one option, we have to go with it. |
| 46 | if (right_target.size() == 1 && left_target.size() == 1) { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 47 | *center_left = CreateCenterFromTarget( |
| 48 | left_target[0].first.x(), left_target[0].first.y(), |
| 49 | left_target[0].second.x(), left_target[0].second.y()); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 50 | *center_right = CreateCenterFromTarget( |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 51 | right_target[0].first.x(), right_target[0].first.y(), |
| 52 | right_target[0].second.x(), right_target[0].second.y()); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 53 | return; |
| 54 | } |
| 55 | |
| 56 | // Now we have to make a decision. |
| 57 | double min_angle = -1.0; |
| 58 | int left_index = 0; |
| 59 | // First pick the widest target from the left. |
| 60 | for (size_t i = 0; i < left_target.size(); i++) { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 61 | const double h = left_target[i].first.y() - left_target[i].second.y(); |
| 62 | const double wid1 = |
| 63 | TargetWidth(left_target[i].first.x(), left_target[i].first.y(), |
| 64 | left_target[i].second.x(), left_target[i].second.y()); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 65 | const double angle = h / wid1; |
| 66 | if (min_angle == -1.0 || ::std::abs(angle) < ::std::abs(min_angle)) { |
| 67 | min_angle = angle; |
| 68 | left_index = i; |
| 69 | } |
| 70 | } |
| 71 | // Calculate the angle of the bottom edge for the left. |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 72 | double h = |
| 73 | left_target[left_index].first.y() - left_target[left_index].second.y(); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 74 | |
| 75 | double good_ang = min_angle; |
| 76 | double min_ang_err = -1.0; |
| 77 | int right_index = -1; |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 78 | // Now pick the bottom edge angle from the right that lines up best with the |
| 79 | // left. |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 80 | for (size_t j = 0; j < right_target.size(); j++) { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 81 | double wid2 = |
| 82 | TargetWidth(right_target[j].first.x(), right_target[j].first.y(), |
| 83 | right_target[j].second.x(), right_target[j].second.y()); |
| 84 | h = right_target[j].first.y() - right_target[j].second.y(); |
| 85 | double ang = h / wid2; |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 86 | double ang_err = ::std::abs(good_ang - ang); |
| 87 | if (min_ang_err == -1.0 || min_ang_err > ang_err) { |
| 88 | min_ang_err = ang_err; |
| 89 | right_index = j; |
| 90 | } |
| 91 | } |
| 92 | |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 93 | *center_left = CreateCenterFromTarget( |
| 94 | left_target[left_index].first.x(), left_target[left_index].first.y(), |
| 95 | left_target[left_index].second.x(), left_target[left_index].second.y()); |
| 96 | *center_right = CreateCenterFromTarget(right_target[right_index].first.x(), |
| 97 | right_target[right_index].first.y(), |
| 98 | right_target[right_index].second.x(), |
| 99 | right_target[right_index].second.y()); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 100 | } |
| 101 | |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 102 | long GetFileSize(std::string filename) { |
| 103 | struct stat stat_buf; |
| 104 | int rc = stat(filename.c_str(), &stat_buf); |
| 105 | return rc == 0 ? stat_buf.st_size : -1; |
| 106 | } |
| 107 | |
| 108 | class OutputFile { |
| 109 | public: |
| 110 | OutputFile(const std::string &fname) : ofs(fname, std::ofstream::out) {} |
| 111 | |
| 112 | void Emit(const BlobList &blobl, int64_t timestamp) { |
| 113 | int tmp_size = CalculateSize(blobl) + sizeof(int32_t) + sizeof(uint64_t); |
| 114 | tmp_buf.resize(tmp_size, 0); |
| 115 | { |
| 116 | char *buf = Int64Codec::Write(&tmp_buf[0], tmp_size); |
| 117 | buf = Int64Codec::Write(buf, timestamp); |
| 118 | SerializeBlob(blobl, buf); |
| 119 | } |
| 120 | ofs.write(&tmp_buf[0], tmp_size); |
| 121 | printf("blob_size: %d\n", tmp_size); |
| 122 | } |
| 123 | |
| 124 | std::vector<char> tmp_buf; |
| 125 | |
| 126 | std::ofstream ofs; |
| 127 | }; |
| 128 | |
| 129 | class InputFile { |
| 130 | public: |
| 131 | InputFile(const std::string &fname) |
| 132 | : ifs_(fname, std::ifstream::in), len_(GetFileSize(fname)) { |
| 133 | if (len_ <= 0) { |
| 134 | printf("File (%s) not found. Size (%d)\n", fname.c_str(), (int)len_); |
| 135 | fflush(stdout); |
| 136 | } |
| 137 | assert(len_ > 0); |
| 138 | tmp_buf_.resize(len_, 0); |
| 139 | ifs_.read(&tmp_buf_[0], len_); |
| 140 | buf_ = &tmp_buf_[0]; |
| 141 | } |
| 142 | |
| 143 | bool ReadNext(BlobList *blob_list, uint64_t *timestamp) { |
| 144 | if (buf_ - &tmp_buf_[0] >= len_) return false; |
| 145 | if (prev_ != nullptr) prev_frames_.emplace_back(prev_); |
| 146 | prev_ = buf_; |
| 147 | buf_ += sizeof(uint32_t); |
| 148 | *timestamp = Int64Codec::Read(&buf_); |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 149 | // auto* buf_tmp = buf_; |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 150 | buf_ = ParseBlobList(blob_list, buf_); |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 151 | // fprintf(stderr, "read frame: %lu, buf_size: %lu\n", *timestamp, buf_ - |
| 152 | // buf_tmp); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 153 | return true; |
| 154 | } |
| 155 | |
| 156 | bool ReadPrev(BlobList *blob_list, uint64_t *timestamp) { |
| 157 | if (prev_frames_.empty()) return false; |
| 158 | buf_ = prev_frames_.back(); |
| 159 | prev_frames_.pop_back(); |
| 160 | buf_ += sizeof(uint32_t); |
| 161 | *timestamp = Int64Codec::Read(&buf_); |
| 162 | buf_ = ParseBlobList(blob_list, buf_); |
| 163 | prev_ = nullptr; |
| 164 | return true; |
| 165 | } |
| 166 | |
| 167 | private: |
| 168 | std::vector<const char *> prev_frames_; |
| 169 | const char *buf_; |
| 170 | const char *prev_ = nullptr; |
| 171 | std::ifstream ifs_; |
| 172 | |
| 173 | long len_; |
| 174 | std::vector<char> tmp_buf_; |
| 175 | }; |
| 176 | |
| 177 | class BlobStreamFrame { |
| 178 | public: |
| 179 | BlobList blob_list; |
| 180 | uint64_t timestamp; |
| 181 | void ReadNext(InputFile *fin) { |
| 182 | blob_list.clear(); |
| 183 | if (!fin->ReadNext(&blob_list, ×tamp)) { |
| 184 | exit(0); |
| 185 | return; |
| 186 | } |
| 187 | } |
| 188 | bool ReadPrev(InputFile *fin) { |
| 189 | blob_list.clear(); |
| 190 | return fin->ReadPrev(&blob_list, ×tamp); |
| 191 | } |
| 192 | }; |
| 193 | |
| 194 | const char *kHudText = |
| 195 | "commands:\n" |
| 196 | " SPACE - pause\n" |
| 197 | " c - continue to next target\n" |
| 198 | " s - single step while paused\n" |
| 199 | " k - pause on next target frame\n" |
| 200 | " u - change window scaling\n" |
| 201 | " a - single step backward\n" |
| 202 | " q - quit\n" |
| 203 | " h - help\n"; |
| 204 | |
| 205 | class NetworkForwardingImageStream : public aos::events::EpollWait { |
| 206 | public: |
| 207 | NetworkForwardingImageStream(ImageFormat fmt, int debug_level, |
| 208 | const std::string &fname1, |
| 209 | const std::string &fname2) |
| 210 | : fmt_(fmt), |
| 211 | ifs1_(fname1), |
| 212 | ifs2_(fname2), |
| 213 | blob_filt_(fmt, 40, 750, 250000), |
| 214 | finder_(0.25, 35) { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 215 | text_overlay_.draw_fn = [this](RenderInterface *render, double /*width*/, |
| 216 | double /*height*/) { |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 217 | render->SetSourceRGB(1.0, 1.0, 1.0); |
| 218 | if (hud_text) render->Text(20, 20, 0, 0, kHudText); |
| 219 | }; |
| 220 | |
| 221 | overlays_.push_back(&overlay_); |
| 222 | overlays_.push_back(&text_overlay_); |
| 223 | view_.view()->SetOverlays(&overlays_); |
| 224 | |
| 225 | if (debug_level > 0) { |
| 226 | finder_.EnableOverlay(&overlay_); |
| 227 | } |
| 228 | if (debug_level > 1) { |
| 229 | blob_filt_.EnableOverlay(&overlay_); |
| 230 | } |
| 231 | |
| 232 | frame1.ReadNext(&ifs1_); |
| 233 | frame2.ReadNext(&ifs2_); |
| 234 | |
| 235 | std::pair<int, int> skip = |
| 236 | TickFrame(std::max(frame1.timestamp, frame2.timestamp)); |
| 237 | printf("Initialzation skipped (%d, %d)\n", skip.first, skip.second); |
| 238 | |
| 239 | ms_event_delta_ = 20; |
| 240 | play_forward = true; |
| 241 | paused = false; |
| 242 | single_step = false; |
| 243 | pause_on_next_target = true; |
| 244 | continue_to_next_target = false; |
| 245 | view_.view()->SetScale(scale_factor); |
| 246 | view_.view()->key_press_event = [this](uint32_t keyval) { |
| 247 | play_forward = true; |
| 248 | switch (keyval) { |
| 249 | case GDK_KEY_space: |
| 250 | paused = !paused; |
| 251 | pause_on_next_target = false; |
| 252 | continue_to_next_target = false; |
| 253 | break; |
| 254 | case GDK_KEY_c: |
| 255 | pause_on_next_target = true; |
| 256 | continue_to_next_target = true; |
| 257 | paused = false; |
| 258 | break; |
| 259 | case GDK_KEY_s: |
| 260 | single_step = true; |
| 261 | continue_to_next_target = false; |
| 262 | paused = true; |
| 263 | break; |
| 264 | case GDK_KEY_k: |
| 265 | pause_on_next_target = true; |
| 266 | continue_to_next_target = false; |
| 267 | paused = false; |
| 268 | break; |
| 269 | case GDK_KEY_u: |
| 270 | if (scale_factor == 1.0) { |
| 271 | scale_factor = 0.75; |
| 272 | view_.view()->SetScale(0.75); |
| 273 | } else { |
| 274 | scale_factor = 1.0; |
| 275 | view_.view()->SetScale(1.0); |
| 276 | view_.view()->MoveTo(150, -220); |
| 277 | } |
| 278 | break; |
| 279 | case GDK_KEY_a: |
| 280 | play_forward = false; |
| 281 | single_step = true; |
| 282 | paused = true; |
| 283 | break; |
| 284 | case GDK_KEY_q: |
| 285 | exit(0); |
| 286 | case GDK_KEY_h: |
| 287 | hud_text = !hud_text; |
| 288 | break; |
| 289 | default: |
| 290 | printf("pressed: %s\n", gdk_keyval_name(keyval)); |
| 291 | } |
| 292 | }; |
| 293 | } |
| 294 | |
| 295 | double scale_factor = 1.0; |
| 296 | bool hud_text = true; |
| 297 | bool play_forward; |
| 298 | bool paused; |
| 299 | bool single_step; |
| 300 | bool pause_on_next_target; |
| 301 | bool continue_to_next_target; |
| 302 | |
| 303 | std::string distance_text; |
| 304 | |
| 305 | std::pair<int, int> TickFrame(uint64_t time) { |
| 306 | timestamp_ += time; |
| 307 | return TickToFrame(timestamp_); |
| 308 | } |
| 309 | |
| 310 | std::pair<int, int> TickBackFrame(uint64_t time) { |
| 311 | timestamp_ -= time; |
| 312 | return TickBackToFrame(timestamp_); |
| 313 | } |
| 314 | |
| 315 | std::pair<int, int> TickToFrame(uint64_t timestamp) { |
| 316 | std::pair<int, int> skip(0, 0); |
| 317 | while (frame1.timestamp < timestamp) { |
| 318 | frame1.ReadNext(&ifs1_); |
| 319 | skip.first++; |
| 320 | } |
| 321 | while (frame2.timestamp < timestamp) { |
| 322 | frame2.ReadNext(&ifs2_); |
| 323 | skip.second++; |
| 324 | } |
| 325 | return skip; |
| 326 | } |
| 327 | |
| 328 | std::pair<int, int> TickBackToFrame(uint64_t timestamp) { |
| 329 | std::pair<int, int> skip(0, 0); |
| 330 | while (frame1.timestamp >= timestamp) { |
| 331 | if (!frame1.ReadPrev(&ifs1_)) break; |
| 332 | skip.first++; |
| 333 | } |
| 334 | while (frame2.timestamp >= timestamp) { |
| 335 | if (!frame2.ReadPrev(&ifs2_)) break; |
| 336 | skip.second++; |
| 337 | } |
| 338 | frame1.ReadPrev(&ifs1_); |
| 339 | frame2.ReadPrev(&ifs2_); |
| 340 | return skip; |
| 341 | } |
| 342 | BlobStreamFrame frame1; |
| 343 | BlobStreamFrame frame2; |
| 344 | uint64_t timestamp_ = 0; |
| 345 | |
| 346 | Vector<2> GetCenter(const BlobList &blob_list) { |
| 347 | std::vector<std::pair<Vector<2>, Vector<2>>> corners = |
| 348 | finder_.Find(blob_filt_.FilterBlobs(blob_list)); |
| 349 | |
| 350 | if (corners.size() == 1) { |
| 351 | Vector<2> center = (corners[0].first + corners[0].second) * (0.5); |
| 352 | return center; |
| 353 | } |
| 354 | return {0, 0}; |
| 355 | } |
| 356 | |
| 357 | void DrawSuperSpeed() { |
| 358 | PixelRef color = {0, 255, 255}; |
| 359 | // S |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 360 | overlay_.AddLine(Vector<2>(200, 100), Vector<2>(100, 100), color); |
| 361 | overlay_.AddLine(Vector<2>(100, 100), Vector<2>(100, 300), color); |
| 362 | overlay_.AddLine(Vector<2>(100, 300), Vector<2>(200, 300), color); |
| 363 | overlay_.AddLine(Vector<2>(200, 300), Vector<2>(200, 500), color); |
| 364 | overlay_.AddLine(Vector<2>(200, 500), Vector<2>(100, 500), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 365 | // U |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 366 | overlay_.AddLine(Vector<2>(250, 100), Vector<2>(250, 500), color); |
| 367 | overlay_.AddLine(Vector<2>(250, 500), Vector<2>(350, 500), color); |
| 368 | overlay_.AddLine(Vector<2>(350, 500), Vector<2>(350, 100), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 369 | // P |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 370 | overlay_.AddLine(Vector<2>(400, 100), Vector<2>(400, 500), color); |
| 371 | overlay_.AddLine(Vector<2>(400, 100), Vector<2>(500, 100), color); |
| 372 | overlay_.AddLine(Vector<2>(500, 100), Vector<2>(500, 300), color); |
| 373 | overlay_.AddLine(Vector<2>(500, 300), Vector<2>(400, 300), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 374 | // E |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 375 | overlay_.AddLine(Vector<2>(550, 100), Vector<2>(550, 500), color); |
| 376 | overlay_.AddLine(Vector<2>(550, 100), Vector<2>(650, 100), color); |
| 377 | overlay_.AddLine(Vector<2>(550, 300), Vector<2>(650, 300), color); |
| 378 | overlay_.AddLine(Vector<2>(550, 500), Vector<2>(650, 500), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 379 | // R |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 380 | overlay_.AddLine(Vector<2>(700, 100), Vector<2>(700, 500), color); |
| 381 | overlay_.AddLine(Vector<2>(700, 100), Vector<2>(800, 100), color); |
| 382 | overlay_.AddLine(Vector<2>(800, 100), Vector<2>(800, 300), color); |
| 383 | overlay_.AddLine(Vector<2>(800, 300), Vector<2>(700, 300), color); |
| 384 | overlay_.AddLine(Vector<2>(700, 350), Vector<2>(800, 500), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 385 | // S |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 386 | overlay_.AddLine(Vector<2>(200, 550), Vector<2>(100, 550), color); |
| 387 | overlay_.AddLine(Vector<2>(100, 550), Vector<2>(100, 750), color); |
| 388 | overlay_.AddLine(Vector<2>(100, 750), Vector<2>(200, 750), color); |
| 389 | overlay_.AddLine(Vector<2>(200, 750), Vector<2>(200, 950), color); |
| 390 | overlay_.AddLine(Vector<2>(200, 950), Vector<2>(100, 950), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 391 | // P |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 392 | overlay_.AddLine(Vector<2>(250, 550), Vector<2>(250, 950), color); |
| 393 | overlay_.AddLine(Vector<2>(250, 550), Vector<2>(350, 550), color); |
| 394 | overlay_.AddLine(Vector<2>(350, 550), Vector<2>(350, 750), color); |
| 395 | overlay_.AddLine(Vector<2>(350, 750), Vector<2>(250, 750), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 396 | // E |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 397 | overlay_.AddLine(Vector<2>(400, 550), Vector<2>(400, 950), color); |
| 398 | overlay_.AddLine(Vector<2>(400, 550), Vector<2>(500, 550), color); |
| 399 | overlay_.AddLine(Vector<2>(400, 750), Vector<2>(500, 750), color); |
| 400 | overlay_.AddLine(Vector<2>(400, 950), Vector<2>(500, 950), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 401 | // E |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 402 | overlay_.AddLine(Vector<2>(550, 550), Vector<2>(550, 950), color); |
| 403 | overlay_.AddLine(Vector<2>(550, 550), Vector<2>(650, 550), color); |
| 404 | overlay_.AddLine(Vector<2>(550, 750), Vector<2>(650, 750), color); |
| 405 | overlay_.AddLine(Vector<2>(550, 950), Vector<2>(650, 950), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 406 | // D |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 407 | overlay_.AddLine(Vector<2>(700, 550), Vector<2>(700, 950), color); |
| 408 | overlay_.AddLine(Vector<2>(700, 550), Vector<2>(800, 575), color); |
| 409 | overlay_.AddLine(Vector<2>(800, 575), Vector<2>(800, 925), color); |
| 410 | overlay_.AddLine(Vector<2>(800, 925), Vector<2>(700, 950), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 411 | } |
| 412 | |
| 413 | void UpdateNewTime(int new_delta) { |
| 414 | if (new_delta != ms_event_delta_) { |
| 415 | ms_event_delta_ = new_delta; |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 416 | SetTime(::std::chrono::milliseconds(ms_event_delta_) + |
| 417 | aos::monotonic_clock::now()); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 418 | } |
| 419 | } |
| 420 | |
| 421 | void Done() override { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 422 | SetTime(::std::chrono::milliseconds(ms_event_delta_) + |
| 423 | aos::monotonic_clock::now()); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 424 | if (paused && !single_step) return; |
| 425 | single_step = false; |
| 426 | frame_count_++; |
| 427 | |
| 428 | while (true) { |
| 429 | overlay_.Reset(); |
| 430 | view_.SetFormatAndClear(fmt_); |
| 431 | std::pair<int, int> skipped(1, 1); |
| 432 | // how far we will step to look for the next target |
| 433 | int nano_step = 300 * 1e6; |
| 434 | if (play_forward && seeking_target_) { |
| 435 | skipped = TickFrame(nano_step); |
| 436 | } else if (seeking_target_) { |
| 437 | skipped = TickBackFrame(nano_step); |
| 438 | } else if (play_forward) { |
| 439 | frame1.ReadNext(&ifs1_); |
| 440 | frame2.ReadNext(&ifs2_); |
| 441 | } else { |
| 442 | frame1.ReadPrev(&ifs1_); |
| 443 | frame2.ReadPrev(&ifs2_); |
| 444 | } |
| 445 | // printf("skipped (%d, %d)\n", skipped.first, skipped.second); |
| 446 | |
| 447 | std::vector<std::pair<Vector<2>, Vector<2>>> corner1 = |
| 448 | finder_.Find(blob_filt_.FilterBlobs(frame1.blob_list)); |
| 449 | std::vector<std::pair<Vector<2>, Vector<2>>> corner2 = |
| 450 | finder_.Find(blob_filt_.FilterBlobs(frame2.blob_list)); |
| 451 | |
| 452 | Vector<2> cent1; |
| 453 | Vector<2> cent2; |
| 454 | SelectTargets(corner1, corner2, ¢1, ¢2); |
| 455 | |
| 456 | /* |
| 457 | int target_count_; |
| 458 | if (cent1 == Vector<2>(0, 0) && cent2 == Vector<2>(0, 0)) { |
| 459 | missed_count_ += std::min(skipped.first, skipped.second); |
| 460 | if (missed_count_ > 15) { |
| 461 | seeking_target_ = true; |
| 462 | DrawSuperSpeed(); |
| 463 | SetTime(aos::vision::MsTime(1)); |
| 464 | if (line_break_) { |
| 465 | printf("_-_-_-%d_-_-_-_\n", target_count_); |
| 466 | target_count_++; |
| 467 | line_break_ = false; |
| 468 | } |
| 469 | if (continue_to_next_target) { |
| 470 | continue_to_next_target = false; |
| 471 | } |
| 472 | continue; |
| 473 | } |
| 474 | } else { |
| 475 | missed_count_ = 0; |
| 476 | } |
| 477 | */ |
| 478 | |
| 479 | if (seeking_target_) { |
| 480 | if (play_forward) { |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 481 | // Go back to the last time we didn't see a target and play from |
| 482 | // there. |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 483 | TickBackFrame(nano_step); |
| 484 | seeking_target_ = false; |
| 485 | } else if (seeking_target_) { |
| 486 | TickFrame(nano_step); |
| 487 | seeking_target_ = false; |
| 488 | } |
| 489 | continue; |
| 490 | } |
| 491 | |
| 492 | // comment out to turn off full blob drawing |
| 493 | view_.DrawBlobList(frame1.blob_list, {0, 0, 255}); |
| 494 | view_.DrawSecondBlobList(frame2.blob_list, {0, 255, 0}, {0, 255, 255}); |
| 495 | |
| 496 | DrawCross(overlay_, Vector<2>(fmt_.w / 2.0, fmt_.h / 2.0), {255, 0, 0}); |
| 497 | |
| 498 | double timeFromEpoch = |
| 499 | 1e-9 * ((double)frame1.timestamp + (double)frame2.timestamp) / 2; |
| 500 | printf("timestamp: %g skew: %g\n", timeFromEpoch, |
| 501 | 1e-9 * ((double)frame1.timestamp - (double)frame2.timestamp)); |
| 502 | /* |
| 503 | if (cent1 == Vector<2>(0, 0) && cent2 == Vector<2>(0, 0)) { |
| 504 | } else { |
| 505 | DrawCross(overlay_, cent1, {255, 255, 255}); |
| 506 | DrawCross(overlay_, cent2, {255, 255, 255}); |
| 507 | double x = (cent1.x() + cent2.x()) / 2.0; |
| 508 | DrawCross(overlay_, Vector<2>(x, fmt_.h / 2.0), {255, 255, 255}); |
| 509 | SetTime(aos::vision::MsTime(100)); |
| 510 | if (pause_on_next_target && !continue_to_next_target) { |
| 511 | paused = true; |
| 512 | pause_on_next_target = false; |
| 513 | } |
| 514 | line_break_ = true; |
| 515 | missed_count_ = 0; |
| 516 | } |
| 517 | fflush(stdout); |
| 518 | */ |
| 519 | view_.view()->Redraw(); |
| 520 | break; |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | void DrawCross(PixelLinesOverlay &overlay, Vector<2> center, PixelRef color) { |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 525 | overlay.AddLine(Vector<2>(center.x() - 25, center.y()), |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 526 | Vector<2>(center.x() + 25, center.y()), color); |
Parker Schuh | 24ee58d | 2017-03-11 16:13:23 -0800 | [diff] [blame] | 527 | overlay.AddLine(Vector<2>(center.x(), center.y() - 25), |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 528 | Vector<2>(center.x(), center.y() + 25), color); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 529 | } |
| 530 | |
| 531 | void AddTo(aos::events::EpollLoop *loop) { |
| 532 | Done(); |
| 533 | loop->AddWait(this); |
| 534 | } |
| 535 | |
| 536 | std::unique_ptr<PixelRef[]> outbuf; |
| 537 | ImagePtr ptr; |
| 538 | |
| 539 | BlobStreamViewer view_; |
| 540 | |
| 541 | private: |
| 542 | int ms_event_delta_ = 200; |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 543 | |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 544 | public: |
| 545 | // basic image size |
| 546 | ImageFormat fmt_; |
| 547 | |
| 548 | // where we darw for debugging |
| 549 | PixelLinesOverlay overlay_; |
| 550 | |
| 551 | // Where we draw text on the screen. |
| 552 | LambdaOverlay text_overlay_; |
| 553 | // container for viewer |
| 554 | std::vector<OverlayBase *> overlays_; |
| 555 | |
| 556 | InputFile ifs1_; |
| 557 | InputFile ifs2_; |
| 558 | |
| 559 | // our blob processing object |
| 560 | HistogramBlobFilter blob_filt_; |
| 561 | |
| 562 | // corner finder to align aiming |
| 563 | CornerFinder finder_; |
| 564 | |
| 565 | // indicates we have lost a target |
| 566 | bool line_break_ = false; |
| 567 | |
| 568 | // indicates we are looking for the next target |
| 569 | bool seeking_target_ = false; |
| 570 | |
| 571 | int frame_count_ = 0; |
| 572 | |
| 573 | // count how many frames we miss in a row. |
| 574 | int missed_count_ = 16; |
| 575 | }; |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 576 | } // namespace vision |
| 577 | } // namespace y2016 |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 578 | |
| 579 | int main(int argc, char *argv[]) { |
| 580 | using namespace y2016::vision; |
| 581 | aos::events::EpollLoop loop; |
| 582 | gtk_init(&argc, &argv); |
| 583 | |
| 584 | if (argc != 3) { |
| 585 | printf("Wrong number of arguments. Got (%d) expected 3.\n", argc); |
| 586 | printf( |
| 587 | " arguments are debug level as {0, 1, 2} and then filename without the " |
| 588 | "{_0.dat,_1.dat} suffixes\n"); |
| 589 | } |
| 590 | |
| 591 | int dbg = std::stoi(argv[1]); |
| 592 | |
| 593 | std::string file(argv[2]); |
| 594 | aos::vision::ImageFormat fmt = {640 * 2, 480 * 2}; |
| 595 | |
| 596 | printf("file (%s) dbg_lvl (%d)\n", file.c_str(), dbg); |
| 597 | |
| 598 | std::string fname_path = file; |
Tyler Chatow | bf0609c | 2021-07-31 16:13:27 -0700 | [diff] [blame^] | 599 | NetworkForwardingImageStream strm1(fmt, dbg, fname_path + "_0.dat", |
| 600 | fname_path + "_1.dat"); |
Parker Schuh | d7db83d | 2017-02-08 20:49:15 -0800 | [diff] [blame] | 601 | fprintf(stderr, "staring main\n"); |
| 602 | strm1.AddTo(&loop); |
| 603 | |
| 604 | fprintf(stderr, "staring main\n"); |
| 605 | loop.RunWithGtkMain(); |
| 606 | } |