Made as lib
This commit is contained in:
parent
af372b21b0
commit
64a9d5402d
|
@ -5,3 +5,7 @@ authors = ["Thomas Forgione <thomas@tforgione.fr>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
image = "*"
|
image = "*"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "psnr"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
extern crate image;
|
||||||
|
|
||||||
|
use image::{Pixel, GenericImage, ImageResult, ImageError};
|
||||||
|
|
||||||
|
pub fn psnr<P: Pixel<Subpixel=u8>, T: GenericImage<Pixel=P>>(img1: &T, img2: &T) -> ImageResult<f64> {
|
||||||
|
|
||||||
|
let twenty_log10_max: f64 = 20.0 * (std::u32::MAX as f64).log10();
|
||||||
|
|
||||||
|
if img1.dimensions() != img2.dimensions() {
|
||||||
|
return Err(ImageError::DimensionError);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mse = 0.0;
|
||||||
|
|
||||||
|
for x in 0 .. img1.dimensions().0 {
|
||||||
|
for y in 0 .. img1.dimensions().1 {
|
||||||
|
|
||||||
|
let p1 = img1.get_pixel(x, y).to_rgba();
|
||||||
|
let p2 = img2.get_pixel(x, y).to_rgba();
|
||||||
|
|
||||||
|
let dx = p1.data[0] as f64 - p2.data[0] as f64;
|
||||||
|
let dy = p1.data[1] as f64 - p2.data[1] as f64;
|
||||||
|
let dz = p1.data[2] as f64 - p2.data[2] as f64;
|
||||||
|
|
||||||
|
let dx = dx * dx;
|
||||||
|
let dy = dy * dy;
|
||||||
|
let dz = dz * dz;
|
||||||
|
|
||||||
|
mse += dx + dy + dz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mse /= (img1.dimensions().0 * img1.dimensions().1 * 3) as f64;
|
||||||
|
Ok(twenty_log10_max - 10.0 * mse.log10())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn psnr_files(path1: &str, path2: &str) -> ImageResult<f64> {
|
||||||
|
let img1 = image::open(path1)?;
|
||||||
|
let img2 = image::open(path2)?;
|
||||||
|
psnr(&img1, &img2)
|
||||||
|
}
|
51
src/main.rs
51
src/main.rs
|
@ -1,50 +1,13 @@
|
||||||
extern crate image;
|
extern crate image;
|
||||||
|
extern crate psnr;
|
||||||
|
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use image::{ImageResult, ImageError};
|
use image::ImageResult;
|
||||||
|
use psnr::psnr_files;
|
||||||
|
|
||||||
const MAX: u32 = 255;
|
fn psnr_dir(path1: &str, path2: &str) -> Vec<(String, ImageResult<f64>)> {
|
||||||
|
|
||||||
fn mse_files(path1: &str, path2: &str) -> ImageResult<f64> {
|
|
||||||
|
|
||||||
let twenty_log10_max: f64 = 20.0 * (MAX as f64).log10();
|
|
||||||
|
|
||||||
let img1 = image::open(path1)?;
|
|
||||||
let img2 = image::open(path2)?;
|
|
||||||
|
|
||||||
use image::GenericImage;
|
|
||||||
|
|
||||||
if img1.dimensions() != img2.dimensions() {
|
|
||||||
return Err(ImageError::DimensionError);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut mse = 0.0;
|
|
||||||
|
|
||||||
for x in 0 .. img1.dimensions().0 {
|
|
||||||
for y in 0 .. img1.dimensions().1 {
|
|
||||||
let p1 = img1.get_pixel(x, y);
|
|
||||||
let p2 = img2.get_pixel(x, y);
|
|
||||||
|
|
||||||
let dx = p1[0] as f64 - p2[0] as f64;
|
|
||||||
let dy = p1[1] as f64 - p2[1] as f64;
|
|
||||||
let dz = p1[2] as f64 - p2[2] as f64;
|
|
||||||
|
|
||||||
let dx = dx * dx;
|
|
||||||
let dy = dy * dy;
|
|
||||||
let dz = dz * dz;
|
|
||||||
|
|
||||||
mse += dx + dy + dz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mse /= (img1.dimensions().0 * img1.dimensions().1 * 3) as f64;
|
|
||||||
|
|
||||||
Ok(twenty_log10_max - 10.0 * mse.log10())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mse_dir(path1: &str, path2: &str) -> Vec<(String, ImageResult<f64>)> {
|
|
||||||
let mut dirs1: Vec<_> = fs::read_dir(path1).unwrap()
|
let mut dirs1: Vec<_> = fs::read_dir(path1).unwrap()
|
||||||
.map(|x|x.unwrap())
|
.map(|x|x.unwrap())
|
||||||
.filter(|x| x.file_name().into_string().unwrap().ends_with(".png"))
|
.filter(|x| x.file_name().into_string().unwrap().ends_with(".png"))
|
||||||
|
@ -63,9 +26,9 @@ fn mse_dir(path1: &str, path2: &str) -> Vec<(String, ImageResult<f64>)> {
|
||||||
for file in dirs1 {
|
for file in dirs1 {
|
||||||
let p1 = path1.to_owned() + &file.file_name().to_owned().into_string().unwrap();
|
let p1 = path1.to_owned() + &file.file_name().to_owned().into_string().unwrap();
|
||||||
let p2 = path2.to_owned() + &file.file_name().to_owned().into_string().unwrap();
|
let p2 = path2.to_owned() + &file.file_name().to_owned().into_string().unwrap();
|
||||||
let mse = mse_files(&p1, &p2);
|
let psnr = psnr_files(&p1, &p2);
|
||||||
|
|
||||||
let elt = (file.file_name().to_owned().into_string().unwrap(), mse.unwrap());
|
let elt = (file.file_name().to_owned().into_string().unwrap(), psnr.unwrap());
|
||||||
println!("{} {}", elt.0, elt.1);
|
println!("{} {}", elt.0, elt.1);
|
||||||
res.push((elt.0, Ok(elt.1)));
|
res.push((elt.0, Ok(elt.1)));
|
||||||
}
|
}
|
||||||
|
@ -77,5 +40,5 @@ fn main() {
|
||||||
let path1 = args().nth(1).unwrap();
|
let path1 = args().nth(1).unwrap();
|
||||||
let path2 = args().nth(2).unwrap();
|
let path2 = args().nth(2).unwrap();
|
||||||
|
|
||||||
let _ = mse_dir(&path1, &path2);
|
let _ = psnr_dir(&path1, &path2);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue