///|
pub struct ImageStats {
min : Int
max : Int
mean_x1000 : Int
variance_x1000 : Int
nonzero : Int
count : Int
} derive(Debug, Eq)
///|
pub fn ImageStats::from_gray(image : GrayImage) -> ImageStats {
let count = image.pixels.length()
if count == 0 {
{ min: 0, max: 0, mean_x1000: 0, variance_x1000: 0, nonzero: 0, count: 0 }
} else {
let mut low = 255
let mut high = 0
let mut sum = 0
let mut nonzero = 0
for value in image.pixels {
low = min_i(low, value)
high = max_i(high, value)
sum += value
if value != 0 {
nonzero += 1
}
}
let mean = sum / count * 1000 + sum % count * 1000 / count
let mut variance_sum = 0
for value in image.pixels {
let delta = value * 1000 - mean
variance_sum += delta * delta / 1000
}
{
min: low,
max: high,
mean_x1000: mean,
variance_x1000: variance_sum / count,
nonzero,
count,
}
}
}
///|
pub fn ImageStats::dynamic_range(self : ImageStats) -> Int {
self.max - self.min
}
///|
pub fn ImageStats::is_constant(self : ImageStats) -> Bool {
self.min == self.max
}
///|
pub fn GrayImage::stats(self : GrayImage) -> ImageStats {
ImageStats::from_gray(self)
}
///|
pub fn GrayImage::mean(self : GrayImage) -> Int {
self.stats().mean_x1000 / 1000
}
///|
pub fn GrayImage::sum(self : GrayImage) -> Int {
let mut total = 0
for value in self.pixels {
total += value
}
total
}
///|
pub fn GrayImage::count_value(self : GrayImage, value : Int) -> Int {
let mut total = 0
for pixel in self.pixels {
if pixel == clamp_u8(value) {
total += 1
}
}
total
}
///|
pub fn GrayImage::count_in_range(
self : GrayImage,
low : Int,
high : Int,
) -> Int {
let lo = clamp_u8(low)
let hi = clamp_u8(high)
let mut total = 0
for pixel in self.pixels {
if pixel >= lo && pixel <= hi {
total += 1
}
}
total
}
///|
pub fn GrayImage::mean_abs_error(self : GrayImage, other : GrayImage) -> Int {
let count = min_i(self.pixels.length(), other.pixels.length())
if count == 0 {
0
} else {
let mut total = 0
for i in 0.. Int {
let count = min_i(self.pixels.length(), other.pixels.length())
if count == 0 {
0
} else {
let mut total = 0
for i in 0.. Int {
let mse = self.mse_x1000(other)
if mse == 0 {
999999
} else {
1000 * 10 * 1000 / mse
}
}
///|
pub fn GrayImage::tile(self : GrayImage, tile_size : Size) -> Array[GrayImage] {
let out : Array[GrayImage] = []
let tw = max_i(1, tile_size.width)
let th = max_i(1, tile_size.height)
for y in 0.. GrayImage {
let b = max_i(0, border)
let out = GrayImage::new(
width=self.width + b * 2,
height=self.height + b * 2,
fill~,
)
for y in 0.. GrayImage {
let w = max_i(0, min_i(self.width - max_i(0, rect.x), rect.width))
let h = max_i(0, min_i(self.height - max_i(0, rect.y), rect.height))
let out = GrayImage::new(width=w, height=h)
for y in 0.. GrayImage {
let out = GrayImage::new(width=self.width, height=self.height)
for y in 0.. GrayImage {
let out = GrayImage::new(width=self.width, height=self.height)
for y in 0.. GrayImage {
self.flip_horizontal().flip_vertical()
}
///|
pub fn GrayImage::resize_nearest(self : GrayImage, size : Size) -> GrayImage {
let out = GrayImage::new(
width=max_i(0, size.width),
height=max_i(0, size.height),
)
if self.width == 0 || self.height == 0 {
out
} else {
for y in 0..