Skip to content

Commit

Permalink
zarrs_filter: add guided filter
Browse files Browse the repository at this point in the history
  • Loading branch information
LDeakin committed Mar 16, 2024
1 parent 3d30f3a commit 258ffcc
Show file tree
Hide file tree
Showing 8 changed files with 601 additions and 32 deletions.
3 changes: 3 additions & 0 deletions docs/guided_filter/guided_filter6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
A computation graph for a memory efficient guided filter implementation.
The stored value in each image is shown at each computation step.
$I(x)$ denotes the integral image of $x$ and $\overline{x}$ denotes a mean value computed from the integral image over a window $w_k$.
Binary file added docs/guided_filter/guided_filter6.pdf
Binary file not shown.
89 changes: 89 additions & 0 deletions docs/guided_filter/guided_filter6.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
\documentclass[border=0pt,multi,tikz]{standalone}

\usetikzlibrary{positioning}
\usetikzlibrary{patterns}
\usetikzlibrary{hobby}
\usetikzlibrary{svg.path}
\usetikzlibrary{calc}
\usetikzlibrary{decorations}
\usetikzlibrary{decorations.markings}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{arrows}
\usetikzlibrary{fit}
\usetikzlibrary{fadings}

\pgfdeclarelayer{bg} % declare background layer
\pgfsetlayers{bg,main} % set the order of the layers (main is the standard layer)

\begin{document}
\begin{tikzpicture}[
% xscale=1.0,
% yscale=-0.5,
arrow/.style={-{Latex[length=3pt]}, shorten <=-3pt, shorten >=-3pt},
stage/.style={dotted},
every node/.style={right,font=\small},
]

\matrix []
{
\node(c0){}; \node(i0){}; & \node(i1){1-4}; & \node(i2){5}; & \node(i3){6-9}; & \node(i4){10}; & \node(i5){11-14}; & \node(i6){15}; & \node(i7){16-19}; & \node(i8){20}; \\
\node(im0){Input}; & \node[](a){}; &&&&& \node(i){$\overline{a_k} v_i$}; && \node(k){$q_i = \overline{a_k} v_i + \overline{b_k}$}; \\
\node(im1){Integral}; & \node(b){$I(v_i)$}; && \node(e){$I\left(\left(v_i-\mu_k\right)^2\right)$}; && \node(h){$I(a_k)$}; && \node(j){$I(b_k)$}; \\
\node(im2){Transient results}; && \node(c){$\mu_k = \overline{v_i}$}; && \node[right](f){$a_k=\sigma_k^2 / (\sigma_k^2 + \epsilon)$}; && \\
\node(im3){Transient results}; &&&& \node[right](g){$b_k = (1 - a_k)\mu_k$}; \\
&&&& \node[gray](bot){$\sigma_k^2 = \overline{\left(v_i - \mu_k \right)^2}$}; \\
};

\node[anchor=east,xshift=-0.1cm](aa) at (a.west) {$v_i$};

\draw[arrow] (aa.south) |- (b.west);
%\draw[arrow] (a2.east) -- (b.west);
% \draw[arrow] (b.west) -- (a2.east);
\draw[arrow] (b.south) |- (c.west);
\draw[arrow] (c.east) -- (f.west);
\draw[arrow] (c.north) |- (e.west);
% \draw[arrow,ultra thick,white] (d.north) |- (e.west);
\draw[arrow] (aa.east) -| (c.south|-e.east) -- (e.west);
%\draw[arrow] (d.east) -- (e.west);
% \draw[arrow] (e.west) -- (d.east);
\draw[arrow] (e.south) |- (f.west);
\draw[arrow] (e.south) |- (g.west);
\draw[arrow] (f.north) |- (h.west);
\draw[arrow] (h.north) |- (i.west);
%\coordinate[] (is) at (g.east -| i.south);
%\draw[] (g) -- (is);
%\draw[arrow] (is) |- (j.west);
\draw[arrow] (g.east) -| (i.south|-j.west) -- (j.west);
\draw[arrow] (j.north) |- (k.west);
\draw[arrow] (i.east) -- (k.west);
\node[circle, fill=black, anchor=center,inner sep=0pt, minimum size=3pt](intersection) at (c.south|-e.east){};
\node[circle, fill=black, anchor=center,inner sep=0pt, minimum size=3pt](intersection) at (e.south|-f.west){};
\node[circle, fill=black, anchor=center,inner sep=0pt, minimum size=3pt](intersection) at (j.north|-k.west){};

\node[rotate=90,anchor=south,align=center] at ($(im0.west)!0.5!(im3.west)$) {\textbf{Images}};
\node[anchor=east,align=right] at (i1.west) {Computation step:};

% Black lines
\draw[] (i1.west|-k.north east) -- (k.north east);
% \draw[] (i0.west|-k.north east) -- (i0.south west |- bot.south);

% Dashed lines memory
\draw[stage] (im0.west|-k.south east) -- (k.south-|k.east);
\draw[stage] (im0.west|-f.north east) -- (f.north-|k.east);
\draw[stage] (im0.west|-f.south east) -- (f.south-|k.east);
\draw[stage] (im0.west|-g.south east) -- (g.south-|k.east);


