37 std::span<const float> gray, uint32_t w, uint32_t
h,
40 const size_t n =
static_cast<size_t>(w) *
h;
42 auto grad =
sobel(gray, w,
h);
44 std::vector<float> ixx(n), iyy(n), ixy(n);
46 std::for_each(std::execution::par_unseq,
47 std::views::iota(
size_t { 0 }, n).begin(),
48 std::views::iota(
size_t { 0 }, n).end(),
50 const float dx = grad.dx[i];
51 const float dy = grad.dy[i];
61 std::vector<float> response(n);
63 std::for_each(std::execution::par_unseq,
64 std::views::iota(
size_t { 0 }, n).begin(),
65 std::views::iota(
size_t { 0 }, n).end(),
67 const float det = sxx[i] * syy[i] - sxy[i] * sxy[i];
68 const float trace = sxx[i] + syy[i];
69 response[i] = std::max(0.0F, det - k * trace * trace);
72 normalize_response(response);
78 std::span<const float> gray,
79 std::span<float> dx, std::span<float> dy, std::span<float> tmp,
80 std::span<float> ixx, std::span<float> iyy, std::span<float> ixy,
81 std::span<float> sxx, std::span<float> syy, std::span<float> sxy,
83 uint32_t w, uint32_t
h,
85 std::span<const float> kern)
87 const size_t n =
static_cast<size_t>(w) *
h;
89 sobel(gray, dx, dy, tmp, w,
h);
92 const float* dx_ptr = dx.data();
93 const float* dy_ptr = dy.data();
94 float* ixx_ptr = ixx.data();
95 float* iyy_ptr = iyy.data();
96 float* ixy_ptr = ixy.data();
98 std::for_each(std::execution::par_unseq,
99 std::views::iota(
size_t { 0 }, n).begin(),
100 std::views::iota(
size_t { 0 }, n).end(),
102 const float gx = dx_ptr[i];
103 const float gy = dy_ptr[i];
104 ixx_ptr[i] = gx * gx;
105 iyy_ptr[i] = gy * gy;
106 ixy_ptr[i] = gx * gy;
110 const float* h_src[3] = { ixx.data(), iyy.data(), ixy.data() };
111 float* h_dst[3] = { dx.data(), dy.data(), tmp.data() };
114 const float* v_src[3] = { dx.data(), dy.data(), tmp.data() };
115 float* v_dst[3] = { sxx.data(), syy.data(), sxy.data() };
119 const float* sxx_ptr = sxx.data();
120 const float* syy_ptr = syy.data();
121 const float* sxy_ptr = sxy.data();
122 float* dst_ptr =
dst.data();
124#ifdef MAYAFLUX_ARCH_X64
125 const __m256 k_vec = _mm256_set1_ps(k);
126 const __m256 zero = _mm256_setzero_ps();
129 for (; i + 8 <= n; i += 8) {
130 const __m256 s0 = _mm256_loadu_ps(sxx_ptr + i);
131 const __m256 s1 = _mm256_loadu_ps(syy_ptr + i);
132 const __m256 s01 = _mm256_loadu_ps(sxy_ptr + i);
134 const __m256 det = _mm256_sub_ps(
135 _mm256_mul_ps(s0, s1),
136 _mm256_mul_ps(s01, s01));
137 const __m256 trace = _mm256_add_ps(s0, s1);
138 const __m256 resp = _mm256_max_ps(zero,
139 _mm256_fnmadd_ps(k_vec,
140 _mm256_mul_ps(trace, trace),
143 _mm256_storeu_ps(dst_ptr + i, resp);
146 const float s0 = sxx_ptr[i];
147 const float s1 = syy_ptr[i];
148 const float s01 = sxy_ptr[i];
149 const float det = s0 * s1 - s01 * s01;
150 const float trace = s0 + s1;
151 dst_ptr[i] = std::max(0.0F, det - k * trace * trace);
154#elif defined(MAYAFLUX_ARCH_ARM64)
155 const float32x4_t k_vec = vdupq_n_f32(k);
156 const float32x4_t zero = vdupq_n_f32(0.0F);
159 for (; i + 4 <= n; i += 4) {
160 const float32x4_t s0 = vld1q_f32(sxx_ptr + i);
161 const float32x4_t s1 = vld1q_f32(syy_ptr + i);
162 const float32x4_t s01 = vld1q_f32(sxy_ptr + i);
164 const float32x4_t det = vsubq_f32(
166 vmulq_f32(s01, s01));
167 const float32x4_t trace = vaddq_f32(s0, s1);
168 const float32x4_t resp = vmaxq_f32(zero,
169 vmlsq_f32(det, k_vec, vmulq_f32(trace, trace)));
171 vst1q_f32(dst_ptr + i, resp);
174 const float s0 = sxx_ptr[i];
175 const float s1 = syy_ptr[i];
176 const float s01 = sxy_ptr[i];
177 const float det = s0 * s1 - s01 * s01;
178 const float trace = s0 + s1;
179 dst_ptr[i] = std::max(0.0F, det - k * trace * trace);
183 for (
size_t i = 0; i < n; ++i) {
184 const float s0 = sxx_ptr[i];
185 const float s1 = syy_ptr[i];
186 const float s01 = sxy_ptr[i];
187 const float det = s0 * s1 - s01 * s01;
188 const float trace = s0 + s1;
189 dst_ptr[i] = std::max(0.0F, det - k * trace * trace);
194 normalize_response(
dst.first(n));