initial commit
This commit is contained in:
106
filter.h
Normal file
106
filter.h
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include "diffvg.h"
|
||||
#include "atomic.h"
|
||||
|
||||
enum class FilterType {
|
||||
Box,
|
||||
Tent,
|
||||
RadialParabolic, // 4/3(1 - (d/r))
|
||||
Hann // https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows
|
||||
};
|
||||
|
||||
struct Filter {
|
||||
FilterType type;
|
||||
float radius;
|
||||
};
|
||||
|
||||
struct DFilter {
|
||||
float radius;
|
||||
};
|
||||
|
||||
DEVICE
|
||||
inline
|
||||
float compute_filter_weight(const Filter &filter,
|
||||
float dx,
|
||||
float dy) {
|
||||
if (fabs(dx) > filter.radius || fabs(dy) > filter.radius) {
|
||||
return 0;
|
||||
}
|
||||
if (filter.type == FilterType::Box) {
|
||||
return 1.f / square(2 * filter.radius);
|
||||
} else if (filter.type == FilterType::Tent) {
|
||||
return (filter.radius - fabs(dx)) * (filter.radius - fabs(dy)) /
|
||||
square(square(filter.radius));
|
||||
} else if (filter.type == FilterType::RadialParabolic) {
|
||||
return (4.f / 3.f) * (1 - square(dx / filter.radius)) *
|
||||
(4.f / 3.f) * (1 - square(dy / filter.radius));
|
||||
} else {
|
||||
assert(filter.type == FilterType::Hann);
|
||||
// normalize dx, dy to [0, 1]
|
||||
auto ndx = (dx / (2*filter.radius)) + 0.5f;
|
||||
auto ndy = (dy / (2*filter.radius)) + 0.5f;
|
||||
// the normalization factor is R^2
|
||||
return 0.5f * (1.f - cos(float(2 * M_PI) * ndx)) *
|
||||
0.5f * (1.f - cos(float(2 * M_PI) * ndy)) /
|
||||
square(filter.radius);
|
||||
}
|
||||
}
|
||||
|
||||
DEVICE
|
||||
inline
|
||||
void d_compute_filter_weight(const Filter &filter,
|
||||
float dx,
|
||||
float dy,
|
||||
float d_return,
|
||||
DFilter *d_filter) {
|
||||
if (filter.type == FilterType::Box) {
|
||||
// return 1.f / square(2 * filter.radius);
|
||||
atomic_add(d_filter->radius,
|
||||
d_return * (-2) * 2 * filter.radius / cubic(2 * filter.radius));
|
||||
} else if (filter.type == FilterType::Tent) {
|
||||
// return (filer.radius - fabs(dx)) * (filer.radius - fabs(dy)) /
|
||||
// square(square(filter.radius));
|
||||
auto fx = filter.radius - fabs(dx);
|
||||
auto fy = filter.radius - fabs(dy);
|
||||
auto norm = 1 / square(filter.radius);
|
||||
auto d_fx = d_return * fy * norm;
|
||||
auto d_fy = d_return * fx * norm;
|
||||
auto d_norm = d_return * fx * fy;
|
||||
atomic_add(d_filter->radius,
|
||||
d_fx + d_fy + (-4) * d_norm / pow(filter.radius, 5));
|
||||
} else if (filter.type == FilterType::RadialParabolic) {
|
||||
// return (4.f / 3.f) * (1 - square(dx / filter.radius)) *
|
||||
// (4.f / 3.f) * (1 - square(dy / filter.radius));
|
||||
// auto d_square_x = d_return * (-4.f / 3.f);
|
||||
// auto d_square_y = d_return * (-4.f / 3.f);
|
||||
auto r3 = filter.radius * filter.radius * filter.radius;
|
||||
auto d_radius = -(2 * square(dx) + 2 * square(dy)) / r3;
|
||||
atomic_add(d_filter->radius, d_radius);
|
||||
} else {
|
||||
assert(filter.type == FilterType::Hann);
|
||||
// // normalize dx, dy to [0, 1]
|
||||
// auto ndx = (dx / (2*filter.radius)) + 0.5f;
|
||||
// auto ndy = (dy / (2*filter.radius)) + 0.5f;
|
||||
// // the normalization factor is R^2
|
||||
// return 0.5f * (1.f - cos(float(2 * M_PI) * ndx)) *
|
||||
// 0.5f * (1.f - cos(float(2 * M_PI) * ndy)) /
|
||||
// square(filter.radius);
|
||||
|
||||
// normalize dx, dy to [0, 1]
|
||||
auto ndx = (dx / (2*filter.radius)) + 0.5f;
|
||||
auto ndy = (dy / (2*filter.radius)) + 0.5f;
|
||||
auto fx = 0.5f * (1.f - cos(float(2*M_PI) * ndx));
|
||||
auto fy = 0.5f * (1.f - cos(float(2*M_PI) * ndy));
|
||||
auto norm = 1 / square(filter.radius);
|
||||
auto d_fx = d_return * fy * norm;
|
||||
auto d_fy = d_return * fx * norm;
|
||||
auto d_norm = d_return * fx * fy;
|
||||
auto d_ndx = d_fx * 0.5f * sin(float(2*M_PI) * ndx) * float(2*M_PI);
|
||||
auto d_ndy = d_fy * 0.5f * sin(float(2*M_PI) * ndy) * float(2*M_PI);
|
||||
atomic_add(d_filter->radius,
|
||||
d_ndx * (-2*dx / square(2*filter.radius)) +
|
||||
d_ndy * (-2*dy / square(2*filter.radius)) +
|
||||
(-2) * d_norm / cubic(filter.radius));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user