quantization matrix wip
This commit is contained in:
@@ -18,7 +18,7 @@ impl Cfg{
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
//Init all descriptors:
|
//Init all descriptors:
|
||||||
let desc = DCT;
|
let desc = DCT::new();
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
//dbg!(args);
|
//dbg!(args);
|
||||||
|
|||||||
+76
-2
@@ -45,14 +45,76 @@ impl Descriptor for Median {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct 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],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Interprets a 64-element array as an 8x8 matrix
|
||||||
|
/// returns a nicely printable string
|
||||||
|
fn print_matrix<T: ToString>(array: [T; 64]) -> String {
|
||||||
|
let mut output = String::new();
|
||||||
|
for x in 0..8 {
|
||||||
|
for y in 0..8 {
|
||||||
|
output.push_str(&array[x*8+y].to_string());
|
||||||
|
output.push_str(",\t");
|
||||||
|
}
|
||||||
|
output.push('\n');
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Define S such that if (Q < 50), then S = 5000/Q, else S = 200 – 2*Q.
|
||||||
|
// The output quantization matrix Ts[i,j] at each location of row i and column j is such that
|
||||||
|
// Ts[i,j] = floor((S * Tb[i,j] + 50) / 100)
|
||||||
|
|
||||||
|
|
||||||
|
impl DCT {
|
||||||
|
pub fn new() -> DCT {
|
||||||
|
let base_quantization_matrix: [u8; 64] = [
|
||||||
|
16, 11, 10, 16, 24, 40, 51, 61,
|
||||||
|
12, 12, 14, 19, 26, 58, 60, 55,
|
||||||
|
14, 13, 16, 24, 40, 57, 69, 56,
|
||||||
|
14, 17, 22, 29, 51, 87, 80, 62,
|
||||||
|
18, 22, 37, 56, 6, 10, 103, 77,
|
||||||
|
24, 35, 55, 64, 8, 10, 113, 92,
|
||||||
|
49, 64, 78, 8, 10, 12, 12, 101,
|
||||||
|
72, 92, 95, 9, 11, 10, 103, 99,
|
||||||
|
];
|
||||||
|
DCT { quantization_matrix: base_quantization_matrix }
|
||||||
|
}
|
||||||
|
pub fn quantization_matrix(&self, quality: u8) -> [u8; 64] {
|
||||||
|
let mut quantization_matrix = self.quantization_matrix.clone();
|
||||||
|
let scalar: f32 = match quality {
|
||||||
|
1..=49 => 5000.0/quality as f32,
|
||||||
|
50..=100 => 200.0 - 2.0*quality as f32,
|
||||||
|
_ => 1.0 //TODO: error
|
||||||
|
};
|
||||||
|
for i in 0..64 {
|
||||||
|
quantization_matrix[i] = ((scalar * self.quantization_matrix[i] as f32 + 50.0) / 100.0).floor() as u8;
|
||||||
|
if quantization_matrix[i] == 0 {
|
||||||
|
quantization_matrix[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quantization_matrix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Descriptor for DCT {
|
impl Descriptor for DCT {
|
||||||
fn describe(&self, img: image::DynamicImage) -> u64 {
|
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 mut reconstructed: [u8; 64] = [0; 64];
|
let mut reconstructed: [u8; 64] = [0; 64];
|
||||||
let img = self.resize(img);
|
let img = self.resize(img);
|
||||||
let _ = 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 {
|
||||||
let k = (v*8)+u;
|
let k = (v*8)+u;
|
||||||
@@ -79,6 +141,17 @@ impl Descriptor for DCT {
|
|||||||
//println!{"{}", dct_values[k]}
|
//println!{"{}", dct_values[k]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println!("DCT-coefficients:\n {}", print_matrix(dct_values));
|
||||||
|
// Quantization:
|
||||||
|
for i in 0..64 {
|
||||||
|
dct_values[i] = (dct_values[i] / qmatrix[i] as f64).round();
|
||||||
|
}
|
||||||
|
println!("DCT-coefficients, quantized:\n {}", print_matrix(dct_values));
|
||||||
|
// De-quantization:
|
||||||
|
for i in 0..64 {
|
||||||
|
dct_values[i] = dct_values[i] * qmatrix[i] as f64;
|
||||||
|
}
|
||||||
|
println!("DCT-coefficients, de-quantized:\n {}", print_matrix(dct_values));
|
||||||
for k in 0..64 {
|
for k in 0..64 {
|
||||||
let x = (k%8) as f64;
|
let x = (k%8) as f64;
|
||||||
let y = (k/8) as f64;
|
let y = (k/8) as f64;
|
||||||
@@ -106,6 +179,7 @@ impl Descriptor for DCT {
|
|||||||
//println!("Reconstructed pixel: {}", sum);
|
//println!("Reconstructed pixel: {}", sum);
|
||||||
reconstructed[k] = std::cmp::min(255_u8, sum as u8);
|
reconstructed[k] = std::cmp::min(255_u8, sum as u8);
|
||||||
}
|
}
|
||||||
|
//println!("{}", print_matrix(reconstructed));
|
||||||
save_buffer(
|
save_buffer(
|
||||||
"reconstructed.png",
|
"reconstructed.png",
|
||||||
&reconstructed,
|
&reconstructed,
|
||||||
|
|||||||
Reference in New Issue
Block a user