blob: 649f1bbcf1eed9c316f6ec135b15d2f17bd5848c [file] [log] [blame]
James Kuszmaul77d536c2023-02-11 17:30:59 -08001#include "frc971/vision/foxglove_image_converter_lib.h"
2
James Kuszmaul0c593962023-01-28 16:04:20 -08003#include <opencv2/imgcodecs.hpp>
4#include <opencv2/imgproc.hpp>
5
James Kuszmaulacff22f2023-03-04 21:00:02 -08006DEFINE_int32(jpeg_quality, 60,
James Kuszmaul77d536c2023-02-11 17:30:59 -08007 "Compression quality of JPEGs, 0-100; lower numbers mean lower "
8 "quality and resulting image sizes.");
James Kuszmaul682daef2024-03-03 14:25:10 -08009DEFINE_uint32(max_period_ms, 100,
10 "Fastest period at which to convert images, to limit CPU usage.");
James Kuszmaul77d536c2023-02-11 17:30:59 -080011
James Kuszmaul0c593962023-01-28 16:04:20 -080012namespace frc971::vision {
James Kuszmaul0c593962023-01-28 16:04:20 -080013std::string_view ExtensionForCompression(ImageCompression compression) {
14 switch (compression) {
15 case ImageCompression::kJpeg:
16 return "jpeg";
17 case ImageCompression::kPng:
18 return "png";
19 }
20}
James Kuszmaul59a308f2023-01-28 19:14:07 -080021
James Kuszmaul0c593962023-01-28 16:04:20 -080022flatbuffers::Offset<foxglove::CompressedImage> CompressImage(
James Kuszmaul59a308f2023-01-28 19:14:07 -080023 const cv::Mat image, const aos::monotonic_clock::time_point eof,
24 flatbuffers::FlatBufferBuilder *fbb, ImageCompression compression) {
James Kuszmaul0c593962023-01-28 16:04:20 -080025 std::string_view format = ExtensionForCompression(compression);
26 // imencode doesn't let us pass in anything other than an std::vector, and
27 // performance isn't yet a big enough issue to try to avoid the copy.
28 std::vector<uint8_t> buffer;
James Kuszmaul77d536c2023-02-11 17:30:59 -080029 CHECK(cv::imencode(absl::StrCat(".", format), image, buffer,
30 {cv::IMWRITE_JPEG_QUALITY, FLAGS_jpeg_quality}));
James Kuszmaul0c593962023-01-28 16:04:20 -080031 const flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data_offset =
32 fbb->CreateVector(buffer);
James Kuszmaul59a308f2023-01-28 19:14:07 -080033 const struct timespec timestamp_t = aos::time::to_timespec(eof);
James Kuszmaul0c593962023-01-28 16:04:20 -080034 const foxglove::Time time{static_cast<uint32_t>(timestamp_t.tv_sec),
35 static_cast<uint32_t>(timestamp_t.tv_nsec)};
36 const flatbuffers::Offset<flatbuffers::String> format_offset =
37 fbb->CreateString(format);
38 foxglove::CompressedImage::Builder builder(*fbb);
39 builder.add_timestamp(&time);
40 builder.add_data(data_offset);
41 builder.add_format(format_offset);
42 return builder.Finish();
43}
44
45FoxgloveImageConverter::FoxgloveImageConverter(aos::EventLoop *event_loop,
46 std::string_view input_channel,
47 std::string_view output_channel,
48 ImageCompression compression)
49 : event_loop_(event_loop),
James Kuszmaul59a308f2023-01-28 19:14:07 -080050 image_callback_(
51 event_loop_, input_channel,
52 [this, compression](const cv::Mat image,
53 const aos::monotonic_clock::time_point eof) {
James Kuszmaul682daef2024-03-03 14:25:10 -080054 if (event_loop_->monotonic_now() >
55 (std::chrono::milliseconds(FLAGS_max_period_ms) +
56 sender_.monotonic_sent_time())) {
57 auto builder = sender_.MakeBuilder();
58 builder.CheckOk(builder.Send(
59 CompressImage(image, eof, builder.fbb(), compression)));
60 }
James Kuszmaul59a308f2023-01-28 19:14:07 -080061 }),
James Kuszmaul0c593962023-01-28 16:04:20 -080062 sender_(
James Kuszmaul59a308f2023-01-28 19:14:07 -080063 event_loop_->MakeSender<foxglove::CompressedImage>(output_channel)) {}
James Kuszmaul0c593962023-01-28 16:04:20 -080064} // namespace frc971::vision