refactor dct and quality
This commit is contained in:
@@ -19,10 +19,9 @@ impl Cfg{
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
//Init all descriptors:
|
//Init all descriptors:
|
||||||
let desc = DCT::new();
|
let desc = DCT::new().with_quality(50);
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
//dbg!(args);
|
|
||||||
|
|
||||||
let cfg = Cfg::load(&args)
|
let cfg = Cfg::load(&args)
|
||||||
.expect("Error loading config");
|
.expect("Error loading config");
|
||||||
|
|||||||
+59
-55
@@ -2,14 +2,9 @@ use image::{save_buffer, GenericImageView};
|
|||||||
use std::f64::consts::{PI, SQRT_2};
|
use std::f64::consts::{PI, SQRT_2};
|
||||||
use crate::descriptors::{Descriptor, print_matrix, DCT};
|
use crate::descriptors::{Descriptor, print_matrix, DCT};
|
||||||
|
|
||||||
/// A struct representing a Discrete Cosine Transform descriptor
|
|
||||||
/// Transforms an image into an 8x8 grayscale version, and transforms it
|
|
||||||
/// into the frequency domain
|
|
||||||
// pub struct DCT {
|
|
||||||
// quantization_matrix: [u8; 64],
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl DCT {
|
impl DCT {
|
||||||
|
/// Returns a new DCT instance with a calculated DCT matrix.
|
||||||
pub fn new() -> DCT {
|
pub fn new() -> DCT {
|
||||||
let base_quantization_matrix: [u8; 64] = [
|
let base_quantization_matrix: [u8; 64] = [
|
||||||
16, 11, 10, 16, 24, 40, 51, 61,
|
16, 11, 10, 16, 24, 40, 51, 61,
|
||||||
@@ -23,8 +18,10 @@ impl DCT {
|
|||||||
];
|
];
|
||||||
DCT { quantization_matrix: base_quantization_matrix }
|
DCT { quantization_matrix: base_quantization_matrix }
|
||||||
}
|
}
|
||||||
pub fn quantization_matrix(&self, quality: u8) -> [u8; 64] {
|
|
||||||
let mut quantization_matrix = self.quantization_matrix.clone();
|
// Builds DCT with given quality value
|
||||||
|
pub fn with_quality(mut self, quality: u8) -> Self {
|
||||||
|
let mut quantization_matrix: [u8; 64] = [0; 64];
|
||||||
let scalar: f32 = match quality {
|
let scalar: f32 = match quality {
|
||||||
1..=49 => 5000.0/quality as f32,
|
1..=49 => 5000.0/quality as f32,
|
||||||
50..=100 => 200.0 - 2.0*quality as f32,
|
50..=100 => 200.0 - 2.0*quality as f32,
|
||||||
@@ -36,54 +33,14 @@ impl DCT {
|
|||||||
quantization_matrix[i] = 1;
|
quantization_matrix[i] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
quantization_matrix
|
self.quantization_matrix = quantization_matrix;
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO
|
pub fn dct(&self, img: image::DynamicImage) -> [f64; 64] {
|
||||||
// pub fn dct(&self, img: image::DynamicImage) -> [f64; 64] {
|
//let qmatrix = self.quantization_matrix(self.quality);
|
||||||
// }
|
//println!("Q-{} quantization matrix:\n{}", self.quality, print_matrix(qmatrix));
|
||||||
|
|
||||||
pub fn idct(&self, dct_values: [f64; 64]) -> [u8; 64] {
|
|
||||||
let mut reconstructed: [u8; 64] = [0; 64];
|
|
||||||
for k in 0..64 {
|
|
||||||
let x = (k%8) as f64;
|
|
||||||
let y = (k/8) as f64;
|
|
||||||
let mut sum = 0.0;
|
|
||||||
for u in 0..8 {
|
|
||||||
for v in 0..8 {
|
|
||||||
let mut alpha = 1.0;
|
|
||||||
if u == 0 {
|
|
||||||
alpha = alpha / SQRT_2
|
|
||||||
}
|
|
||||||
if v == 0 {
|
|
||||||
alpha = alpha / SQRT_2
|
|
||||||
}
|
|
||||||
let uv = (v*8)+u;
|
|
||||||
let v = v as f64;
|
|
||||||
let u = u as f64;
|
|
||||||
sum +=
|
|
||||||
alpha *
|
|
||||||
dct_values[uv] *
|
|
||||||
((2.0 * x + 1.0) * u * PI / 16.0).cos() *
|
|
||||||
((2.0 * y + 1.0) * v * PI / 16.0).cos()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sum = 127.0 + (0.25 * sum).round();
|
|
||||||
reconstructed[k] = std::cmp::min(255_u8, sum as u8);
|
|
||||||
}
|
|
||||||
reconstructed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Descriptor for DCT {
|
|
||||||
fn describe(&self, img: image::DynamicImage) -> u64 {
|
|
||||||
let quality: u8 = 15;
|
|
||||||
let qmatrix = self.quantization_matrix(quality);
|
|
||||||
|
|
||||||
println!("Base quantization matrix:\n{}", print_matrix(self.quantization_matrix));
|
|
||||||
println!("Q-{} quantization matrix:\n{}", quality, print_matrix(qmatrix));
|
|
||||||
let mut dct_values: [f64; 64] = [0.0; 64];
|
let mut dct_values: [f64; 64] = [0.0; 64];
|
||||||
let img = self.resize(img);
|
|
||||||
img.save("resize.png").expect("Error saving file");
|
img.save("resize.png").expect("Error saving file");
|
||||||
for u in 0..8 {
|
for u in 0..8 {
|
||||||
for v in 0..8 {
|
for v in 0..8 {
|
||||||
@@ -111,19 +68,64 @@ impl Descriptor for DCT {
|
|||||||
//println!{"{}", dct_values[k]}
|
//println!{"{}", dct_values[k]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dct_values
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn idct(&self, dct_values: [f64; 64]) -> [u8; 64] {
|
||||||
|
let mut reconstructed: [u8; 64] = [0; 64];
|
||||||
|
for k in 0..64 {
|
||||||
|
let x = (k%8) as f64;
|
||||||
|
let y = (k/8) as f64;
|
||||||
|
let mut sum = 0.0;
|
||||||
|
for u in 0..8 {
|
||||||
|
for v in 0..8 {
|
||||||
|
let mut alpha = 1.0;
|
||||||
|
if u == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
let uv = (v*8)+u;
|
||||||
|
let v = v as f64;
|
||||||
|
let u = u as f64;
|
||||||
|
sum +=
|
||||||
|
alpha *
|
||||||
|
dct_values[uv] *
|
||||||
|
((2.0 * x + 1.0) * u * PI / 16.0).cos() *
|
||||||
|
((2.0 * y + 1.0) * v * PI / 16.0).cos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum = 127.0 + (0.25 * sum).round();
|
||||||
|
reconstructed[k] = std::cmp::min(255_u8, sum as u8);
|
||||||
|
}
|
||||||
|
reconstructed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Descriptor for DCT {
|
||||||
|
fn describe(&self, img: image::DynamicImage) -> u64 {
|
||||||
|
let img = self.resize(img);
|
||||||
|
let mut dct_values = self.dct(img);
|
||||||
println!("DCT-coefficients:\n {}", print_matrix(dct_values));
|
println!("DCT-coefficients:\n {}", print_matrix(dct_values));
|
||||||
|
|
||||||
// Quantization:
|
// Quantization:
|
||||||
|
println!("Using quantization matrix:\n{}", print_matrix(self.quantization_matrix));
|
||||||
for i in 0..64 {
|
for i in 0..64 {
|
||||||
dct_values[i] = (dct_values[i] / qmatrix[i] as f64).round();
|
dct_values[i] = (dct_values[i] / self.quantization_matrix[i] as f64).round();
|
||||||
}
|
}
|
||||||
println!("DCT-coefficients, quantized:\n {}", print_matrix(dct_values));
|
println!("DCT-coefficients, quantized:\n {}", print_matrix(dct_values));
|
||||||
|
|
||||||
// De-quantization:
|
// De-quantization:
|
||||||
for i in 0..64 {
|
for i in 0..64 {
|
||||||
dct_values[i] = dct_values[i] * qmatrix[i] as f64;
|
dct_values[i] = dct_values[i] * self.quantization_matrix[i] as f64;
|
||||||
}
|
}
|
||||||
println!("DCT-coefficients, de-quantized:\n {}", print_matrix(dct_values));
|
println!("DCT-coefficients, de-quantized:\n {}", print_matrix(dct_values));
|
||||||
|
|
||||||
|
// Reconstruction original pixel values:
|
||||||
let reconstructed = self.idct(dct_values);
|
let reconstructed = self.idct(dct_values);
|
||||||
println!("Reconstructed pixel values:\n{}", print_matrix(reconstructed));
|
println!("Reconstructed pixel values:\n{}", print_matrix(reconstructed));
|
||||||
|
|
||||||
save_buffer(
|
save_buffer(
|
||||||
"reconstructed.png",
|
"reconstructed.png",
|
||||||
&reconstructed,
|
&reconstructed,
|
||||||
@@ -131,6 +133,8 @@ impl Descriptor for DCT {
|
|||||||
8,
|
8,
|
||||||
image::ColorType::L8
|
image::ColorType::L8
|
||||||
).expect("Error saving buffer");
|
).expect("Error saving buffer");
|
||||||
|
|
||||||
|
// Calculating descriptor from dct values:
|
||||||
let mut mask: u64 = 0;
|
let mut mask: u64 = 0;
|
||||||
for dct in dct_values {
|
for dct in dct_values {
|
||||||
if dct > 0.0 {
|
if dct > 0.0 {
|
||||||
|
|||||||
@@ -13,22 +13,25 @@ pub trait Descriptor {
|
|||||||
|
|
||||||
/// Interprets a 64-element array as an 8x8 matrix
|
/// Interprets a 64-element array as an 8x8 matrix
|
||||||
/// returns a nicely printable string
|
/// returns a nicely printable string
|
||||||
fn print_matrix<T: ToString>(array: [T; 64]) -> String {
|
fn print_matrix<T: ToString + std::fmt::Display>(array: [T; 64]) -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
for x in 0..8 {
|
for x in 0..8 {
|
||||||
for y in 0..8 {
|
for y in 0..8 {
|
||||||
output.push_str(&array[x*8+y].to_string());
|
let element = format!("{:.2}", &array[x*8+y]);
|
||||||
output.push_str(",\t");
|
let element = format!("{:8}\t", element);
|
||||||
|
output.push_str(&element);
|
||||||
}
|
}
|
||||||
output.push('\n');
|
output.push('\n');
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A struct representing a Discrete Cosine Transform descriptor
|
||||||
|
/// Transforms an image into an 8x8 grayscale version, and transforms it
|
||||||
|
/// into the frequency domain
|
||||||
pub struct DCT {
|
pub struct DCT {
|
||||||
quantization_matrix: [u8; 64],
|
quantization_matrix: [u8; 64]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod dct;
|
pub mod dct;
|
||||||
|
|
||||||
// fn median64<T: Ord + Copy>(values: &[T]) -> T {
|
// fn median64<T: Ord + Copy>(values: &[T]) -> T {
|
||||||
|
|||||||
Reference in New Issue
Block a user