81 lines
2.3 KiB
Rust
81 lines
2.3 KiB
Rust
//! Descriptors that can be used to describe an image.
|
|
//! If two images are (almost) the same, their descriptions will be the same.
|
|
|
|
use image::GenericImageView;
|
|
|
|
pub trait Descriptor {
|
|
/// Print the name of the descriptor,
|
|
fn info(&self) -> String;
|
|
fn resize(&self, img: &image::DynamicImage) -> image::DynamicImage {
|
|
img.grayscale().thumbnail_exact(8, 8)
|
|
}
|
|
fn describe(&self, img: &image::DynamicImage) -> u64;
|
|
fn distance(&self, a: u64, b: u64) -> u64 {
|
|
(a^b).count_ones().into()
|
|
}
|
|
}
|
|
|
|
/// Interprets a 64-element array as an 8x8 matrix
|
|
/// returns a nicely printable string
|
|
fn print_matrix<T: ToString + std::fmt::Display>(array: [T; 64]) -> String {
|
|
let mut output = String::new();
|
|
for x in 0..8 {
|
|
for y in 0..8 {
|
|
let element = format!("{:.2}", &array[x*8+y]);
|
|
let element = format!("{:8}\t", element);
|
|
output.push_str(&element);
|
|
}
|
|
output.push('\n');
|
|
}
|
|
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 {
|
|
quantization_matrix: [u8; 64]
|
|
}
|
|
pub mod dct;
|
|
|
|
fn median64<T: Ord + Copy>(values: &[T]) -> T {
|
|
let mut sorted_values = values.to_vec();
|
|
sorted_values.sort();
|
|
let len = sorted_values.len();
|
|
sorted_values[len/2]
|
|
}
|
|
|
|
pub struct Median;
|
|
|
|
impl Descriptor for Median {
|
|
fn info(&self) -> String {
|
|
"median".to_string()
|
|
}
|
|
|
|
fn describe(&self, img: &image::DynamicImage) -> u64 {
|
|
let img = self.resize(img);
|
|
let mut values: [u8; 64] = [0; 64];
|
|
let mut i: usize = 0;
|
|
for (_, _, pix) in img.pixels() {
|
|
values[i] = pix[0];
|
|
i = i+1;
|
|
}
|
|
let median = median64(&values);
|
|
let mut mask: u64 = 0;
|
|
img.save("debug.png").unwrap();
|
|
for (_, _, pix) in img.pixels() {
|
|
if pix[0] > median {
|
|
mask += 1;
|
|
}
|
|
mask = mask << 1;
|
|
}
|
|
mask
|
|
}
|
|
}
|
|
|
|
pub fn get_all_descriptors() -> Vec<Box<dyn Descriptor>> {
|
|
let mut descriptors: Vec<Box<dyn Descriptor>> = Vec::with_capacity(2);
|
|
descriptors.push(Box::new(DCT::new()));
|
|
descriptors.push(Box::new(Median));
|
|
descriptors
|
|
} |