blob: 770eefd3fffba3a344e211ac46f62e5452bdcbc6 [file] [log] [blame]
Parker Schuh90641112017-02-25 12:18:36 -08001#include "aos/vision/debug/debug_framework.h"
2
3#include <gtk/gtk.h>
4
John Park33858a32018-09-28 23:05:48 -07005#include "aos/logging/implementations.h"
6#include "aos/logging/logging.h"
Parker Schuh90641112017-02-25 12:18:36 -08007#include "aos/vision/blob/find_blob.h"
8#include "aos/vision/blob/stream_view.h"
Parker Schuh90641112017-02-25 12:18:36 -08009#include "aos/vision/events/epoll_events.h"
10#include "aos/vision/image/jpeg_routines.h"
11
Stephan Pleinesf63bde82024-01-13 15:59:33 -080012namespace aos::vision {
Parker Schuh90641112017-02-25 12:18:36 -080013
Parker Schuhcd258b82017-04-09 16:28:29 -070014// Detect screen height on smaller monitors.
15int GetScreenHeight() {
16 fprintf(stderr, "gtk version_info: %d.%d.%d\n", gtk_get_major_version(),
17 gtk_get_minor_version(), gtk_get_micro_version());
18
19 GdkScreen *screen = gdk_screen_get_default();
20 GdkRectangle dimensions;
21// Deprecated in newer versions of GTK and missing from older versions.
22#if GTK_CHECK_VERSION(3, 22, 7)
23 GdkDisplay *display = gdk_screen_get_display(screen);
24 GdkMonitor *monitor = gdk_display_get_primary_monitor(display);
25 gdk_monitor_get_geometry(monitor, &dimensions);
26#else
27 dimensions.height = gdk_screen_get_height(screen);
28 dimensions.width = gdk_screen_get_width(screen);
29#endif
30 fprintf(stdout, "Monitor dimensions: %dx%d\n", dimensions.width,
31 dimensions.height);
32 return dimensions.height;
33}
34
Parker Schuh90641112017-02-25 12:18:36 -080035bool DecodeJpeg(aos::vision::DataRef data,
36 aos::vision::BlobStreamViewer *view) {
37 auto fmt = aos::vision::GetFmt(data);
38 auto value = view->img();
39 if (!value.fmt().Equals(fmt)) {
40 view->SetFormatAndClear(fmt);
41 }
42 return aos::vision::ProcessJpeg(data, view->img().data());
43}
44
45class DebugFramework : public DebugFrameworkInterface {
46 public:
Parker Schuhcd258b82017-04-09 16:28:29 -070047 explicit DebugFramework(FilterHarness *filter, CameraParams camera_params)
48 : camera_params_(camera_params), filter_(filter) {
Parker Schuh90641112017-02-25 12:18:36 -080049 view_.key_press_event = [this](uint32_t keyval) {
50 for (const auto &event : key_press_events()) {
51 event(keyval);
52 }
53 };
54 filter->InstallViewer(&view_);
Parker Schuhcd258b82017-04-09 16:28:29 -070055 auto key_press = filter->RegisterKeyPress();
56 if (key_press) {
57 InstallKeyPress(key_press);
58 }
59 if (GetScreenHeight() < 1024) {
Parker Schuh02f13f62019-02-16 16:42:41 -080060 view_.SetScale(1.0);
Parker Schuhcd258b82017-04-09 16:28:29 -070061 }
Alex Perry5b1e8e32019-04-07 13:25:31 -070062
63 // Pass along the set exposure so that users can acceess it.
Austin Schuha0c41ba2020-09-10 22:59:14 -070064 filter->InstallSetExposure(
65 [this](uint32_t abs_exp) { this->SetExposure(abs_exp); });
Parker Schuh90641112017-02-25 12:18:36 -080066 }
67
68 // This the first stage in the pipeline that takes
Parker Schuhcd258b82017-04-09 16:28:29 -070069 bool NewJpeg(DataRef data) override {
Parker Schuh90641112017-02-25 12:18:36 -080070 DecodeJpeg(data, &view_);
71
72 auto fmt = view_.img().fmt();
Parker Schuhcd258b82017-04-09 16:28:29 -070073 return HandleBlobs(FindBlobs(filter_->Threshold(view_.img())), fmt);
Parker Schuh90641112017-02-25 12:18:36 -080074 }
75
Parker Schuh02f13f62019-02-16 16:42:41 -080076 bool NewImage(ImageFormat fmt,
77 const std::function<bool(ImagePtr data)> &process) override {
78 auto value = view_.img();
79 if (!value.fmt().Equals(fmt)) {
80 view_.SetFormatAndClear(fmt);
81 }
82 process(view_.img());
83
84 return HandleBlobs(FindBlobs(filter_->Threshold(view_.img())), fmt);
85 }
86
Parker Schuhcd258b82017-04-09 16:28:29 -070087 bool NewBlobList(BlobList blob_list, ImageFormat fmt) override {
Parker Schuh90641112017-02-25 12:18:36 -080088 view_.SetFormatAndClear(fmt);
89
Parker Schuhcd258b82017-04-09 16:28:29 -070090 return HandleBlobs(std::move(blob_list), fmt);
Parker Schuh90641112017-02-25 12:18:36 -080091 }
92
Parker Schuhcd258b82017-04-09 16:28:29 -070093 bool JustCheckForTarget(BlobList blob_list, ImageFormat fmt) override {
94 return filter_->JustCheckForTarget(std::move(blob_list), fmt);
95 }
96
97 bool HandleBlobs(BlobList blob_list, ImageFormat fmt) {
98 bool result = filter_->HandleBlobs(std::move(blob_list), fmt);
Parker Schuh90641112017-02-25 12:18:36 -080099 view_.Redraw();
Parker Schuhcd258b82017-04-09 16:28:29 -0700100 return result;
Parker Schuh90641112017-02-25 12:18:36 -0800101 }
102
103 aos::events::EpollLoop *Loop() override { return &loop_; }
104
Parker Schuhcd258b82017-04-09 16:28:29 -0700105 const CameraParams &camera_params() override { return camera_params_; }
106
107 BlobStreamViewer *viewer() override { return &view_; }
108
Parker Schuh90641112017-02-25 12:18:36 -0800109 private:
Parker Schuhcd258b82017-04-09 16:28:29 -0700110 CameraParams camera_params_;
Parker Schuh90641112017-02-25 12:18:36 -0800111 FilterHarness *filter_;
112 BlobStreamViewer view_;
113
114 aos::events::EpollLoop loop_;
115};
116
117std::unique_ptr<ImageSource> MakeImageSource(
118 const std::string &image_source_string,
119 DebugFrameworkInterface *interface) {
120 (void)interface;
121 // Each of the image_source strings is of the form format_type:format_spec
122 auto it = image_source_string.find(':');
123 if (it == std::string::npos) {
124 fprintf(stderr, "invalid ImageSource: %s.\n", image_source_string.c_str());
125 exit(-1);
126 }
127 auto image_source_type = image_source_string.substr(0, it);
128 // Get std::function<std::unique_ptr<ImageSource>()> from the registration
129 // factory.
130 const auto &factory = ImageSourceGlobalFactory::Get(image_source_type);
131 if (!factory) {
132 fprintf(stderr, "invalid ImageSource: %s.\n", image_source_string.c_str());
133 exit(-1);
134 }
135 auto result = factory();
136 // Construct the image source.
137 result->Init(image_source_string.substr(it + 1), interface);
138 return result;
139}
140
141const char *kHelpMessage = R"(
142
143image_source is parsed out and selects where to get the images
144from. Each source type has a different configuration format string listed
145below. The colon separates the source specifier and the source config
146parameter. A single command line argument help will print this message.
147)";
148
Parker Schuhcd258b82017-04-09 16:28:29 -0700149void DebugFrameworkMain(int argc, char **argv, FilterHarness *filter,
150 CameraParams camera_params) {
Parker Schuh90641112017-02-25 12:18:36 -0800151 ::aos::logging::Init();
Parker Schuh90641112017-02-25 12:18:36 -0800152
153 gtk_init(&argc, &argv);
154
155 // Use fprintf because it is only supposed to be used interactively.
156 // This uses a registration system to pick out the individual file type
157 // registered by REGISTER_IMAGE_SOURCE.
158 // see jpeg_list-source.cc for ane sample of this.
159 if (argc < 2 || argv[1] == std::string("help")) {
160 fprintf(stderr, "Usage %s image_source:format_spec\n", argv[0]);
161 fprintf(stderr, "%s", kHelpMessage);
162 // Iterate through all registered entities in ImageSourceGlobalFactory
163 // and print out their individual help messages.
164 for (const auto &type : ImageSourceGlobalFactory::GetAll()) {
165 fprintf(stderr, " %s:\n", type.first.c_str());
166 fprintf(stderr, "%s", type.second()->GetHelpMessage());
167 }
168 exit(-1);
169 }
170
Parker Schuhcd258b82017-04-09 16:28:29 -0700171 DebugFramework replay(filter, camera_params);
Parker Schuh90641112017-02-25 12:18:36 -0800172
173 std::unique_ptr<ImageSource> image_source = MakeImageSource(argv[1], &replay);
174
175 replay.Loop()->RunWithGtkMain();
176}
177
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800178} // namespace aos::vision