diff --git a/src/camera/camera.h b/src/camera/camera.h index 07736b7c..57fc2436 100644 --- a/src/camera/camera.h +++ b/src/camera/camera.h @@ -33,5 +33,6 @@ class ICamera { [[nodiscard]] virtual auto GetCameraConstant() const -> camera_constant_t = 0; virtual auto IsDone() -> bool { return false; } virtual ~ICamera() = default; + virtual void Grab() = 0; }; } // namespace camera diff --git a/src/camera/cv_camera.cc b/src/camera/cv_camera.cc index 96b6227f..7e3e5984 100644 --- a/src/camera/cv_camera.cc +++ b/src/camera/cv_camera.cc @@ -66,10 +66,6 @@ CVCamera::CVCamera(const CameraConstant& c, std::optional log_path) auto CVCamera::GetFrame() -> timestamped_frame_t { timestamped_frame_t timestamped_frame; cv::Mat raw_image; - if (!cap_.grab()) { - Restart(); - LOG(WARNING) << "Restarting camera"; - } timestamped_frame.timestamp = frc::Timer::GetFPGATimestamp().to(); cap_.retrieve(raw_image); @@ -96,6 +92,13 @@ auto CVCamera::Restart() -> void { std::this_thread::sleep_for(std::chrono::seconds(3)); } +auto CVCamera::Grab() -> void { + if (!cap_.grab()) { + Restart(); + LOG(WARNING) << "Restarting camera"; + cap_timestamp_ = frc::Timer::GetFPGATimestamp().to(); +} + auto CVCamera::GetCameraConstant() const -> camera_constant_t { return camera_constant_; } diff --git a/src/camera/cv_camera.h b/src/camera/cv_camera.h index 048d96b7..64d7b3d1 100644 --- a/src/camera/cv_camera.h +++ b/src/camera/cv_camera.h @@ -13,6 +13,7 @@ class CVCamera : public ICamera { std::optional log_path = std::nullopt); auto GetFrame() -> timestamped_frame_t override; auto Restart() -> void override; + auto Grab() -> void override; [[nodiscard]] auto GetCameraConstant() const -> camera_constant_t override; private: @@ -21,6 +22,7 @@ class CVCamera : public ICamera { std::string pipeline_; std::optional log_path_; cv::Mat backup_image_; + double cap_timestamp_; }; } // namespace camera diff --git a/src/camera/disk_camera.cc b/src/camera/disk_camera.cc index f3663c58..f0fea313 100644 --- a/src/camera/disk_camera.cc +++ b/src/camera/disk_camera.cc @@ -80,6 +80,8 @@ auto DiskCamera::GetFrame() -> timestamped_frame_t { auto DiskCamera::Restart() -> void {} +auto DiskCamera::Grab() -> void {} + auto DiskCamera::GetCameraConstant() const -> camera_constant_t { return *camera_constant_; } diff --git a/src/camera/disk_camera.h b/src/camera/disk_camera.h index 08d98d2d..73c3be56 100644 --- a/src/camera/disk_camera.h +++ b/src/camera/disk_camera.h @@ -31,6 +31,7 @@ class DiskCamera : public ICamera { std::optional end = std::nullopt); auto GetFrame() -> timestamped_frame_t override; auto Restart() -> void override; + auto Grab() -> void override; auto IsDone() -> bool override { return image_paths_.empty(); } [[nodiscard]] auto GetCameraConstant() const -> camera_constant_t override; diff --git a/src/test/integration_test/CMakeLists.txt b/src/test/integration_test/CMakeLists.txt index 951f9606..c41fcfc8 100644 --- a/src/test/integration_test/CMakeLists.txt +++ b/src/test/integration_test/CMakeLists.txt @@ -30,3 +30,6 @@ target_link_libraries(pva_test PRIVATE utils localization vpi) add_executable(bfs-test bfs_tester.cc) target_link_libraries(bfs-test PRIVATE pathing utils nlohmann_json::nlohmann_json wpiutil) + +add_executable(libjpeg-benchmark libjpeg_benchmark.cc) +target_link_libraries(libjpeg-benchmark PRIVATE ${OpenCV_LIBS} utils) diff --git a/src/test/integration_test/libjpeg_benchmark.cc b/src/test/integration_test/libjpeg_benchmark.cc new file mode 100644 index 00000000..e14d043e --- /dev/null +++ b/src/test/integration_test/libjpeg_benchmark.cc @@ -0,0 +1,63 @@ +#include +#include +#include +#include "absl/flags/flag.h" +#include "absl/flags/internal/flag.h" +#include "absl/flags/parse.h" +#include "src/utils/log.h" +#include "src/utils/pch.h" +#include + +ABSL_FLAG(std::string, image_path, "path/to/image.jpg", // NOLINT + "Path to the image file to be loaded and decoded."); + +ABSL_FLAG(uint, num_trials, 10000, "Number of decoding trials to perform."); // NOLINT + +auto loadImage(const std::string& path) -> std::vector { + std::ifstream file(path, std::ios::binary); + if (!file) { + LOG(FATAL) << "Image could not be loaded from path '" << path + << "'; path invalid or image doesn't exist."; + } + std::vector data(std::istreambuf_iterator(file), {}); + return data; +} + +auto decodeImage(const std::vector& raw) -> cv::Mat { + cv::Mat decoded = cv::imdecode(raw, cv::IMREAD_COLOR); + return decoded; +} + +auto main(int argc, char** argv) -> int { + absl::ParseCommandLine(argc, argv); + std::string imagePath = absl::GetFlag(FLAGS_image_path); + std::vector rawImageData = loadImage(imagePath); + // print which jpeg library we are using so that we know and don't get mixed up + std::istringstream stream(cv::getBuildInformation()); + std::string line; + while (std::getline(stream, line)) { + if (line.find("jpeg:") != std::string::npos || + line.find("JPEG:") != std::string::npos) { + LOG(INFO) << line; + } + } + const uint tests = absl::GetFlag(FLAGS_num_trials); + std::vector trials; + for (uint i = 0; i < tests; ++i) { + auto start = std::chrono::high_resolution_clock::now(); + cv::Mat decodedImage = decodeImage(rawImageData); + auto end = std::chrono::high_resolution_clock::now(); + if (decodedImage.empty()) { + LOG(INFO) << "image decode failed"; + continue; + } + double ms = std::chrono::duration(end - start).count(); + trials.push_back(ms); + } + + double total = std::accumulate(trials.begin(), trials.end(), 0.0); + double average = total / trials.size(); + LOG(INFO) << "Average decoding time over " << tests << " trials: " << average + << " ms"; + return 0; +}