Limit blob debug output in 2022 camera_reader

If we got a huge number of blobs, camera reader would crash because of
trying to allocate too large of a flatbuffer message.

Also, the TargetEstimate message does need to make it across the network
without too high of latency, so excessive debug information in it would
be sub-optimal.

Change-Id: I394c909b4c66940451b3ea2b90f6dc8d383420f6
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/y2022/vision/blob_detector.cc b/y2022/vision/blob_detector.cc
index 6949dd0..2d5ae63 100644
--- a/y2022/vision/blob_detector.cc
+++ b/y2022/vision/blob_detector.cc
@@ -221,8 +221,10 @@
                      cv::Scalar(0, 0, 255), 0);
   }
 
-  cv::drawContours(view_image, blob_result.filtered_blobs, -1,
-                   cv::Scalar(0, 100, 0), cv::FILLED);
+  if (blob_result.filtered_blobs.size() > 0) {
+    cv::drawContours(view_image, blob_result.filtered_blobs, -1,
+                     cv::Scalar(0, 100, 0), cv::FILLED);
+  }
 
   static constexpr double kCircleRadius = 2.0;
   // Draw blob centroids
diff --git a/y2022/vision/camera_reader.cc b/y2022/vision/camera_reader.cc
index 2be2ef1..f1cb4e8 100644
--- a/y2022/vision/camera_reader.cc
+++ b/y2022/vision/camera_reader.cc
@@ -50,6 +50,8 @@
   return builder->fbb()->CreateVectorOfStructs(points_fbs);
 }
 
+constexpr size_t kMaxBlobsForDebug = 100;
+
 // Converts a vector of cv::Point to PointT for the flatbuffer
 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Blob>>>
 CvBlobsToFbs(const std::vector<std::vector<cv::Point>> &blobs,
@@ -60,6 +62,9 @@
     auto blob_builder = builder->MakeBuilder<Blob>();
     blob_builder.add_points(points_offset);
     blobs_fbs.emplace_back(blob_builder.Finish());
+    if (blobs_fbs.size() == kMaxBlobsForDebug) {
+      break;
+    }
   }
   return builder->fbb()->CreateVector(blobs_fbs.data(), blobs_fbs.size());
 }
diff --git a/y2022/vision/viewer.cc b/y2022/vision/viewer.cc
index dfcd49d..24c8fc6 100644
--- a/y2022/vision/viewer.cc
+++ b/y2022/vision/viewer.cc
@@ -50,9 +50,12 @@
 }
 
 std::vector<std::vector<cv::Point>> FbsToCvBlobs(
-    const flatbuffers::Vector<flatbuffers::Offset<Blob>> &blobs_fbs) {
+    const flatbuffers::Vector<flatbuffers::Offset<Blob>> *blobs_fbs) {
+  if (blobs_fbs == nullptr) {
+    return {};
+  }
   std::vector<std::vector<cv::Point>> blobs;
-  for (const auto blob : blobs_fbs) {
+  for (const auto blob : *blobs_fbs) {
     blobs.emplace_back(FbsToCvPoints(*blob->points()));
   }
   return blobs;
@@ -86,8 +89,8 @@
     // Store the TargetEstimate data so we can match timestamp with image
     target_est_map[target_timestamp] = BlobDetector::BlobResult{
         cv::Mat(),
-        FbsToCvBlobs(*target_est->blob_result()->filtered_blobs()),
-        FbsToCvBlobs(*target_est->blob_result()->unfiltered_blobs()),
+        FbsToCvBlobs(target_est->blob_result()->filtered_blobs()),
+        FbsToCvBlobs(target_est->blob_result()->unfiltered_blobs()),
         FbsToBlobStats(*target_est->blob_result()->blob_stats()),
         FbsToBlobStats(*target_est->blob_result()->filtered_stats()),
         cv::Point{target_est->blob_result()->centroid()->x(),