use scirs2_core::ndarray::{Array2, IxDyn};
use scirs2_ndimage::morphology::{
distance_transform_bf, distance_transform_cdt, distance_transform_edt,
};
#[allow(dead_code)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Demonstrating distance transform functions\n");
let mut input = Array2::from_elem((10, 10), false);
for i in 3..7 {
for j in 3..7 {
input[[i, j]] = true;
}
}
println!("Input binary image:");
print_binary_2d(&input);
let input_dyn = input
.clone()
.into_dimensionality::<IxDyn>()
.expect("Operation failed");
let (edt_result, _) =
distance_transform_edt(&input_dyn, None, true, false).expect("Distance transform failed");
let edt = edt_result
.expect("Operation failed")
.into_dimensionality::<scirs2_core::ndarray::Ix2>()
.expect("Operation failed");
println!(
"\nEuclidean Distance Transform (distance from each true pixel to nearest false pixel):"
);
print_distance_2d(&edt);
let (cdt_result, _) = distance_transform_cdt(&input_dyn, "cityblock", true, false)
.expect("City block distance transform failed");
let cdt = cdt_result
.expect("Operation failed")
.into_dimensionality::<scirs2_core::ndarray::Ix2>()
.expect("Operation failed");
println!("\nCity Block (Manhattan) Distance Transform:");
print_integer_distance_2d(&cdt);
let (chess_result, _) = distance_transform_cdt(&input_dyn, "chessboard", true, false)
.expect("Chessboard distance transform failed");
let chess = chess_result
.expect("Operation failed")
.into_dimensionality::<scirs2_core::ndarray::Ix2>()
.expect("Operation failed");
println!("\nChessboard Distance Transform:");
print_integer_distance_2d(&chess);
let (bf_edt_result, _) = distance_transform_bf(&input_dyn, "euclidean", None, true, false)
.expect("Brute force distance transform failed");
let bf_edt = bf_edt_result
.expect("Operation failed")
.into_dimensionality::<scirs2_core::ndarray::Ix2>()
.expect("Operation failed");
println!("\nBrute Force Euclidean Distance Transform:");
print_distance_2d(&bf_edt);
let (_, indices) = distance_transform_edt(&input_dyn, None, false, true)
.expect("Distance transform with indices failed");
let indices = indices.expect("Operation failed");
println!("\nDistance Transform with Indices (showing a slice of the indices):");
println!("For each true pixel, these indices show the coordinates of the nearest false pixel");
println!("Dimension 0 (row) indices:");
print_indices_2d(&indices, 0);
println!("\nDimension 1 (column) indices:");
print_indices_2d(&indices, 1);
let sampling = [1.0, 0.5]; let (custom_edt_result, _) = distance_transform_edt(&input_dyn, Some(&sampling), true, false)
.expect("Custom sampling distance transform failed");
let custom_edt = custom_edt_result
.expect("Operation failed")
.into_dimensionality::<scirs2_core::ndarray::Ix2>()
.expect("Operation failed");
println!("\nEuclidean Distance Transform with Custom Sampling [1.0, 0.5]:");
println!("(Distances in column direction are halved due to sampling)");
print_distance_2d(&custom_edt);
Ok(())
}
#[allow(dead_code)]
fn print_binary_2d(arr: &Array2<bool>) {
for i in 0..arr.shape()[0] {
for j in 0..arr.shape()[1] {
if arr[[i, j]] {
print!("█ ");
} else {
print!("· ");
}
}
println!();
}
}
#[allow(dead_code)]
fn print_distance_2d(arr: &Array2<f64>) {
for i in 0..arr.shape()[0] {
for j in 0..arr.shape()[1] {
let val = arr[[i, j]];
if val < 0.01 {
print!("0.0 ");
} else {
print!("{:.1} ", val);
}
}
println!();
}
}
#[allow(dead_code)]
fn print_integer_distance_2d(arr: &Array2<i32>) {
for i in 0..arr.shape()[0] {
for j in 0..arr.shape()[1] {
let val = arr[[i, j]];
print!("{:2} ", val);
}
println!();
}
}
#[allow(dead_code)]
fn print_indices_2d(
indices: &scirs2_core::ndarray::ArrayBase<scirs2_core::ndarray::OwnedRepr<i32>, IxDyn>,
dim: usize,
) {
for i in 0..indices.shape()[1] {
for j in 0..indices.shape()[2] {
print!("{:2} ", indices[[dim, i, j]]);
}
println!();
}
}