blob: 930ec2efbcbafeacd576a405a774f29474d96bda [file] [log] [blame]
Jim Ostrowskic560cbe2020-03-07 00:29:30 -08001#include <map>
Jim Ostrowski23eb6582020-03-04 23:15:32 -08002#include <opencv2/calib3d.hpp>
3#include <opencv2/features2d.hpp>
4#include <opencv2/highgui/highgui.hpp>
5#include <opencv2/imgproc.hpp>
6
7#include "aos/events/shm_event_loop.h"
8#include "aos/init.h"
Jim Ostrowskibaa43692020-03-08 16:25:10 -07009#include "aos/time/time.h"
Jim Ostrowskic560cbe2020-03-07 00:29:30 -080010#include "y2020/vision/sift/sift_generated.h"
Jim Ostrowski23eb6582020-03-04 23:15:32 -080011#include "y2020/vision/vision_generated.h"
12
13DEFINE_string(config, "config.json", "Path to the config file to use.");
Austin Schuh69b2f792020-03-15 14:31:55 -070014DEFINE_string(channel, "/camera", "Channel name for the image.");
Jim Ostrowski23eb6582020-03-04 23:15:32 -080015
16namespace frc971 {
17namespace vision {
18namespace {
19
Jim Ostrowski834dddf2021-04-10 14:40:19 -070020struct TargetData {
21 float x;
22 float y;
23 float radius;
24};
Jim Ostrowskic560cbe2020-03-07 00:29:30 -080025
Jim Ostrowski834dddf2021-04-10 14:40:19 -070026std::map<int64_t, TargetData> target_data_map;
27std::map<int64_t, std::vector<TargetData>> feature_match_map;
28std::map<int64_t, std::vector<int>> feature_index_map;
29
30aos::Fetcher<CameraImage> image_fetcher;
31aos::Fetcher<sift::ImageMatchResult> match_fetcher;
32
33bool DisplayLoop() {
34 // Try to get target data
35 // TODO<Jim>: Could also parse (and show) matching features
36 if (match_fetcher.Fetch()) {
37 const sift::ImageMatchResult *match = match_fetcher.get();
38 CHECK(match != nullptr) << "Got null when trying to fetch match result";
39
40 int64_t timestamp = match->image_monotonic_timestamp_ns();
41 if (match->camera_poses() != NULL && match->camera_poses()->size() > 0) {
42 LOG(INFO) << "Got matches for timestamp " << timestamp << "\n";
43 TargetData target_data = {
44 match->camera_poses()->Get(0)->query_target_point_x(),
45 match->camera_poses()->Get(0)->query_target_point_y(),
46 match->camera_poses()->Get(0)->query_target_point_radius()};
47 target_data_map[timestamp] = target_data;
48 // Only keep last 10 matches
49 while (target_data_map.size() > 10u) {
50 target_data_map.erase(target_data_map.begin());
51 }
52 }
53 }
54
55 // Read latest image
56 if (!image_fetcher.Fetch()) {
57 return true;
58 }
59
60 const CameraImage *image = image_fetcher.get();
61 CHECK(image != nullptr) << "Couldn't read image";
62
63 // Create color image:
64 cv::Mat image_color_mat(cv::Size(image->cols(), image->rows()), CV_8UC2,
65 (void *)image->data()->data());
66 cv::Mat rgb_image(cv::Size(image->cols(), image->rows()), CV_8UC3);
67 cv::cvtColor(image_color_mat, rgb_image, CV_YUV2BGR_YUYV);
68
69 int64_t timestamp = image->monotonic_timestamp_ns();
70 auto target_it = target_data_map.find(timestamp);
71 if (target_it != target_data_map.end()) {
72 float x = target_it->second.x;
73 float y = target_it->second.y;
74 float radius = target_it->second.radius;
75 cv::circle(rgb_image, cv::Point2f(x, y), radius, cv::Scalar(0, 255, 0), 5);
76 }
77
78 cv::imshow("Display", rgb_image);
79 int keystroke = cv::waitKey(1);
80 if ((keystroke & 0xFF) == static_cast<int>('c')) {
81 // Convert again, to get clean image
82 cv::cvtColor(image_color_mat, rgb_image, CV_YUV2BGR_YUYV);
83 std::stringstream name;
84 name << "capture-" << aos::realtime_clock::now() << ".png";
85 cv::imwrite(name.str(), rgb_image);
86 LOG(INFO) << "Saved image file: " << name.str();
87 } else if ((keystroke & 0xFF) == static_cast<int>('q')) {
88 return false;
89 }
90 return true;
91}
92
93void ViewerMain() {
Jim Ostrowskic560cbe2020-03-07 00:29:30 -080094 std::map<int64_t, TargetData> target_data_map;
95
Jim Ostrowski23eb6582020-03-04 23:15:32 -080096 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
97 aos::configuration::ReadConfig(FLAGS_config);
98
99 aos::ShmEventLoop event_loop(&config.message());
100
Jim Ostrowski834dddf2021-04-10 14:40:19 -0700101 image_fetcher = event_loop.MakeFetcher<CameraImage>(FLAGS_channel);
Jim Ostrowski23eb6582020-03-04 23:15:32 -0800102
Jim Ostrowski834dddf2021-04-10 14:40:19 -0700103 match_fetcher = event_loop.MakeFetcher<sift::ImageMatchResult>(FLAGS_channel);
Jim Ostrowskibaa43692020-03-08 16:25:10 -0700104
Jim Ostrowski834dddf2021-04-10 14:40:19 -0700105 // Run the display loop
106 event_loop.AddPhasedLoop(
107 [&event_loop](int) {
108 if (!DisplayLoop()) {
109 LOG(INFO) << "Calling event_loop Exit";
110 event_loop.Exit();
111 };
112 },
113 ::std::chrono::milliseconds(100));
Jim Ostrowski23eb6582020-03-04 23:15:32 -0800114
115 event_loop.Run();
116}
117
118} // namespace
119} // namespace vision
120} // namespace frc971
121
122// Quick and lightweight grayscale viewer for images
123int main(int argc, char **argv) {
124 aos::InitGoogle(&argc, &argv);
125 frc971::vision::ViewerMain();
126}