-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkernels.cpp
More file actions
70 lines (61 loc) · 2.53 KB
/
kernels.cpp
File metadata and controls
70 lines (61 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
Copyright [2024] [Yao Yao]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "kernels.h"
std::vector<float> make_gaussian_filter(float sigma, float radiusToSigRatio){
#if 1
// Sampled Gaussian kernel
// This is incorrect but the result is better. i.e. more key points. OpenCV GaussianBlur is also doing this.
(void)(radiusToSigRatio);
assert(sigma > 0);
const int filter_size = std::min(int(std::round(sigma * radiusToSigRatio * 2 + 1)) | 1, cuda_DoG_max_filter_size);
const int radius = (filter_size - 1) / 2;
std::vector<float> filter((size_t)filter_size);
for(int i = 0; i < filter_size; i++){
filter[i] = std::exp(-sqr(i - radius) / (2 * sqr(sigma)));
}
float const factor = 1.f / std::accumulate(filter.begin(), filter.end(), 0.f);
// printf("filter sigma=%f: ", sigma);
for(int i = 0; i < filter_size; i++){
filter[i] *= factor;
// printf("%f, ", filter[i]);
}
// printf("\n");
return filter;
#else
// Ideal implementation based on normal CDF / erfc. This is theoretically better but detects less key points.
assert(sigma > 0);
const int filter_size = std::min(int(std::round(sigma * radiusToSigRatio * 2 + 1)) | 1, cuda_DoG_max_filter_size);
const int radius = (filter_size - 1) / 2;
std::vector<float> filter((size_t)filter_size);
double const rcpSigma = 1.0 / sigma;
auto const normalCDFx2 = [rcpSigma](double x){
double const rsqrt_2 = std::sqrt(0.5);
double const factor = -rsqrt_2 * rcpSigma;
return erfc(x * factor);
};
double left = normalCDFx2(-0.5 - radius);
for(int i = 0; i < filter_size; i++){
double const right = normalCDFx2(0.5 - radius + i);
filter[i] = right - left;
left = right;
}
const float factor = static_cast<float>(1.0 / std::accumulate(filter.begin(), filter.end(), 0.0));
// printf("filter sigma=%f: ", sigma);
for(int i = 0; i < filter_size; i++){
filter[i] *= factor;
// printf("%f, ", filter[i]);
}
// printf("\n");
return filter;
#endif
}