mirror of
https://github.com/akai-katto/dandere2x.git
synced 2026-04-11 00:11:14 +02:00
133 lines
5.4 KiB
C++
133 lines
5.4 KiB
C++
|
|
/*
|
|
This file is part of the Dandere2x project.
|
|
|
|
Dandere2x is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Dandere2x is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Dandere2x. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
========= Copyright akai_katto 2021, All rights reserved. ============
|
|
Original Author: akai_katto
|
|
Purpose: Dandere2x is built to have multiple evaluators, i.e the user
|
|
can use MSE (mean squared error) or SSIM-MSE (a variation of
|
|
SSIM I wrote that also let's MSE vote.)
|
|
|
|
This class allows an evalutor object to be instantiated
|
|
wherein the code can request what evaluation metric they want
|
|
to use, allowing for one code to access both MSE and SSIM-MSE
|
|
evaluation tools.
|
|
|
|
As a general rule of thumb, evaluators are passed references,
|
|
while in the rest of code, shared_ptr is passed. This stems
|
|
from that the inner most calls should have as little overhead
|
|
as possible.
|
|
===================================================================== */
|
|
|
|
#ifndef CPP_REWORK_ABSTRACTEVALUATOR_H
|
|
#define CPP_REWORK_ABSTRACTEVALUATOR_H
|
|
|
|
// internal includes
|
|
#include <cmath>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <memory>
|
|
#include "../frame/Frame.h"
|
|
#include "../plugins/block_plugins/Block.h"
|
|
|
|
class AbstractEvaluator {
|
|
|
|
public:
|
|
|
|
|
|
bool evaluate(const Frame ¤t_frame,
|
|
const Frame &next_frame,
|
|
const Frame &next_frame_compressed,
|
|
const Block &block,
|
|
const int block_size) {
|
|
return evaluate(current_frame, next_frame, next_frame_compressed,
|
|
block.x_start, block.y_start,
|
|
block.x_end, block.y_end, block_size);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Any evaluator will have to give a binary "yes the matched block passes the constant-quality check" or
|
|
// "no it doesn't". Since each metric is different (i.e higher number in some means better, lower number means worse)
|
|
// it's left to the implementation to determine what quantifies that a block is matched or not.
|
|
//-----------------------------------------------------------------------------
|
|
bool evaluate(const Frame ¤t_frame,
|
|
const Frame &next_frame,
|
|
const Frame &next_frame_compressed,
|
|
const int current_frame_x, const int current_frame_y,
|
|
const int next_frame_x, const int next_frame_y,
|
|
const int block_size) {
|
|
|
|
// primitive sanity check for any evaluation
|
|
if (current_frame.block_out_of_bounds(current_frame_x, current_frame_y, block_size) ||
|
|
current_frame.block_out_of_bounds(next_frame_x, next_frame_y, block_size))
|
|
return false;
|
|
|
|
return evaluate_implementation(current_frame, next_frame, next_frame_compressed, current_frame_x,
|
|
current_frame_y,
|
|
next_frame_x, next_frame_y, block_size);
|
|
}
|
|
|
|
// Some handy functions wherever an evaluator is used.
|
|
double psnr_two_frames(const Frame ¤t_frame, const Frame &next_frame) {
|
|
double sum = 0;
|
|
|
|
for (int x = 0; x < current_frame.get_width(); x++) {
|
|
for (int y = 0; y < current_frame.get_height(); y++) {
|
|
sum += square(current_frame.get_color(x, y), next_frame.get_color(x, y));
|
|
}
|
|
}
|
|
|
|
sum /= (next_frame.get_height() * next_frame.get_width());
|
|
|
|
double result = 20 * log10(255) - 10 * log10(sum);
|
|
return result;
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual bool evaluate_implementation(const Frame ¤t_frame,
|
|
const Frame &next_frame,
|
|
const Frame &next_frame_compressed,
|
|
const int current_frame_x, const int current_frame_y,
|
|
const int next_frame_x, const int next_frame_y,
|
|
const int block_size) = 0;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: A simple square function which calculuates the "distance" or loss
|
|
// between two colors.
|
|
//-----------------------------------------------------------------------------
|
|
int square(const Frame::Color &color_a, const Frame::Color &color_b) {
|
|
|
|
int r1 = (int) color_a.r;
|
|
int r2 = (int) color_b.r;
|
|
int g1 = (int) color_a.g;
|
|
int g2 = (int) color_b.g;
|
|
int b1 = (int) color_a.b;
|
|
int b2 = (int) color_b.b;
|
|
|
|
// Developer Note: We're using multiplication here and addition rather than POW
|
|
// to avoid having to work with doubles for computational improvements.
|
|
return (r2 - r1) * (r2 - r1) + (g2 - g1) * (g2 - g1) + (b2 - b1) * (b2 - b1);
|
|
}
|
|
|
|
};
|
|
|
|
|
|
#endif //CPP_REWORK_ABSTRACTEVALUATOR_H
|