| 26 | |
| 27 | template<typename T, typename convAccT> |
| 28 | unsigned harris(Array<float> &x_out, Array<float> &y_out, |
| 29 | Array<float> &resp_out, const Array<T> &in, |
| 30 | const unsigned max_corners, const float min_response, |
| 31 | const float sigma, const unsigned filter_len, |
| 32 | const float k_thr) { |
| 33 | dim4 idims = in.dims(); |
| 34 | |
| 35 | // Window filter |
| 36 | auto h_filter = memAlloc<convAccT>(filter_len); |
| 37 | // Decide between rectangular or circular filter |
| 38 | if (sigma < 0.5f) { |
| 39 | for (unsigned i = 0; i < filter_len; i++) { |
| 40 | h_filter[i] = static_cast<T>(1) / (filter_len); |
| 41 | } |
| 42 | } else { |
| 43 | gaussian1D<convAccT>(h_filter.get(), static_cast<int>(filter_len), |
| 44 | sigma); |
| 45 | } |
| 46 | Array<convAccT> filter = |
| 47 | createDeviceDataArray<convAccT>(dim4(filter_len), h_filter.release()); |
| 48 | unsigned border_len = filter_len / 2 + 1; |
| 49 | |
| 50 | Array<T> ix = createEmptyArray<T>(idims); |
| 51 | Array<T> iy = createEmptyArray<T>(idims); |
| 52 | |
| 53 | // Compute first order derivatives |
| 54 | gradient<T>(iy, ix, in); |
| 55 | |
| 56 | Array<T> ixx = createEmptyArray<T>(idims); |
| 57 | Array<T> ixy = createEmptyArray<T>(idims); |
| 58 | Array<T> iyy = createEmptyArray<T>(idims); |
| 59 | |
| 60 | // Compute second-order derivatives |
| 61 | getQueue().enqueue(kernel::second_order_deriv<T>, ixx, ixy, iyy, |
| 62 | in.elements(), ix, iy); |
| 63 | |
| 64 | // Convolve second-order derivatives with proper window filter |
| 65 | ixx = convolve2<T, convAccT>(ixx, filter, filter, false); |
| 66 | ixy = convolve2<T, convAccT>(ixy, filter, filter, false); |
| 67 | iyy = convolve2<T, convAccT>(iyy, filter, filter, false); |
| 68 | |
| 69 | const unsigned corner_lim = in.elements() * 0.2f; |
| 70 | |
| 71 | Array<T> responses = createEmptyArray<T>(dim4(in.elements())); |
| 72 | |
| 73 | getQueue().enqueue(kernel::harris_responses<T>, responses, idims[0], |
| 74 | idims[1], ixx, ixy, iyy, k_thr, border_len); |
| 75 | |
| 76 | Array<float> xCorners = createEmptyArray<float>(dim4(corner_lim)); |
| 77 | Array<float> yCorners = createEmptyArray<float>(dim4(corner_lim)); |
| 78 | Array<float> respCorners = createEmptyArray<float>(dim4(corner_lim)); |
| 79 | |
| 80 | const unsigned min_r = |
| 81 | (max_corners > 0) ? 0U : static_cast<unsigned>(min_response); |
| 82 | |
| 83 | // Performs non-maximal suppression |
| 84 | getQueue().sync(); |
| 85 | unsigned corners_found = 0; |