|
|
|
#include "downscale.hpp"
|
|
|
|
|
|
|
|
#include <image_io.hpp>
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
#include <libavutil/frame.h>
|
|
|
|
#include <libswscale/swscale.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
static raw_rgb_image downscale_step(AVFrame const * frame, int factor) {
|
|
|
|
raw_rgb_image image(frame->width / factor, frame->height / factor);
|
|
|
|
|
|
|
|
auto context = sws_getContext(frame->width, frame->height, static_cast<AVPixelFormat>(frame->format), image.width(), image.height(), image.format(), 0, nullptr, nullptr, nullptr);
|
|
|
|
if(!context) throw std::runtime_error("boem sws context");
|
|
|
|
sws_scale (context, {frame->data}, {frame->linesize}, 0, frame->height, {image.frame->data}, {image.frame->linesize});
|
|
|
|
sws_freeContext(context);
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
static raw_rgb_image downscale_to(const av::frame &frame, int w, int h){
|
|
|
|
// ffmpeg doesnt let us downscale all the way to 5 at once :(, so we do a loop
|
|
|
|
raw_rgb_image image;
|
|
|
|
auto new_frame = frame.get();
|
|
|
|
while(new_frame->width > 8*w && new_frame->height > 8*h){
|
|
|
|
image = downscale_step(new_frame, 4);
|
|
|
|
new_frame = image.frame.get();
|
|
|
|
}
|
|
|
|
return to_raw_rgb_image(image.frame, w, h);
|
|
|
|
}
|
|
|
|
|
|
|
|
downscale downscale::pre_calculate(av::frame const & frame){
|
|
|
|
auto const image = downscale_to(crop_to_square(frame), 5, 5);
|
|
|
|
|
|
|
|
downscale ret;
|
|
|
|
ret.data.assign(image.data.size(), 0);
|
|
|
|
|
|
|
|
std::copy(image.data.begin(), image.data.end(), ret.data.begin());
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
downscale downscale::calculate(const av::frame& frame){
|
|
|
|
return pre_calculate(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
static double square(double x){
|
|
|
|
return x*x;
|
|
|
|
}
|
|
|
|
|
|
|
|
double downscale::distance_to(const downscale& fingerprint) const {
|
|
|
|
assert(data.size() == fingerprint.data.size());
|
|
|
|
|
|
|
|
double distance = 0;
|
|
|
|
for(size_t i = 0; i < data.size(); ++i){
|
|
|
|
distance += square(data[i] - fingerprint.data[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return distance;
|
|
|
|
}
|