AliceVision
Photogrammetric Computer Vision Framework
gaussian.hpp
1 // This file is part of the AliceVision project.
2 // Copyright (c) 2020 AliceVision contributors.
3 // This Source Code Form is subject to the terms of the Mozilla Public License,
4 // v. 2.0. If a copy of the MPL was not distributed with this file,
5 // You can obtain one at https://mozilla.org/MPL/2.0/.
6 
7 #pragma once
8 
9 #include <aliceVision/image/Image.hpp>
10 
11 namespace aliceVision {
12 
14 {
15  public:
16  GaussianPyramidNoMask(const size_t width_base, const size_t height_base, const size_t limit_scales = 64);
17 
18  bool process(const image::Image<image::RGBfColor>& input);
19 
20  bool downscale(image::Image<image::RGBfColor>& output, const image::Image<image::RGBfColor>& input);
21 
22  const size_t getScalesCount() const { return _scales; }
23 
24  const std::vector<image::Image<image::RGBfColor>>& getPyramidColor() const { return _pyramid_color; }
25 
26  std::vector<image::Image<image::RGBfColor>>& getPyramidColor() { return _pyramid_color; }
27 
28  protected:
29  std::vector<image::Image<image::RGBfColor>> _pyramid_color;
30  std::vector<image::Image<image::RGBfColor>> _filter_buffer;
31  size_t _width_base;
32  size_t _height_base;
33  size_t _scales;
34 };
35 
36 template<class T>
37 inline void convolveRow(typename image::Image<T>::RowXpr output_row,
38  typename image::Image<T>::ConstRowXpr input_row,
39  const Eigen::Matrix<float, 5, 1>& kernel,
40  bool loop)
41 {
42  const int radius = 2;
43 
44  for (int j = 0; j < input_row.cols(); j++)
45  {
46  T sum = T();
47  float sumw = 0.0f;
48 
49  for (int k = 0; k < kernel.size(); k++)
50  {
51  float w = kernel(k);
52  int col = j + k - radius;
53 
54  /* mirror 5432 | 123456 | 5432 */
55 
56  if (!loop)
57  {
58  if (col < 0)
59  {
60  col = -col;
61  }
62 
63  if (col >= input_row.cols())
64  {
65  col = input_row.cols() - 1 - (col + 1 - input_row.cols());
66  }
67  }
68  else
69  {
70  if (col < 0)
71  {
72  col = input_row.cols() + col;
73  }
74 
75  if (col >= input_row.cols())
76  {
77  col = col - input_row.cols();
78  }
79  }
80 
81  sum += w * input_row(col);
82  sumw += w;
83  }
84 
85  output_row(j) = sum / sumw;
86  }
87 }
88 
89 template<class T>
90 inline void convolveColumns(typename image::Image<T>::RowXpr output_row, const image::Image<T>& input_rows, const Eigen::Matrix<float, 5, 1>& kernel)
91 {
92  for (int j = 0; j < output_row.cols(); j++)
93  {
94  T sum = T();
95  float sumw = 0.0f;
96 
97  for (int k = 0; k < kernel.size(); k++)
98  {
99  float w = kernel(k);
100  sum += w * input_rows(k, j);
101  sumw += w;
102  }
103 
104  output_row(j) = sum / sumw;
105  }
106 }
107 
108 template<class T>
109 bool convolveGaussian5x5(image::Image<T>& output, const image::Image<T>& input, bool loop = false)
110 {
111  if (output.size() != input.size())
112  {
113  return false;
114  }
115 
116  Eigen::Matrix<float, 5, 1> kernel;
117  kernel[0] = 1.0f;
118  kernel[1] = 4.0f;
119  kernel[2] = 6.0f;
120  kernel[3] = 4.0f;
121  kernel[4] = 1.0f;
122  kernel = kernel / kernel.sum();
123 
124  image::Image<T> buf(output.width(), 5);
125 
126  int radius = 2;
127 
128  convolveRow<T>(buf.row(0), input.row(2), kernel, loop);
129  convolveRow<T>(buf.row(1), input.row(1), kernel, loop);
130  convolveRow<T>(buf.row(2), input.row(0), kernel, loop);
131  convolveRow<T>(buf.row(3), input.row(1), kernel, loop);
132  convolveRow<T>(buf.row(4), input.row(2), kernel, loop);
133 
134  for (int i = 0; i < output.height() - 3; i++)
135  {
136  convolveColumns<T>(output.row(i), buf, kernel);
137 
138  buf.row(0) = buf.row(1);
139  buf.row(1) = buf.row(2);
140  buf.row(2) = buf.row(3);
141  buf.row(3) = buf.row(4);
142  convolveRow<T>(buf.row(4), input.row(i + 3), kernel, loop);
143  }
144 
150  convolveColumns<T>(output.row(output.height() - 3), buf, kernel);
151 
152  buf.row(0) = buf.row(1);
153  buf.row(1) = buf.row(2);
154  buf.row(2) = buf.row(3);
155  buf.row(3) = buf.row(4);
156  convolveRow<T>(buf.row(4), input.row(output.height() - 2), kernel, loop);
157  convolveColumns<T>(output.row(output.height() - 2), buf, kernel);
158 
159  buf.row(0) = buf.row(1);
160  buf.row(1) = buf.row(2);
161  buf.row(2) = buf.row(3);
162  buf.row(3) = buf.row(4);
163  convolveRow<T>(buf.row(4), input.row(output.height() - 3), kernel, loop);
164  convolveColumns<T>(output.row(output.height() - 1), buf, kernel);
165 
166  return true;
167 }
168 
169 } // namespace aliceVision
aliceVision
Definition: checkerDetector.cpp:32
aliceVision::GaussianPyramidNoMask
Definition: gaussian.hpp:13
aliceVision::GaussianPyramidNoMask::GaussianPyramidNoMask
GaussianPyramidNoMask(const size_t width_base, const size_t height_base, const size_t limit_scales=64)
Definition: gaussian.cpp:13
aliceVision::image::Image
Definition: ImageDescriber_AKAZE_OCV.hpp:21
aliceVision::image::Image::width
int width() const
Retrieve the width of the image.
Definition: Image.hpp:110
aliceVision::convolveGaussian5x5
bool convolveGaussian5x5(image::Image< T > &output, const image::Image< T > &input, bool loop=false)
Definition: gaussian.hpp:109
aliceVision::image::Image::height
int height() const
Retrieve the height of the image.
Definition: Image.hpp:116
aliceVision::GaussianPyramidNoMask::process
bool process(const image::Image< image::RGBfColor > &input)
Definition: gaussian.cpp:39