blob: f5ecb407a290f01500319c2eb4a8d65ba6a3a537 [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 Kuszmaul77d536c2023-02-11 17:30:59 -08006DEFINE_int32(jpeg_quality, 95,
7 "Compression quality of JPEGs, 0-100; lower numbers mean lower "
8 "quality and resulting image sizes.");
9
James Kuszmaul0c593962023-01-28 16:04:20 -080010namespace frc971::vision {
James Kuszmaul0c593962023-01-28 16:04:20 -080011std::string_view ExtensionForCompression(ImageCompression compression) {
12 switch (compression) {
13 case ImageCompression::kJpeg:
14 return "jpeg";
15 case ImageCompression::kPng:
16 return "png";
17 }
18}
James Kuszmaul59a308f2023-01-28 19:14:07 -080019
James Kuszmaul0c593962023-01-28 16:04:20 -080020flatbuffers::Offset<foxglove::CompressedImage> CompressImage(
James Kuszmaul59a308f2023-01-28 19:14:07 -080021 const cv::Mat image, const aos::monotonic_clock::time_point eof,
22 flatbuffers::FlatBufferBuilder *fbb, ImageCompression compression) {
James Kuszmaul0c593962023-01-28 16:04:20 -080023 std::string_view format = ExtensionForCompression(compression);
24 // imencode doesn't let us pass in anything other than an std::vector, and
25 // performance isn't yet a big enough issue to try to avoid the copy.
26 std::vector<uint8_t> buffer;
James Kuszmaul77d536c2023-02-11 17:30:59 -080027 CHECK(cv::imencode(absl::StrCat(".", format), image, buffer,
28 {cv::IMWRITE_JPEG_QUALITY, FLAGS_jpeg_quality}));
James Kuszmaul0c593962023-01-28 16:04:20 -080029 const flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data_offset =
30 fbb->CreateVector(buffer);
James Kuszmaul59a308f2023-01-28 19:14:07 -080031 const struct timespec timestamp_t = aos::time::to_timespec(eof);
James Kuszmaul0c593962023-01-28 16:04:20 -080032 const foxglove::Time time{static_cast<uint32_t>(timestamp_t.tv_sec),
33 static_cast<uint32_t>(timestamp_t.tv_nsec)};
34 const flatbuffers::Offset<flatbuffers::String> format_offset =
35 fbb->CreateString(format);
36 foxglove::CompressedImage::Builder builder(*fbb);
37 builder.add_timestamp(&time);
38 builder.add_data(data_offset);
39 builder.add_format(format_offset);
40 return builder.Finish();
41}
42
43FoxgloveImageConverter::FoxgloveImageConverter(aos::EventLoop *event_loop,
44 std::string_view input_channel,
45 std::string_view output_channel,
46 ImageCompression compression)
47 : event_loop_(event_loop),
James Kuszmaul59a308f2023-01-28 19:14:07 -080048 image_callback_(
49 event_loop_, input_channel,
50 [this, compression](const cv::Mat image,
51 const aos::monotonic_clock::time_point eof) {
52 auto builder = sender_.MakeBuilder();
53 builder.CheckOk(builder.Send(
54 CompressImage(image, eof, builder.fbb(), compression)));
55 }),
James Kuszmaul0c593962023-01-28 16:04:20 -080056 sender_(
James Kuszmaul59a308f2023-01-28 19:14:07 -080057 event_loop_->MakeSender<foxglove::CompressedImage>(output_channel)) {}
James Kuszmaul0c593962023-01-28 16:04:20 -080058} // namespace frc971::vision