blob: 68495b15c7a9e5dc976ef5359a9d4798900c41a1 [file] [log] [blame]
Austin Schuhdb2ed9d2022-12-26 14:02:26 -08001#include <opencv2/highgui/highgui.hpp>
2#include <opencv2/imgproc.hpp>
3
Ravago Jones17e13a22023-01-28 17:12:11 -08004#include "absl/strings/match.h"
Austin Schuhdb2ed9d2022-12-26 14:02:26 -08005#include "aos/events/shm_event_loop.h"
6#include "aos/init.h"
Ravago Jones17e13a22023-01-28 17:12:11 -08007#include "aos/json_to_flatbuffer.h"
Austin Schuhdb2ed9d2022-12-26 14:02:26 -08008#include "aos/time/time.h"
9#include "frc971/vision/vision_generated.h"
10
11DEFINE_string(config, "aos_config.json", "Path to the config file to use.");
12DEFINE_string(channel, "/camera", "Channel name for the image.");
13
14DEFINE_string(capture, "",
15 "If set, capture a single image and save it to this filename.");
16
Austin Schuhceb96542023-02-04 11:43:33 -080017DEFINE_int32(rate, 100, "Time in milliseconds to wait between images");
18
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080019namespace frc971 {
20namespace vision {
21namespace {
22
23aos::Fetcher<CameraImage> image_fetcher;
24bool DisplayLoop() {
25 const CameraImage *image;
26
27 // Read next image
28 if (!image_fetcher.Fetch()) {
29 VLOG(2) << "Couldn't fetch next image";
30 return true;
31 }
32
33 image = image_fetcher.get();
34 CHECK(image != nullptr) << "Couldn't read image";
35
36 // Create color image:
37 cv::Mat image_color_mat(cv::Size(image->cols(), image->rows()), CV_8UC2,
38 (void *)image->data()->data());
39 cv::Mat bgr_image(cv::Size(image->cols(), image->rows()), CV_8UC3);
40 cv::cvtColor(image_color_mat, bgr_image, cv::COLOR_YUV2BGR_YUYV);
41
42 if (!FLAGS_capture.empty()) {
Ravago Jones17e13a22023-01-28 17:12:11 -080043 if (absl::EndsWith(FLAGS_capture, ".bfbs")) {
44 aos::WriteFlatbufferToFile(FLAGS_capture, image_fetcher.CopyFlatBuffer());
45 } else {
46 cv::imwrite(FLAGS_capture, bgr_image);
47 }
48
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080049 return false;
50 }
51
52 cv::imshow("Display", bgr_image);
53 int keystroke = cv::waitKey(1);
54 if ((keystroke & 0xFF) == static_cast<int>('c')) {
55 // Convert again, to get clean image
56 cv::cvtColor(image_color_mat, bgr_image, cv::COLOR_YUV2BGR_YUYV);
57 std::stringstream name;
58 name << "capture-" << aos::realtime_clock::now() << ".png";
59 cv::imwrite(name.str(), bgr_image);
60 LOG(INFO) << "Saved image file: " << name.str();
61 } else if ((keystroke & 0xFF) == static_cast<int>('q')) {
62 return false;
63 }
64 return true;
65}
66
67void ViewerMain() {
68 aos::FlatbufferDetachedBuffer<aos::Configuration> config =
69 aos::configuration::ReadConfig(FLAGS_config);
70
71 aos::ShmEventLoop event_loop(&config.message());
72
73 image_fetcher = event_loop.MakeFetcher<CameraImage>(FLAGS_channel);
74
75 // Run the display loop
76 event_loop.AddPhasedLoop(
77 [&event_loop](int) {
78 if (!DisplayLoop()) {
79 LOG(INFO) << "Calling event_loop Exit";
80 event_loop.Exit();
81 };
82 },
Austin Schuhceb96542023-02-04 11:43:33 -080083 ::std::chrono::milliseconds(FLAGS_rate));
Austin Schuhdb2ed9d2022-12-26 14:02:26 -080084
85 event_loop.Run();
86
87 image_fetcher = aos::Fetcher<CameraImage>();
88}
89
90} // namespace
91} // namespace vision
92} // namespace frc971
93
94int main(int argc, char **argv) {
95 aos::InitGoogle(&argc, &argv);
96 frc971::vision::ViewerMain();
97}