368{
369 size_t seed = std::hash<std::string_view> {}(Reflect::enum_to_string(op));
370
371 std::visit([&seed](const auto& p) {
372 using T = std::decay_t<decltype(p)>;
373 if constexpr (std::is_same_v<T, std::monostate>) {
374 } else if constexpr (std::is_same_v<T, ThresholdParams>) {
375 hash_combine(seed, std::hash<float> {}(p.value));
376 } else if constexpr (std::is_same_v<T, ThresholdAdaptiveParams>) {
377 hash_combine(seed, std::hash<uint32_t> {}(p.block_size));
379 } else if constexpr (std::is_same_v<T, NormalizeRangeParams>) {
382 } else if constexpr (std::is_same_v<T, GaussianBlurParams>) {
384 } else if constexpr (std::is_same_v<T, FilterSeparableParams>) {
385 for (float v : p.kernel_x)
387 for (float v : p.kernel_y)
389 } else if constexpr (std::is_same_v<T, CannyParams>) {
391 hash_combine(seed, std::hash<float> {}(p.low_threshold));
392 hash_combine(seed, std::hash<float> {}(p.high_threshold));
393 } else if constexpr (std::is_same_v<T, MorphParams>) {
395 } else if constexpr (std::is_same_v<T, HarrisParams>) {
398 } else if constexpr (std::is_same_v<T, ExtractPeaksParams>) {
400 hash_combine(seed, std::hash<uint32_t> {}(p.nms_radius));
401 } else if constexpr (std::is_same_v<T, TrackKeypointsParams>) {
402 hash_combine(seed, std::hash<uint32_t> {}(p.window_radius));
403 hash_combine(seed, std::hash<uint32_t> {}(p.max_iterations));
404 hash_combine(seed, std::hash<float> {}(p.eigen_threshold));
405 hash_combine(seed, std::hash<float> {}(p.error_threshold));
406 } else if constexpr (std::is_same_v<T, FindContoursParams>) {
408 hash_combine(seed, std::hash<uint32_t> {}(p.max_contours));
409 hash_combine(seed, std::hash<uint32_t> {}(p.max_points_per_contour));
411 } else if constexpr (std::is_same_v<T, ConnectedComponentsParams>) {
412 hash_combine(seed, std::hash<bool> {}(p.export_labels));
414 }
415 },
416 params);
417
418 return seed;
419}
void hash_combine(size_t &seed, size_t value)
Combine a hash into an existing seed, FNV-style.