blob: 5a842b7b6978919828f0104d096b38786810b364 [file] [log] [blame]
Parker Schuh24ee58d2017-03-11 16:13:23 -08001#include <sys/stat.h>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07002
3#include <cstdio>
4#include <cstdlib>
Parker Schuh2cd173d2017-01-28 00:12:01 -08005#include <fstream>
6#include <iostream>
7#include <memory>
8#include <thread>
9#include <vector>
10
John Park33858a32018-09-28 23:05:48 -070011#include "aos/time/time.h"
Parker Schuh2cd173d2017-01-28 00:12:01 -080012#include "aos/vision/events/socket_types.h"
13#include "aos/vision/events/udp.h"
14#include "aos/vision/image/image_stream.h"
15#include "aos/vision/image/jpeg_routines.h"
16#include "aos/vision/image/reader.h"
17#include "y2016/vision/blob_filters.h"
18#include "y2016/vision/stereo_geometry.h"
19#include "y2016/vision/vision_data.pb.h"
20
Stephan Pleinesf63bde82024-01-13 15:59:33 -080021namespace y2016::vision {
Parker Schuh2cd173d2017-01-28 00:12:01 -080022using aos::events::DataSocket;
Tyler Chatowbf0609c2021-07-31 16:13:27 -070023using aos::events::TCPServer;
24using aos::events::TXUdpSocket;
25using aos::vision::BlobList;
26using aos::vision::BlobLRef;
27using aos::vision::CornerFinder;
28using aos::vision::DataRef;
29using aos::vision::HistogramBlobFilter;
Parker Schuh2cd173d2017-01-28 00:12:01 -080030using aos::vision::ImageFormat;
Tyler Chatowbf0609c2021-07-31 16:13:27 -070031using aos::vision::ImageStreamEvent;
32using aos::vision::ImageValue;
33using aos::vision::Int32Codec;
34using aos::vision::Int64Codec;
35using aos::vision::PixelRef;
36using aos::vision::RangeImage;
37using aos::vision::Vector;
Parker Schuh2cd173d2017-01-28 00:12:01 -080038
Parker Schuh24ee58d2017-03-11 16:13:23 -080039::aos::vision::CameraParams GetCameraParams(const Calibration &calibration) {
40 ::aos::vision::CameraParams params;
41 params.set_width(calibration.camera_image_width());
42 params.set_height(calibration.camera_image_height());
43 params.set_exposure(calibration.camera_exposure());
44 params.set_brightness(calibration.camera_brightness());
45 params.set_gain(calibration.camera_gain());
46 params.set_fps(calibration.camera_fps());
47 return params;
Parker Schuh2cd173d2017-01-28 00:12:01 -080048}
49
50int64_t Nanos(aos::monotonic_clock::duration time_diff) {
51 return std::chrono::duration_cast<std::chrono::nanoseconds>(time_diff)
52 .count();
53}
54
55int64_t NowNanos() {
56 return Nanos(aos::monotonic_clock::now().time_since_epoch());
57}
58
59inline bool FileExist(const std::string &name) {
60 struct stat buffer;
61 return (stat(name.c_str(), &buffer) == 0);
62}
63
64class ImageSender : public ImageStreamEvent {
65 public:
Parker Schuh24ee58d2017-03-11 16:13:23 -080066 ImageSender(int camera_index, aos::vision::CameraParams params,
Parker Schuh2cd173d2017-01-28 00:12:01 -080067 const std::string &fname, const std::string &ipadder, int port)
68 : ImageStreamEvent(fname, params),
69 camera_index_(camera_index),
70 udp_serv_(ipadder, 8080),
71 tcp_serv_(port),
Parker Schuh24ee58d2017-03-11 16:13:23 -080072 blob_filt_(ImageFormat(params.width(), params.height()), 40, 750,
73 250000),
Parker Schuh2cd173d2017-01-28 00:12:01 -080074 finder_(0.25, 35) {
75 int index = 0;
76 while (true) {
77 std::string file = "./logging/blob_record_" + std::to_string(index) +
78 "_" + std::to_string(camera_index_) + ".dat";
79 if (FileExist(file)) {
80 index++;
81 } else {
82 printf("Logging to file (%s)\n", file.c_str());
83 ofst_.open(file);
84 assert(ofst_.is_open());
85 break;
86 }
87 }
88 }
89
90 ~ImageSender() { ofst_.close(); }
91
92 void ProcessImage(DataRef data, aos::monotonic_clock::time_point tp) {
93 int64_t timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
94 tp.time_since_epoch())
95 .count();
96 DecodeJpeg(data, &image_);
97 auto fmt = image_.fmt();
98
Brian Silverman37b15b32019-03-10 13:30:18 -070099 RangeImage rimg = ThresholdImageWithFunction(
100 image_.get(), [](PixelRef px) { return (px.g > 88); });
Parker Schuh2cd173d2017-01-28 00:12:01 -0800101
102 // flip the right image as this camera is mount backward
103 if (camera_index_ == 0) {
104 rimg.Flip(fmt.w, fmt.h);
105 }
106
107 BlobList blobl = aos::vision::FindBlobs(rimg);
108 auto whatever = blob_filt_.FilterBlobs(blobl);
109
110 VisionData target;
111 target.set_camera_index(camera_index_);
112 target.set_image_timestamp(timestamp);
113
114 if (!whatever.empty()) {
115 std::vector<std::pair<Vector<2>, Vector<2>>> corners =
116 finder_.Find(whatever);
117
118 if (!corners.empty()) {
119 for (int i = 0; i < (int)corners.size(); i++) {
120 Target *pos = target.add_target();
121 pos->set_left_corner_x(corners[i].first.x());
122 pos->set_left_corner_y(corners[i].first.y());
123 pos->set_right_corner_x(corners[i].second.x());
124 pos->set_right_corner_y(corners[i].second.y());
125 }
126 }
127 }
128 target.set_send_timestamp(NowNanos());
129
130 // always send data
131 std::string dat;
132 if (target.SerializeToString(&dat)) {
133 if (print_once_) {
134 printf("Beginning data streaming camera %d...\n", camera_index_);
135 print_once_ = false;
136 }
137
138 // Send only target over udp.
139 udp_serv_.Send(dat.data(), dat.size());
140 }
141
142 // Write blob to file for logging.
143 int blob_size = CalculateSize(blobl);
144 int tmp_size = blob_size + sizeof(int32_t) + sizeof(uint64_t);
145 char *buf;
146 blob_data_.resize(tmp_size, 0);
147 {
148 buf = Int32Codec::Write(&blob_data_[0], tmp_size);
149 buf = Int64Codec::Write(buf, timestamp);
150 SerializeBlob(blobl, buf);
151 }
152 ofst_.write(&blob_data_[0], tmp_size);
153
154 // Add blob debug
155 bool debug = true;
156 if (debug) {
157 target.set_raw(buf, blob_size);
158 if (target.SerializeToString(&dat)) {
159 tcp_serv_.Broadcast([&](DataSocket *client) { client->Emit(dat); });
160 }
161 }
162
163 bool timing = false;
164 if (timing) {
165 if (n_time > 0) {
166 auto now = aos::monotonic_clock::now();
167 printf("%g, %g\n",
168 (((double)Nanos(now - tstart)) / (double)(n_time)) / 1e6,
169 (double)Nanos(now - tp) / 1e6);
170 } else {
171 tstart = aos::monotonic_clock::now();
172 }
173 ++n_time;
174 }
175 }
176
177 TCPServer<DataSocket> *GetTCPServ() { return &tcp_serv_; }
178
179 // print when we start
180 bool print_once_ = true;
181
182 // left or right camera
183 int camera_index_;
184
185 // udp socket on which to send to robot
186 TXUdpSocket udp_serv_;
187
188 // tcp socket on which to debug to laptop
189 TCPServer<DataSocket> tcp_serv_;
190
191 // our blob processing object
192 HistogramBlobFilter blob_filt_;
193
194 // corner finder to align aiming
195 CornerFinder finder_;
196
197 ImageValue image_;
198 std::string blob_data_;
199 std::ofstream ofst_;
200 aos::monotonic_clock::time_point tstart;
201 int n_time = 0;
202
203 private:
204};
205
Parker Schuh24ee58d2017-03-11 16:13:23 -0800206void RunCamera(int camera_index, aos::vision::CameraParams params,
Parker Schuh2cd173d2017-01-28 00:12:01 -0800207 const std::string &device, const std::string &ip_addr,
208 int port) {
Parker Schuh24ee58d2017-03-11 16:13:23 -0800209 printf("Creating camera %d (%d, %d).\n", camera_index, params.width(),
210 params.height());
Parker Schuh2cd173d2017-01-28 00:12:01 -0800211 ImageSender strm(camera_index, params, device, ip_addr, port);
212
213 aos::events::EpollLoop loop;
214 loop.Add(strm.GetTCPServ());
215 loop.Add(&strm);
216 printf("Running Camera (%d)\n", camera_index);
217 loop.Run();
218}
219
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800220} // namespace y2016::vision
Parker Schuh2cd173d2017-01-28 00:12:01 -0800221
222int main(int, char **) {
223 using namespace y2016::vision;
224 StereoGeometry stereo("./stereo_rig.calib");
Parker Schuh2cd173d2017-01-28 00:12:01 -0800225 std::thread cam0([stereo]() {
226 RunCamera(0, GetCameraParams(stereo.calibration()),
227 stereo.calibration().right_camera_name(),
Parker Schuhef47dbf2017-03-04 16:59:30 -0800228 stereo.calibration().roborio_ip_addr(), 8080);
Parker Schuh2cd173d2017-01-28 00:12:01 -0800229 });
230 std::thread cam1([stereo]() {
231 RunCamera(1, GetCameraParams(stereo.calibration()),
232 stereo.calibration().left_camera_name(),
Parker Schuhef47dbf2017-03-04 16:59:30 -0800233 stereo.calibration().roborio_ip_addr(), 8080);
Parker Schuh2cd173d2017-01-28 00:12:01 -0800234 });
235 cam0.join();
236 cam1.join();
237
238 return EXIT_SUCCESS;
239}