| 77 | |
| 78 | template<typename T, bool IsDilation> |
| 79 | void morph3d(Param<T> out, CParam<T> in, CParam<T> mask) { |
| 80 | const af::dim4 dims = in.dims(); |
| 81 | const af::dim4 window = mask.dims(); |
| 82 | const dim_t R0 = window[0] / 2; |
| 83 | const dim_t R1 = window[1] / 2; |
| 84 | const dim_t R2 = window[2] / 2; |
| 85 | const af::dim4 istrides = in.strides(); |
| 86 | const af::dim4 fstrides = mask.strides(); |
| 87 | const dim_t bCount = dims[3]; |
| 88 | const af::dim4 ostrides = out.strides(); |
| 89 | T* outData = out.get(); |
| 90 | const T* inData = in.get(); |
| 91 | const T* filter = mask.get(); |
| 92 | |
| 93 | T init = IsDilation ? common::Binary<T, af_max_t>::init() |
| 94 | : common::Binary<T, af_min_t>::init(); |
| 95 | |
| 96 | for (dim_t batchId = 0; batchId < bCount; ++batchId) { |
| 97 | // either channels or batch is handled by outer most loop |
| 98 | for (dim_t k = 0; k < dims[2]; ++k) { |
| 99 | // k steps along 3rd dimension |
| 100 | for (dim_t j = 0; j < dims[1]; ++j) { |
| 101 | // j steps along 2nd dimension |
| 102 | for (dim_t i = 0; i < dims[0]; ++i) { |
| 103 | // i steps along 1st dimension |
| 104 | T filterResult = init; |
| 105 | |
| 106 | // wk, wj,wi steps along 2nd & 1st dimensions of filter |
| 107 | // window respectively |
| 108 | for (dim_t wk = 0; wk < window[2]; wk++) { |
| 109 | for (dim_t wj = 0; wj < window[1]; wj++) { |
| 110 | for (dim_t wi = 0; wi < window[0]; wi++) { |
| 111 | dim_t offk = k + wk - R2; |
| 112 | dim_t offj = j + wj - R1; |
| 113 | dim_t offi = i + wi - R0; |
| 114 | |
| 115 | T maskValue = |
| 116 | filter[getIdx(fstrides, wi, wj, wk)]; |
| 117 | |
| 118 | if ((maskValue > (T)0) && offi >= 0 && |
| 119 | offj >= 0 && offk >= 0 && offi < dims[0] && |
| 120 | offj < dims[1] && offk < dims[2]) { |
| 121 | T inValue = inData[getIdx(istrides, offi, |
| 122 | offj, offk)]; |
| 123 | |
| 124 | if (IsDilation) |
| 125 | filterResult = |
| 126 | std::max(filterResult, inValue); |
| 127 | else |
| 128 | filterResult = |
| 129 | std::min(filterResult, inValue); |
| 130 | } |
| 131 | |
| 132 | } // window 1st dimension loop ends here |
| 133 | } // window 1st dimension loop ends here |
| 134 | } // filter window loop ends here |
| 135 | |
| 136 | outData[getIdx(ostrides, i, j, k)] = filterResult; |