| 1016 | |
| 1017 | template<typename T, typename convAccT> |
| 1018 | std::vector<Array<T>> buildGaussPyr(Param<T> init_img, const unsigned n_octaves, |
| 1019 | const unsigned n_layers, |
| 1020 | const float init_sigma) { |
| 1021 | // Precompute Gaussian sigmas using the following formula: |
| 1022 | // \sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2 |
| 1023 | std::vector<float> sig_layers(n_layers + 3); |
| 1024 | sig_layers[0] = init_sigma; |
| 1025 | float k = std::pow(2.0f, 1.0f / n_layers); |
| 1026 | for (unsigned i = 1; i < n_layers + 3; i++) { |
| 1027 | float sig_prev = std::pow(k, i - 1) * init_sigma; |
| 1028 | float sig_total = sig_prev * k; |
| 1029 | sig_layers[i] = std::sqrt(sig_total * sig_total - sig_prev * sig_prev); |
| 1030 | } |
| 1031 | |
| 1032 | // Gaussian Pyramid |
| 1033 | std::vector<Array<T>> gauss_pyr; |
| 1034 | std::vector<Array<T>> tmp_pyr; |
| 1035 | gauss_pyr.reserve(n_octaves); |
| 1036 | tmp_pyr.reserve(n_octaves * (n_layers + 3)); |
| 1037 | for (unsigned o = 0; o < n_octaves; o++) { |
| 1038 | gauss_pyr.push_back(createEmptyArray<T>( |
| 1039 | {(o == 0) ? init_img.dims[0] : gauss_pyr[o - 1].dims()[0] / 2, |
| 1040 | (o == 0) ? init_img.dims[1] : gauss_pyr[o - 1].dims()[1] / 2, |
| 1041 | n_layers + 3})); |
| 1042 | |
| 1043 | for (unsigned l = 0; l < n_layers + 3; l++) { |
| 1044 | unsigned src_idx = (l == 0) ? (o - 1) * (n_layers + 3) + n_layers |
| 1045 | : o * (n_layers + 3) + l - 1; |
| 1046 | unsigned idx = o * (n_layers + 3) + l; |
| 1047 | |
| 1048 | if (o == 0 && l == 0) { |
| 1049 | tmp_pyr.push_back(createParamArray(init_img, false)); |
| 1050 | } else if (l == 0) { |
| 1051 | tmp_pyr.push_back( |
| 1052 | createEmptyArray<T>({tmp_pyr[src_idx].dims()[0] / 2, |
| 1053 | tmp_pyr[src_idx].dims()[1] / 2})); |
| 1054 | resize<T>(tmp_pyr[idx], tmp_pyr[src_idx], AF_INTERP_BILINEAR); |
| 1055 | } else { |
| 1056 | tmp_pyr.push_back(createEmptyArray<T>(tmp_pyr[src_idx].dims())); |
| 1057 | Array<T> tmp = createEmptyArray<T>(tmp_pyr[src_idx].dims()); |
| 1058 | Array<convAccT> filter = gauss_filter<convAccT>(sig_layers[l]); |
| 1059 | |
| 1060 | convolve2<T, convAccT>(tmp, tmp_pyr[src_idx], filter, 0, false); |
| 1061 | convolve2<T, convAccT>(tmp_pyr[idx], CParam<T>(tmp), filter, 1, |
| 1062 | false); |
| 1063 | |
| 1064 | // memFree(tmp.ptr); |
| 1065 | } |
| 1066 | |
| 1067 | const unsigned imel = tmp_pyr[idx].elements(); |
| 1068 | const unsigned offset = imel * l; |
| 1069 | |
| 1070 | CUDA_CHECK(cudaMemcpyAsync( |
| 1071 | gauss_pyr[o].get() + offset, tmp_pyr[idx].get(), |
| 1072 | imel * sizeof(T), cudaMemcpyDeviceToDevice, getActiveStream())); |
| 1073 | } |
| 1074 | } |
| 1075 | return gauss_pyr; |
nothing calls this directly
no test coverage detected