Add flag to disable SIFT in camera_reader

This lets us use camera_reader as a simple camera server for calibration
and other testing.

Change-Id: I3705ab8d6b05db31e35f59e196dc4bb1f8d97685
diff --git a/y2020/vision/camera_reader.cc b/y2020/vision/camera_reader.cc
index d0479d2..63cabcf 100644
--- a/y2020/vision/camera_reader.cc
+++ b/y2020/vision/camera_reader.cc
@@ -18,6 +18,8 @@
 // bazel run //y2020/vision:camera_reader -- --config y2020/config.json
 //   --override_hostname pi-7971-1  --ignore_timestamps true
 DEFINE_string(config, "config.json", "Path to the config file to use.");
+DEFINE_bool(skip_sift, false,
+            "If true don't run any feature extraction.  Just forward images.");
 
 namespace frc971 {
 namespace vision {
@@ -38,10 +40,7 @@
             event_loop->MakeSender<sift::ImageMatchResult>("/camera")),
         detailed_result_sender_(
             event_loop->MakeSender<sift::ImageMatchResult>("/camera/detailed")),
-        read_image_timer_(event_loop->AddTimer([this]() {
-          ReadImage();
-          read_image_timer_->Setup(event_loop_->monotonic_now());
-        })) {
+        read_image_timer_(event_loop->AddTimer([this]() { ReadImage(); })) {
     CopyTrainingFeatures();
     // Technically we don't need to do this, but doing it now avoids the first
     // match attempt being slow.
@@ -288,12 +287,17 @@
 
   // Next, grab the features from the image.
   std::vector<cv::KeyPoint> keypoints;
+
   cv::Mat descriptors;
-  sift_->detectAndCompute(image_mat, cv::noArray(), keypoints, descriptors);
+  if (!FLAGS_skip_sift) {
+    sift_->detectAndCompute(image_mat, cv::noArray(), keypoints, descriptors);
+  }
 
   // Then, match those features against our training data.
   std::vector<std::vector<cv::DMatch>> matches;
-  matcher_->knnMatch(/* queryDescriptors */ descriptors, matches, /* k */ 2);
+  if (!FLAGS_skip_sift) {
+    matcher_->knnMatch(/* queryDescriptors */ descriptors, matches, /* k */ 2);
+  }
 
   struct PerImageMatches {
     std::vector<const std::vector<cv::DMatch> *> matches;
@@ -502,14 +506,18 @@
 
 void CameraReader::ReadImage() {
   if (!reader_->ReadLatestImage()) {
-    LOG(INFO) << "No image, sleeping";
-    std::this_thread::sleep_for(std::chrono::milliseconds(10));
+    if (!FLAGS_skip_sift) {
+      LOG(INFO) << "No image, sleeping";
+    }
+    read_image_timer_->Setup(event_loop_->monotonic_now() +
+                             std::chrono::milliseconds(10));
     return;
   }
 
   ProcessImage(reader_->LatestImage());
 
   reader_->SendLatestImage();
+  read_image_timer_->Setup(event_loop_->monotonic_now());
 }
 
 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<sift::ImageMatch>>>
@@ -555,7 +563,9 @@
                            const cv::Mat &descriptors) {
   const int number_features = keypoints.size();
   CHECK_EQ(descriptors.rows, number_features);
-  CHECK_EQ(descriptors.cols, 128);
+  if (number_features != 0) {
+    CHECK_EQ(descriptors.cols, 128);
+  }
   std::vector<flatbuffers::Offset<sift::Feature>> features_vector(
       number_features);
   for (int i = 0; i < number_features; ++i) {