blob: 0ed9e20e81f98952e49b9d13990cef00968d5815 [file] [log] [blame]
Brian Silvermane4664162020-02-15 15:27:46 -08001#include "y2020/vision/sift/fast_gaussian.h"
2
Philipp Schrader790cb542023-07-05 21:06:52 -07003#include "gtest/gtest.h"
Brian Silvermane4664162020-02-15 15:27:46 -08004#include <opencv2/imgproc.hpp>
Brian Silvermane4664162020-02-15 15:27:46 -08005
6#include "y2020/vision/sift/fast_gaussian_all.h"
7
8namespace frc971 {
9namespace vision {
10namespace testing {
11
12class FastGaussianTest : public ::testing::Test {
13 public:
14 cv::Mat RandomImage(int width = 500, int height = 500, int type = CV_8UC3) {
15 cv::Mat result(width, height, type);
16 cv::randu(result, 0, 255);
17 return result;
18 }
19
20 void ExpectEqual(const cv::Mat &a, const cv::Mat &b, double epsilon = 1e-10) {
21 const cv::Mat difference = a - b;
22 double min, max;
23 cv::minMaxLoc(difference, &min, &max);
24 EXPECT_GE(min, -epsilon);
25 EXPECT_LE(max, epsilon);
26 }
27};
28
29// Verifies that the default GaussianBlur parameters work out to 15x15 with
30// sigma of 1.6.
31TEST_F(FastGaussianTest, DefaultGaussianSize) {
32 const auto image = RandomImage(500, 500, CV_32FC3);
33 cv::Mat default_blurred, explicitly_blurred;
34 cv::GaussianBlur(image, default_blurred, cv::Size(), 1.6, 1.6);
35 cv::GaussianBlur(image, explicitly_blurred, cv::Size(15, 15), 1.6, 1.6);
36 ExpectEqual(default_blurred, explicitly_blurred);
37}
38
Brian Silverman4c7235a2021-11-17 19:04:37 -080039// Verifies that with 8U just a 9x9 blur is as much as you get, except for a bit
40// of rounding.
41TEST_F(FastGaussianTest, GaussianSize8U) {
Brian Silvermane4664162020-02-15 15:27:46 -080042 const auto image = RandomImage(500, 500, CV_8UC3);
43 cv::Mat big_blurred, little_blurred;
44 cv::GaussianBlur(image, big_blurred, cv::Size(15, 15), 1.6, 1.6);
45 cv::GaussianBlur(image, little_blurred, cv::Size(9, 9), 1.6, 1.6);
Brian Silverman4c7235a2021-11-17 19:04:37 -080046 ExpectEqual(big_blurred, little_blurred, 3);
Brian Silvermane4664162020-02-15 15:27:46 -080047}
48
49// Verifies that FastGaussian and cv::GaussianBlur give the same result.
50TEST_F(FastGaussianTest, FastGaussian) {
Brian Silvermana9ada662020-02-16 21:00:19 -080051 const auto image = RandomImage(480, 640, CV_16SC1);
Brian Silvermane4664162020-02-15 15:27:46 -080052 cv::Mat slow, fast, fast_direct;
53 static constexpr double kSigma = 1.9465878414647133;
54 static constexpr int kSize = 13;
55
56 cv::GaussianBlur(image, slow, cv::Size(kSize, kSize), kSigma, kSigma);
57 FastGaussian(image, &fast, kSigma);
58
59 // Explicitly call the generated code, to verify that our chosen parameters do
60 // in fact result in using the generated one.
61 fast_direct.create(slow.size(), slow.type());
62 ASSERT_EQ(0,
63 DoGeneratedFastGaussian(MatToHalide<const int16_t>(image),
64 MatToHalide<int16_t>(fast_direct), kSigma));
65
Brian Silverman4b0bcaf2022-01-01 22:48:55 -080066 // 1500/65536 = 0.0228, which is under 3%, which is pretty close.
67 ExpectEqual(slow, fast, 1500);
Brian Silvermane4664162020-02-15 15:27:46 -080068 // The wrapper should be calling the exact same code, so it should end up with
69 // the exact same result.
70 ExpectEqual(fast, fast_direct, 0);
71}
72
73} // namespace testing
74} // namespace vision
75} // namespace frc971