Allows images to be either inserted manually, or taken through the v4l2 camera reader

Change-Id: Ib0496b3c5780f5a4e40b49765472006669551406
Signed-off-by: Henry Speiser <100027428@mvla.net>
diff --git a/y2022/vision/BUILD b/y2022/vision/BUILD
index e893e54..c37d488 100644
--- a/y2022/vision/BUILD
+++ b/y2022/vision/BUILD
@@ -32,6 +32,7 @@
         ":target_estimator_lib",
         "//aos:flatbuffer_merge",
         "//aos/events:event_loop",
+        "//aos/events:shm_event_loop",
         "//aos/network:team_number",
         "//frc971/vision:v4l2_reader",
         "//frc971/vision:vision_fbs",
diff --git a/y2022/vision/camera_reader.cc b/y2022/vision/camera_reader.cc
index f466c8b..77bda6c 100644
--- a/y2022/vision/camera_reader.cc
+++ b/y2022/vision/camera_reader.cc
@@ -5,6 +5,7 @@
 #include <opencv2/imgproc.hpp>
 
 #include "aos/events/event_loop.h"
+#include "aos/events/shm_event_loop.h"
 #include "aos/flatbuffer_merge.h"
 #include "aos/network/team_number.h"
 #include "frc971/vision/v4l2_reader.h"
@@ -15,6 +16,8 @@
 #include "y2022/vision/blob_detector.h"
 #include "y2022/vision/target_estimator.h"
 
+DEFINE_string(image_png, "", "A set of PNG images");
+
 namespace y2022 {
 namespace vision {
 
@@ -37,22 +40,12 @@
              << " on " << team_number;
 }
 
-void CameraReader::ProcessImage(const CameraImage &image) {
+void CameraReader::ProcessImage(const cv::Mat &image_mat) {
   // Remember, we're getting YUYV images, so we start by converting to RGB
 
   // TOOD: Need to code this up for blob detection
-  cv::Mat image_mat(image.rows(), image.cols(), CV_8U);
-  CHECK(image_mat.isContinuous());
-  const int number_pixels = image.rows() * image.cols();
-  for (int i = 0; i < number_pixels; ++i) {
-    reinterpret_cast<uint8_t *>(image_mat.data)[i] =
-        image.data()->data()[i * 2];
-  }
 
-  // Now, send our two messages-- one large, with details for remote
-  // debugging(features), and one smaller
-  // TODO: Send debugging message as well
-  std::vector<std::vector<cv::Point> > filtered_blobs, unfiltered_blobs;
+  std::vector<std::vector<cv::Point>> filtered_blobs, unfiltered_blobs;
   std::vector<BlobDetector::BlobStats> blob_stats;
   cv::Mat binarized_image =
       cv::Mat::zeros(cv::Size(image_mat.cols, image_mat.rows), CV_8UC1);
@@ -69,13 +62,37 @@
 }
 
 void CameraReader::ReadImage() {
+  // Path is for reading from the Disk.
+  if (FLAGS_image_png != "") {
+    std::vector<cv::String> file_list;
+    cv::glob(FLAGS_image_png + "/*.png", file_list, false);
+
+    for (auto file : file_list) {
+      LOG(INFO) << "Reading file " << file;
+      cv::Mat rgb_image = cv::imread(file.c_str());
+      ProcessImage(rgb_image);
+    }
+    event_loop_->Exit();
+    return;
+  }
+  // If we are not reading from the disk, we read the live camera stream.
   if (!reader_->ReadLatestImage()) {
     read_image_timer_->Setup(event_loop_->monotonic_now() +
                              std::chrono::milliseconds(10));
     return;
   }
 
-  ProcessImage(reader_->LatestImage());
+  const CameraImage &image = reader_->LatestImage();
+  cv::Mat image_mat(image.rows(), image.cols(), CV_8U);
+  CHECK(image_mat.isContinuous());
+
+  const int number_pixels = image.rows() * image.cols();
+  for (int i = 0; i < number_pixels; ++i) {
+    reinterpret_cast<uint8_t *>(image_mat.data)[i] =
+        image.data()->data()[i * 2];
+  }
+
+  ProcessImage(image_mat);
 
   reader_->SendLatestImage();
   read_image_timer_->Setup(event_loop_->monotonic_now());
diff --git a/y2022/vision/camera_reader.h b/y2022/vision/camera_reader.h
index 6880248..78abaa5 100644
--- a/y2022/vision/camera_reader.h
+++ b/y2022/vision/camera_reader.h
@@ -5,9 +5,10 @@
 
 #include <opencv2/calib3d.hpp>
 #include <opencv2/features2d.hpp>
+#include <opencv2/imgcodecs.hpp>
 #include <opencv2/imgproc.hpp>
 
-#include "aos/events/event_loop.h"
+#include "aos/events/shm_event_loop.h"
 #include "aos/flatbuffer_merge.h"
 #include "aos/network/team_number.h"
 #include "frc971/vision/v4l2_reader.h"
@@ -26,7 +27,7 @@
 
 class CameraReader {
  public:
-  CameraReader(aos::EventLoop *event_loop,
+  CameraReader(aos::ShmEventLoop *event_loop,
                const sift::TrainingData *training_data, V4L2Reader *reader)
       : event_loop_(event_loop),
         training_data_(training_data),
@@ -44,7 +45,7 @@
   const sift::CameraCalibration *FindCameraCalibration() const;
 
   // Processes an image (including sending the results).
-  void ProcessImage(const CameraImage &image);
+  void ProcessImage(const cv::Mat &image);
 
   // Reads an image, and then performs all of our processing on it.
   void ReadImage();
@@ -75,7 +76,7 @@
     return result;
   }
 
-  aos::EventLoop *const event_loop_;
+  aos::ShmEventLoop *const event_loop_;
   const sift::TrainingData *const training_data_;
   const sift::CameraCalibration *const camera_calibration_;
   V4L2Reader *const reader_;