#include "wvlt_rgb.hpp" #include "math.hpp" #include #include #include #include #include namespace fingerprints { static const int size = 512; wvlt_rgb::pre_fingerprint wvlt_rgb::pre_calculate(av::frame const & frame) { auto const image = to_raw_rgb_image(crop_to_square(frame), size, size); wvlt_rgb::pre_fingerprint ret; // for every color for(unsigned int color = 0; color < 3; ++color){ auto & vector = ret[color]; vector.assign(make_u(image.width() * image.height()), 0); for(unsigned int n = 0; n < make_u(image.width() * image.height()); ++n){ vector[n] = 2.0 * image.data[3*n + color] / double(255) - 1.0; } wvlt::wavelet_2D(vector.data(), make_u(image.width()), make_u(image.height())); } return ret; } wvlt_rgb wvlt_rgb::calculate(av::frame const & frame){ auto const image = to_raw_rgb_image(crop_to_square(frame), size, size); wvlt_rgb ret; std::vector vector(make_u(image.width() * image.height()), 0); // for every color for(unsigned int color = 0; color < 3; ++color){ auto& coefficient_array = color == 0 ? ret.reds : (color == 1 ? ret.greens : ret.blues); unsigned int array_index = 0; for(unsigned int n = 0; n < make_u(image.width() * image.height()); ++n){ vector[n] = 2.0 * image.data[3*n + color] / double(255) - 1.0; } wvlt::wavelet_2D(vector.data(), make_u(image.width()), make_u(image.height())); auto copy = vector; for(auto & x : copy) x = std::abs(x); auto const n_coefficients = coefficient_array.size(); std::nth_element(copy.begin(), copy.begin() + n_coefficients, copy.end(), std::greater()); auto const threshold = copy[n_coefficients-1]; for(unsigned int n = 0; n < vector.size(); ++n){ auto const x = vector[n]; if(std::abs(x) >= threshold) { coefficient_array[array_index++] = std::make_pair(n, x); } if(array_index >= coefficient_array.size()) { break; } } } return ret; } double wvlt_rgb::distance_to(pre_fingerprint const & fingerprint) const { double distance = 0; for(unsigned int color = 0; color < 3; ++color){ auto const & coefficients = color == 0 ? reds : (color == 1 ? greens : blues); for(auto&& p : coefficients){ auto const x = p.second; auto const y = fingerprint[color][p.first]; distance += square(x - y) - square(y); } } return distance; } } // namespace fingerprints