Skip to content

Commit 3dd2499

Browse files
committed
Integrated padding strategies into conv
Also added a changelog
1 parent bc2e4d7 commit 3dd2499

File tree

3 files changed

+93
-6
lines changed

3 files changed

+93
-6
lines changed

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Change Log
2+
3+
## Develop Branch (Unreleased)
4+
5+
### Added
6+
* Padding strategies (`NoPadding`, `ConstantPadding`, `ZeroPadding`)
7+
8+
### Changed
9+
* Integrated Padding strategies into convolutions
10+
11+
### Removed
12+
13+
## 0.1.1
14+
15+
### Added
16+
17+
### Changed
18+
* Applied zero padding by default in convolutions
19+
20+
### Removed
21+
22+
## 0.1.0 (First release)
23+
24+
### Added
25+
* Image type
26+
* Colour Models (RGB, Gray, HSV, CIEXYZ, Channel-less)
27+
* Histogram equalisation
28+
* Image convolutions
29+
* `PixelBound` type to aid in rescaling images
30+
* Canny edge detector
31+
* `KernelBuilder` and `FixedDimensionKernelBuilder` to create kernels
32+
* Builder implementations for Sobel, Gaussian, Box Linear filter, Laplace
33+
* Median filter
34+
* Sobel Operator
35+
* PPM encoding and decoding for images

src/core/padding.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ where
6262
}
6363
}
6464

65-
6665
impl<T> PaddingStrategy<T> for ZeroPadding
6766
where
6867
T: Copy + Zero,
@@ -139,7 +138,7 @@ mod tests {
139138
assert_eq!(p, exp);
140139

141140
let p = i.pad((2, 0), &ConstantPadding(0));
142-
let z = i.pad((2, 0), &ZeroPadding{});
141+
let z = i.pad((2, 0), &ZeroPadding {});
143142
assert_eq!(p, z);
144143

145144
let exp = Image::<u8, Gray>::from_shape_data(

src/processing/conv.rs

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::core::{ColourModel, Image};
21
use crate::core::padding::*;
2+
use crate::core::{ColourModel, Image};
33
use crate::processing::Error;
44
use ndarray::prelude::*;
55
use ndarray::{s, Zip};
@@ -16,9 +16,25 @@ where
1616
type Data;
1717

1818
/// Perform a convolution returning the resultant data
19+
/// applies the default padding of zero padding
1920
fn conv2d(&self, kernel: ArrayView3<Self::Data>) -> Result<Self, Error>;
2021
/// Performs the convolution inplace mutating the containers data
22+
/// applies the default padding of zero padding
2123
fn conv2d_inplace(&mut self, kernel: ArrayView3<Self::Data>) -> Result<(), Error>;
24+
/// Perform a convolution returning the resultant data
25+
/// applies the default padding of zero padding
26+
fn conv2d_with_padding(
27+
&self,
28+
kernel: ArrayView3<Self::Data>,
29+
strategy: &dyn PaddingStrategy<Self::Data>,
30+
) -> Result<Self, Error>;
31+
/// Performs the convolution inplace mutating the containers data
32+
/// applies the default padding of zero padding
33+
fn conv2d_inplace_with_padding(
34+
&mut self,
35+
kernel: ArrayView3<Self::Data>,
36+
strategy: &dyn PaddingStrategy<Self::Data>,
37+
) -> Result<(), Error>;
2238
}
2339

2440
fn kernel_centre(rows: usize, cols: usize) -> (usize, usize) {
@@ -34,6 +50,19 @@ where
3450
type Data = T;
3551

3652
fn conv2d(&self, kernel: ArrayView3<Self::Data>) -> Result<Self, Error> {
53+
self.conv2d_with_padding(kernel, &ZeroPadding {})
54+
}
55+
56+
fn conv2d_inplace(&mut self, kernel: ArrayView3<Self::Data>) -> Result<(), Error> {
57+
*self = self.conv2d_with_padding(kernel, &ZeroPadding {})?;
58+
Ok(())
59+
}
60+
61+
fn conv2d_with_padding(
62+
&self,
63+
kernel: ArrayView3<Self::Data>,
64+
strategy: &dyn PaddingStrategy<Self::Data>,
65+
) -> Result<Self, Error> {
3766
if self.shape()[2] != kernel.shape()[2] {
3867
Err(Error::ChannelDimensionMismatch)
3968
} else {
@@ -45,7 +74,7 @@ where
4574

4675
if shape.0 > 0 && shape.1 > 0 {
4776
let mut result = Self::zeros(shape);
48-
let tmp = self.pad((row_offset, col_offset), &ZeroPadding {});
77+
let tmp = self.pad((row_offset, col_offset), strategy);
4978

5079
Zip::indexed(tmp.windows(kernel.dim())).apply(|(i, j, _), window| {
5180
let mult = &window * &kernel;
@@ -59,8 +88,12 @@ where
5988
}
6089
}
6190

62-
fn conv2d_inplace(&mut self, kernel: ArrayView3<Self::Data>) -> Result<(), Error> {
63-
*self = self.conv2d(kernel)?;
91+
fn conv2d_inplace_with_padding(
92+
&mut self,
93+
kernel: ArrayView3<Self::Data>,
94+
strategy: &dyn PaddingStrategy<Self::Data>,
95+
) -> Result<(), Error> {
96+
*self = self.conv2d_with_padding(kernel, strategy)?;
6497
Ok(())
6598
}
6699
}
@@ -82,6 +115,26 @@ where
82115
fn conv2d_inplace(&mut self, kernel: ArrayView3<Self::Data>) -> Result<(), Error> {
83116
self.data.conv2d_inplace(kernel)
84117
}
118+
119+
fn conv2d_with_padding(
120+
&self,
121+
kernel: ArrayView3<Self::Data>,
122+
strategy: &dyn PaddingStrategy<Self::Data>,
123+
) -> Result<Self, Error> {
124+
let data = self.data.conv2d_with_padding(kernel, strategy)?;
125+
Ok(Self {
126+
data,
127+
model: PhantomData,
128+
})
129+
}
130+
131+
fn conv2d_inplace_with_padding(
132+
&mut self,
133+
kernel: ArrayView3<Self::Data>,
134+
strategy: &dyn PaddingStrategy<Self::Data>,
135+
) -> Result<(), Error> {
136+
self.data.conv2d_inplace_with_padding(kernel, strategy)
137+
}
85138
}
86139

87140
#[cfg(test)]

0 commit comments

Comments
 (0)