% Dashed lines computation steps
\draw[stage] (i1.north west) -- (i1.west |- g.south);
\draw[stage] (i2.north west) -- (i2.west |- g.south);
\draw[stage] (i3.north west) -- (i3.west |- g.south);
\draw[stage] (i4.north west) -- (i4.west |- g.south);
\draw[stage] (i5.north west) -- (i5.west |- g.south);
\draw[stage] (i6.north west) -- (i6.west |- g.south);
\draw[stage] (i7.north west) -- (i7.west |- g.south);
\draw[stage] (i8.north west) -- (i8.west |- g.south);
%\draw[stage] (i9.north west) -- (i9.west |- bot.south);
%\draw[stage] (i10.north west) -- (i10.west |- bot.south);
\end{tikzpicture}
\end{document}
66 changes: 38 additions & 28 deletions docs/zarrs_filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The filters currently supported are:
- **gradient-magnitude**: Compute the gradient magnitude (sobel).
- **gaussian**: Apply a Gaussian kernel.
- **summed area table**: Compute the summed area table.
- **guided filter**: Apply a guided filter (edge-preserving noise filter).

## Installation
`zarrs_filter` is installed with the `filter` feature of `zarrs_tools`
Expand All @@ -32,19 +33,20 @@ zarrs_filter <COMMAND> --help
## Examples (CLI)
```bash
export ENCODE_ARGS="--shard-shape 256,256,256 --chunk-shape 32,32,32"
zarrs_filter reencode array.zarr array_reencode.zarr ${ENCODE_ARGS}
zarrs_filter reencode array.zarr array_reencode_int32.zarr ${ENCODE_ARGS} --data-type int32
zarrs_filter reencode array.zarr array_reencode_float32.zarr ${ENCODE_ARGS} --data-type float32
zarrs_filter crop array.zarr array_crop.zarr ${ENCODE_ARGS} --data-type float32 256,256,256 768,768,768
zarrs_filter rescale array.zarr array_rescale.zarr ${ENCODE_ARGS} --data-type float32 2.0 1.0 --fill-value 1.0
zarrs_filter clamp array.zarr array_clamp.zarr ${ENCODE_ARGS} --data-type float32 5 255 --fill-value 5.0
zarrs_filter equal array.zarr array_equal_bool.zarr ${ENCODE_ARGS} --data-type bool 1 --fill-value true
zarrs_filter equal array.zarr array_eq_u8.zarr ${ENCODE_ARGS} --data-type uint8 1 --fill-value 1
zarrs_filter downsample array.zarr array_downsample.zarr ${ENCODE_ARGS} --data-type float32 2,2,2
zarrs_filter reencode array.zarr array_reenc.zarr ${ENCODE_ARGS}
zarrs_filter reencode array_reenc.zarr array_reenc_int32.zarr ${ENCODE_ARGS} --data-type int32
zarrs_filter reencode array_reenc.zarr array_reenc_float32.zarr ${ENCODE_ARGS} --data-type float32
zarrs_filter crop array_reenc.zarr array_crop.zarr ${ENCODE_ARGS} --data-type float32 256,256,256 768,768,768
zarrs_filter rescale array_reenc.zarr array_rescale.zarr ${ENCODE_ARGS} --data-type float32 2.0 1.0 --fill-value 1.0
zarrs_filter clamp array_reenc.zarr array_clamp.zarr ${ENCODE_ARGS} --data-type float32 5 255 --fill-value 5.0
zarrs_filter equal array_reenc.zarr array_equal_bool.zarr ${ENCODE_ARGS} --data-type bool 1 --fill-value true
zarrs_filter equal array_reenc.zarr array_eq_u8.zarr ${ENCODE_ARGS} --data-type uint8 1 --fill-value 1
zarrs_filter downsample array_reenc.zarr array_downsample.zarr ${ENCODE_ARGS} --data-type float32 2,2,2
zarrs_filter downsample array_eq_u8.zarr array_downsample_discrete.zarr ${ENCODE_ARGS} --data-type uint8 2,2,2 --discrete
zarrs_filter gradient-magnitude array.zarr array_gradient_magnitude.zarr ${ENCODE_ARGS} --data-type float32
zarrs_filter gaussian array.zarr array_gaussian.zarr ${ENCODE_ARGS} --data-type float32 1.0,1.0,1.0 3,3,3
zarrs_filter summed-area-table array.zarr array_sat.zarr ${ENCODE_ARGS} --data-type int64
zarrs_filter gradient-magnitude array_reenc.zarr array_gradient_magnitude.zarr ${ENCODE_ARGS} --data-type float32
zarrs_filter gaussian array_reenc.zarr array_gaussian.zarr ${ENCODE_ARGS} --data-type float32 1.0,1.0,1.0 3,3,3
zarrs_filter summed-area-table array_reenc.zarr array_sat.zarr ${ENCODE_ARGS} --data-type int64
zarrs_filter guided-filter array_reenc.zarr array_guided_filter.zarr ${ENCODE_ARGS} --data-type float32 40000 3
```

