| 23 | |
| 24 | template<typename T> |
| 25 | void fast_pyramid(vector<unsigned> &feat_pyr, vector<Array<float>> &x_pyr, |
| 26 | vector<Array<float>> &y_pyr, vector<unsigned> &lvl_best, |
| 27 | vector<float> &lvl_scl, vector<Array<T>> &img_pyr, |
| 28 | const Array<T> &in, const float fast_thr, |
| 29 | const unsigned max_feat, const float scl_fctr, |
| 30 | const unsigned levels, const unsigned patch_size) { |
| 31 | dim4 indims = in.dims(); |
| 32 | unsigned min_side = std::min(indims[0], indims[1]); |
| 33 | unsigned max_levels = 0; |
| 34 | float scl_sum = 0.f; |
| 35 | |
| 36 | for (unsigned i = 0; i < levels; i++) { |
| 37 | min_side /= scl_fctr; |
| 38 | |
| 39 | // Minimum image side for a descriptor to be computed |
| 40 | if (min_side < patch_size || max_levels == levels) { break; } |
| 41 | |
| 42 | max_levels++; |
| 43 | scl_sum += 1.f / std::pow(scl_fctr, static_cast<float>(i)); |
| 44 | } |
| 45 | |
| 46 | // Compute number of features to keep for each level |
| 47 | lvl_best.resize(max_levels); |
| 48 | lvl_scl.resize(max_levels); |
| 49 | unsigned feat_sum = 0; |
| 50 | for (unsigned i = 0; i < max_levels - 1; i++) { |
| 51 | auto scl = std::pow(scl_fctr, static_cast<float>(i)); |
| 52 | lvl_scl[i] = scl; |
| 53 | |
| 54 | lvl_best[i] = ceil((max_feat / scl_sum) / lvl_scl[i]); |
| 55 | feat_sum += lvl_best[i]; |
| 56 | } |
| 57 | lvl_scl[max_levels - 1] = |
| 58 | std::pow(scl_fctr, static_cast<float>(max_levels) - 1); |
| 59 | lvl_best[max_levels - 1] = max_feat - feat_sum; |
| 60 | |
| 61 | // Hold multi-scale image pyramids |
| 62 | static const dim4 dims0; |
| 63 | static const CParam<T> emptyCParam(NULL, dims0.get(), dims0.get()); |
| 64 | |
| 65 | img_pyr.reserve(max_levels); |
| 66 | |
| 67 | // Create multi-scale image pyramid |
| 68 | for (unsigned i = 0; i < max_levels; i++) { |
| 69 | if (i == 0) { |
| 70 | // First level is used in its original size |
| 71 | img_pyr.push_back(in); |
| 72 | } else { |
| 73 | // Resize previous level image to current level dimensions |
| 74 | dim4 dims(round(indims[0] / lvl_scl[i]), |
| 75 | round(indims[1] / lvl_scl[i])); |
| 76 | |
| 77 | img_pyr.push_back(createEmptyArray<T>(dims)); |
| 78 | img_pyr[i] = |
| 79 | resize(img_pyr[i - 1], dims[0], dims[1], AF_INTERP_BILINEAR); |
| 80 | } |
| 81 | } |
| 82 | |