Make SIFT faster

This uses various halide-optimized functions to do the actual image
processing. It still finds around the same number of features, but much
faster.

Change-Id: I9d7f7093b0ec41acf7ed16b2c91cdadada2f9a22
diff --git a/y2020/vision/sift/fast_gaussian.h b/y2020/vision/sift/fast_gaussian.h
new file mode 100644
index 0000000..580083f
--- /dev/null
+++ b/y2020/vision/sift/fast_gaussian.h
@@ -0,0 +1,44 @@
+#ifndef Y2020_VISION_SIFT_FAST_GAUSSIAN_H_
+#define Y2020_VISION_SIFT_FAST_GAUSSIAN_H_
+
+#include <type_traits>
+
+#include <opencv2/core/mat.hpp>
+#include "HalideBuffer.h"
+#include "glog/logging.h"
+
+namespace frc971 {
+namespace vision {
+
+// Returns a Halide buffer representing the data in mat.
+template <typename T>
+inline Halide::Runtime::Buffer<T, 2> MatToHalide(const cv::Mat &mat) {
+  CHECK_EQ(cv::DataType<typename std::remove_const<T>::type>::type, mat.type());
+  // Verify that at<T>(row, col) accesses this address:
+  //   data + sizeof(T) * (row * cols + col)
+  CHECK_EQ(mat.elemSize(), sizeof(T));
+  CHECK_EQ(mat.elemSize1(), sizeof(T));
+  CHECK_EQ(mat.step1(0), static_cast<size_t>(mat.cols));
+  CHECK_EQ(mat.step1(1), 1u);
+  CHECK_EQ(mat.dims, 2);
+  CHECK(mat.isContinuous());
+  return Halide::Runtime::Buffer<T, 2>(reinterpret_cast<T *>(mat.data),
+                                       mat.cols, mat.rows);
+}
+
+// Performs a gaussian blur with the specified sigma, truncated to a reasonable
+// width. Attempts to use faster implementations, but will fall back to
+// cv::GaussianBlur otherwise. Only handles a limited set of Mat formats.
+//
+// source and destination may not overlap.
+//
+// Always uses BORDER_REPLICATE mode.
+void FastGaussian(const cv::Mat &source, cv::Mat *destination, double sigma);
+void FastSubtract(const cv::Mat &a, const cv::Mat &b, cv::Mat *destination);
+void FastGaussianAndSubtract(const cv::Mat &source, cv::Mat *blurred,
+                             cv::Mat *difference, double sigma);
+
+}  // namespace vision
+}  // namespace vision
+
+#endif  // Y2020_VISION_SIFT_FAST_GAUSSIAN_H_