## Examples (Config)
Expand All @@ -69,21 +71,21 @@ zarrs_filter <RUNFILE.json>
{
"_comment": "Reencode the previous output as float32, automatically cast the fill value",
"filter": "reencode",
"output": "filter/array_float32.zarr",
"output": "array_float32.zarr",
"data_type": "float32"
},
{
"filter": "crop",
"input": "$reencode0",
"output": "filter/array_crop.zarr",
"output": "array_crop.zarr",
"offset": [256, 256, 256],
"shape": [768, 768, 768]
},
{
"_comment": "Multiply by 7.0/20000.0, casting most values in the image between 0 and 7, store in 8-bit (saturate cast)",
"filter": "rescale",
"input": "$reencode0",
"output": "filter/array_3bit.zarr",
"output": "array_3bit.zarr",
"multiply": 0.00035,
"add": 0.0,
"data_type": "uint8",
Expand All @@ -93,7 +95,7 @@ zarrs_filter <RUNFILE.json>
"_comment": "Multiply by 255.0/20000.0, casting most values in the image between 0 and 7, store in 8-bit (saturate cast)",
"filter": "rescale",
"input": "$reencode0",
"output": "filter/array_8bit.zarr",
"output": "array_8bit.zarr",
"multiply": 0.01275,
"add": 0.0,
"data_type": "uint8",
Expand All @@ -102,32 +104,32 @@ zarrs_filter <RUNFILE.json>
{
"_comment": "Clamp the 3-bit output between 2 and 5 and set the fill value to 2",
"filter": "clamp",
"output": "filter/array_3bit_clamp.zarr",
"output": "array_3bit_clamp.zarr",
"min": 2,
"max": 5,
"fill_value": 2
},
{
"_comment": "Calculate a binary image where the input is equal to 5 (the max from the clamp). Store as bool",
"filter": "equal",
"input": "filter/array_3bit_clamp.zarr",
"output": "filter/array_clamp_equal_bool.zarr",
"input": "array_3bit_clamp.zarr",
"output": "array_clamp_equal_bool.zarr",
"value": 5
},
{
"_comment": "Calculate a binary image where the input is equal to 5 (the max from the clamp). Store as uint8",
"filter": "equal",
"input": "filter/array_3bit_clamp.zarr",
"output": "filter/array_3bit_max.zarr",
"input": "array_3bit_clamp.zarr",
"output": "array_3bit_max.zarr",
"value": 5,
"data_type": "uint8",
"fill_value": 0
},
{
"_comment": "Downsample clamped image by a factor of 2 with mean operator.",
"filter": "downsample",
"input": "filter/array_3bit_clamp.zarr",
"output": "filter/array_3bit_clamp_by2_continuous.zarr",
"input": "array_3bit_clamp.zarr",
"output": "array_3bit_clamp_by2_continuous.zarr",
"stride": [2, 2, 2],
"discrete": false,
"data_type": "float32",
Expand All @@ -137,8 +139,8 @@ zarrs_filter <RUNFILE.json>
{
"_comment": "Downsample clamped image by a factor of 2 with mode operator.",
"filter": "downsample",
"input": "filter/array_3bit_clamp.zarr",
"output": "filter/array_3bit_clamp_by2_discrete.zarr",
"input": "array_3bit_clamp.zarr",
"output": "array_3bit_clamp_by2_discrete.zarr",
"stride": [2, 2, 2],
"discrete": true,
"shard_shape": [128, 128, 128],
Expand All @@ -147,19 +149,27 @@ zarrs_filter <RUNFILE.json>
{
"filter": "gradient_magnitude",
"input": "$reencode0",
"output": "filter/array_gradient.zarr"
"output": "array_gradient.zarr"
},
{
"filter": "gaussian",
"input": "$reencode0",
"output": "filter/array_gaussian.zarr",
"output": "array_gaussian.zarr",
"sigma": [1.0, 1.0, 1.0],
"kernel_half_size": [3, 3, 3]
},
{
"filter": "summed_area_table",
"input": "$reencode0",
"output": "filter/array_sat.zarr",
"output": "array_sat.zarr",
"data_type": "float32"
},
{
"filter": "guided_filter",
"input": "$reencode0",
"output": "array_guided_filter.zarr",
"epsilon": 40000.0,
"radius": 3,
"data_type": "float32"
}
]
Expand Down
1 change: 1 addition & 0 deletions src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod filters {
pub mod equal;
pub mod gaussian;
pub mod gradient_magnitude;
pub mod guided_filter;
pub mod reencode;
pub mod rescale;
pub mod summed_area_table;
Expand Down
2 changes: 2 additions & 0 deletions src/filter/filter_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,6 @@ pub enum FilterCommand {
Gaussian(FilterCombinedArgs<filters::gaussian::GaussianArguments>),
/// Compute a summed area table (integral image).
SummedAreaTable(FilterCombinedArgs<filters::summed_area_table::SummedAreaTableArguments>),
/// Apply a guided filter (edge-preserving noise filter).
GuidedFilter(FilterCombinedArgs<filters::guided_filter::GuidedFilterArguments>),
}

0 comments on commit 258ffcc

Please sign in to comment.