| 19 | |
| 20 | template<typename OutT, typename InT> |
| 21 | void bilateral(Param<OutT> out, CParam<InT> in, float const s_sigma, |
| 22 | float const c_sigma) { |
| 23 | using std::clamp; |
| 24 | using std::max; |
| 25 | using std::min; |
| 26 | |
| 27 | af::dim4 const dims = in.dims(); |
| 28 | af::dim4 const istrides = in.strides(); |
| 29 | af::dim4 const ostrides = out.strides(); |
| 30 | |
| 31 | // clamp spatical and chromatic sigma's |
| 32 | float space_ = min(11.5f, max(s_sigma, 0.f)); |
| 33 | float color_ = max(c_sigma, 0.f); |
| 34 | dim_t const radius = max((dim_t)(space_ * 1.5f), (dim_t)1); |
| 35 | float const svar = space_ * space_; |
| 36 | float const cvar = color_ * color_; |
| 37 | |
| 38 | for (dim_t b3 = 0; b3 < dims[3]; ++b3) { |
| 39 | OutT *outData = out.get() + b3 * ostrides[3]; |
| 40 | InT const *inData = in.get() + b3 * istrides[3]; |
| 41 | |
| 42 | // b3 for loop handles following batch configurations |
| 43 | // - gfor |
| 44 | // - input based batch |
| 45 | // - when input is 4d array for color images |
| 46 | for (dim_t b2 = 0; b2 < dims[2]; ++b2) { |
| 47 | // b2 for loop handles following batch configurations |
| 48 | // - channels |
| 49 | // - input based batch |
| 50 | // - when input is 3d array for grayscale images |
| 51 | for (dim_t j = 0; j < dims[1]; ++j) { |
| 52 | // j steps along 2nd dimension |
| 53 | for (dim_t i = 0; i < dims[0]; ++i) { |
| 54 | // i steps along 1st dimension |
| 55 | OutT norm = 0.0; |
| 56 | OutT res = 0.0; |
| 57 | OutT const center = (OutT)inData[getIdx(istrides, i, j)]; |
| 58 | for (dim_t wj = -radius; wj <= radius; ++wj) { |
| 59 | // clamps offsets |
| 60 | dim_t tj = clamp(j + wj, dim_t(0), dims[1] - 1); |
| 61 | for (dim_t wi = -radius; wi <= radius; ++wi) { |
| 62 | // clamps offsets |
| 63 | dim_t ti = clamp(i + wi, dim_t(0), dims[0] - 1); |
| 64 | // proceed |
| 65 | OutT const val = |
| 66 | (OutT)inData[getIdx(istrides, ti, tj)]; |
| 67 | OutT const gauss_space = |
| 68 | (wi * wi + wj * wj) / (-2.0 * svar); |
| 69 | OutT const gauss_range = |
| 70 | ((center - val) * (center - val)) / |
| 71 | (-2.0 * cvar); |
| 72 | OutT const weight = |
| 73 | std::exp(gauss_space + gauss_range); |
| 74 | norm += weight; |
| 75 | res += val * weight; |
| 76 | } |
| 77 | } // filter loop ends here |
| 78 | |