blob: 27bab540487110be0f317bd42a672ab18a75a866 [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
Stephan Pleinesf63bde82024-01-13 15:59:33 -08008namespace frc971::vision::testing {
Brian Silvermane4664162020-02-15 15:27:46 -08009
10class FastGaussianTest : public ::testing::Test {
11 public:
12 cv::Mat RandomImage(int width = 500, int height = 500, int type = CV_8UC3) {
13 cv::Mat result(width, height, type);
14 cv::randu(result, 0, 255);
15 return result;
16 }
17
18 void ExpectEqual(const cv::Mat &a, const cv::Mat &b, double epsilon = 1e-10) {
19 const cv::Mat difference = a - b;
20 double min, max;
21 cv::minMaxLoc(difference, &min, &max);
22 EXPECT_GE(min, -epsilon);
23 EXPECT_LE(max, epsilon);
24 }
25};
26
27// Verifies that the default GaussianBlur parameters work out to 15x15 with
28// sigma of 1.6.
29TEST_F(FastGaussianTest, DefaultGaussianSize) {
30 const auto image = RandomImage(500, 500, CV_32FC3);
31 cv::Mat default_blurred, explicitly_blurred;
32 cv::GaussianBlur(image, default_blurred, cv::Size(), 1.6, 1.6);
33 cv::GaussianBlur(image, explicitly_blurred, cv::Size(15, 15), 1.6, 1.6);
34 ExpectEqual(default_blurred, explicitly_blurred);
35}
36
Brian Silverman4c7235a2021-11-17 19:04:37 -080037// Verifies that with 8U just a 9x9 blur is as much as you get, except for a bit
38// of rounding.
39TEST_F(FastGaussianTest, GaussianSize8U) {
Brian Silvermane4664162020-02-15 15:27:46 -080040 const auto image = RandomImage(500, 500, CV_8UC3);
41 cv::Mat big_blurred, little_blurred;
42 cv::GaussianBlur(image, big_blurred, cv::Size(15, 15), 1.6, 1.6);
43 cv::GaussianBlur(image, little_blurred, cv::Size(9, 9), 1.6, 1.6);
Brian Silverman4c7235a2021-11-17 19:04:37 -080044 ExpectEqual(big_blurred, little_blurred, 3);
Brian Silvermane4664162020-02-15 15:27:46 -080045}
46
47// Verifies that FastGaussian and cv::GaussianBlur give the same result.
48TEST_F(FastGaussianTest, FastGaussian) {
Brian Silvermana9ada662020-02-16 21:00:19 -080049 const auto image = RandomImage(480, 640, CV_16SC1);
Brian Silvermane4664162020-02-15 15:27:46 -080050 cv::Mat slow, fast, fast_direct;
51 static constexpr double kSigma = 1.9465878414647133;
52 static constexpr int kSize = 13;
53
54 cv::GaussianBlur(image, slow, cv::Size(kSize, kSize), kSigma, kSigma);
55 FastGaussian(image, &fast, kSigma);
56
57 // Explicitly call the generated code, to verify that our chosen parameters do
58 // in fact result in using the generated one.
59 fast_direct.create(slow.size(), slow.type());
60 ASSERT_EQ(0,
61 DoGeneratedFastGaussian(MatToHalide<const int16_t>(image),
62 MatToHalide<int16_t>(fast_direct), kSigma));
63
Brian Silverman4b0bcaf2022-01-01 22:48:55 -080064 // 1500/65536 = 0.0228, which is under 3%, which is pretty close.
65 ExpectEqual(slow, fast, 1500);
Brian Silvermane4664162020-02-15 15:27:46 -080066 // The wrapper should be calling the exact same code, so it should end up with
67 // the exact same result.
68 ExpectEqual(fast, fast_direct, 0);
69}
70
Stephan Pleinesf63bde82024-01-13 15:59:33 -080071} // namespace frc971::vision::testing