1pub mod geometric;
2pub mod io;
3pub mod ops;
4
5pub use geometric::GeometricTransform;
6
7use burn::tensor::{Tensor, backend::Backend};
8
9#[derive(Clone, Debug)]
12pub struct Image<B: Backend> {
13 pub tensor: Tensor<B, 3>,
15}
16
17impl<B: Backend> Image<B> {
18 pub fn new(tensor: Tensor<B, 3>) -> Self {
20 Self { tensor }
21 }
22
23 pub fn open(
25 path: impl AsRef<std::path::Path>,
26 device: &B::Device,
27 ) -> crate::error::Result<Self> {
28 io::load_image(path, device)
29 }
30
31 pub fn save(&self, path: impl AsRef<std::path::Path>) -> crate::error::Result<()> {
33 io::save_image(self, path)
34 }
35
36 pub fn shape(&self) -> [usize; 3] {
38 let dims = self.tensor.dims();
39 [dims[0], dims[1], dims[2]]
40 }
41
42 pub fn channels(&self) -> usize {
44 self.tensor.dims()[0]
45 }
46
47 pub fn height(&self) -> usize {
49 self.tensor.dims()[1]
50 }
51
52 pub fn width(&self) -> usize {
54 self.tensor.dims()[2]
55 }
56
57 pub fn template_match(
62 &self,
63 template: &Image<B>,
64 method: crate::features::TemplateMatchMethod,
65 ) -> crate::error::Result<Tensor<B, 2>> {
66 use crate::features::template_match;
67 template_match(self, template, method)
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use crate::test_helpers::{TestBackend, test_device};
75 use burn::backend::ndarray::NdArrayDevice;
76 use burn::tensor::TensorData;
77
78 fn get_test_device() -> NdArrayDevice {
79 test_device()
80 }
81
82 #[test]
83 fn test_image_creation() {
84 let device = get_test_device();
85 let data = TensorData::new(vec![0.5f32; 3 * 10 * 10], [3, 10, 10]);
86 let tensor = Tensor::<TestBackend, 3>::from_data(data, &device);
87 let img = Image::new(tensor);
88
89 assert_eq!(img.channels(), 3);
90 assert_eq!(img.height(), 10);
91 assert_eq!(img.width(), 10);
92 assert_eq!(img.shape(), [3, 10, 10]);
93 }
94
95 #[test]
96 fn test_image_ops() {
97 let device = get_test_device();
98 let data = TensorData::new(vec![0.5f32; 3 * 8 * 8], [3, 8, 8]);
99 let tensor = Tensor::<TestBackend, 3>::from_data(data, &device);
100 let img = Image::new(tensor);
101
102 let cropped = img.crop(2, 2, 4, 4).unwrap();
104 assert_eq!(cropped.shape(), [3, 4, 4]);
105
106 let flipped = img.flip(true, false).unwrap();
108 assert_eq!(flipped.shape(), [3, 8, 8]);
109
110 let rotated = img.rotate(90).unwrap();
112 assert_eq!(rotated.shape(), [3, 8, 8]); let gray = img.grayscale().unwrap();
116 assert_eq!(gray.channels(), 1);
117 assert_eq!(gray.height(), 8);
118 assert_eq!(gray.width(), 8);
119
120 let rgb = gray.to_rgb().unwrap();
122 assert_eq!(rgb.channels(), 3);
123 }
124}