///|
pub fn distance_transform(mask : BinaryMask) -> GrayImage {
let result = GrayImage(width=mask.width, height=mask.height, fill=1.0e6)
for y in 0..= 0 {
let mut x = mask.width - 1
while x >= 0 {
if mask.at(x, y) {
let right = if x + 1 >= mask.width {
1.0e6
} else {
result.at(x + 1, y) + 1.0
}
let bottom = if y + 1 >= mask.height {
1.0e6
} else {
result.at(x, y + 1) + 1.0
}
result.set(x, y, result.at(x, y).min(right).min(bottom))
}
x -= 1
}
y -= 1
}
result
}
///|
pub fn medial_axis(mask : BinaryMask, minimum_distance : Double) -> BinaryMask {
let distance = distance_transform(mask)
let result = BinaryMask(width=mask.width, height=mask.height)
for y in 0..= minimum_distance &&
value >= distance.at(x - 1, y) &&
value >= distance.at(x + 1, y) &&
value >= distance.at(x, y - 1) &&
value >= distance.at(x, y + 1) {
result.set(x, y, true)
}
}
}
result
}
///|
pub fn remove_small_objects(
mask : BinaryMask,
minimum_area : Int,
) -> BinaryMask {
filter_components_by_area(mask, minimum_area, 1_000_000_000)
}
///|
pub fn remove_large_objects(
mask : BinaryMask,
maximum_area : Int,
) -> BinaryMask {
filter_components_by_area(mask, 0, maximum_area)
}
///|
pub fn majority_filter(mask : BinaryMask, radius : Int) -> BinaryMask {
let result = BinaryMask(width=mask.width, height=mask.height)
let safe = radius.max(0)
let total = (safe * 2 + 1) * (safe * 2 + 1)
for y in 0..= total)
}
}
result
}
///|
pub fn border_mask(width : Int, height : Int, thickness : Int) -> BinaryMask {
let result = BinaryMask(width~, height~)
let safe = thickness.max(0)
for y in 0..= width - safe || y >= height - safe {
result.set(x, y, true)
}
}
}
result
}
///|
pub fn interior_mask(width : Int, height : Int, thickness : Int) -> BinaryMask {
border_mask(width, height, thickness).invert()
}
///|
pub fn mask_perimeter(mask : BinaryMask) -> Double {
let boundary = mask.boundary()
Double::from_int(boundary.count())
}
///|
pub fn mask_euler_estimate(mask : BinaryMask) -> Int {
let components = label_components(mask).length()
let holes = label_components(fill_mask_holes(mask).difference(mask)).length()
components - holes
}
///|
pub fn mask_symmetry_score(mask : BinaryMask, horizontal : Bool) -> Double {
if mask.width * mask.height == 0 {
0.0
} else {
let mut equal = 0
for y in 0.. Array[Int] {
let projection = if horizontal {
mask.column_projection()
} else {
mask.row_projection()
}
let result : Array[Int] = []
for i in 0..= threshold {
result.push(i)
}
}
result
}
///|
pub fn mask_fill_ratio(mask : BinaryMask) -> Double {
if mask.width * mask.height == 0 {
0.0
} else {
Double::from_int(mask.count()) / Double::from_int(mask.width * mask.height)
}
}