Apply simple image filters (transformations) to an array.
Warning
zarrs_filter
is highly experimental, has had limited production testing, and is sparsely documented.
The filters currently supported are:
- reencode: Reencode (change encoding, data type, etc.).
- crop: Crop given an offset and shape.
- rescale: Rescale values given a multiplier and offset.
- clamp: Clamp values between a minimum and maximum.
- equal: Return a binary image where the input is equal to some value.
- downsample: Downsample given a stride.
- 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).
zarrs_filter
is installed with the filter
feature of zarrs_tools
cargo install --features=filter zarrs_tools
zarrs_filter --help
zarrs_filter <COMMAND> --help
export ENCODE_ARGS="--shard-shape 256,256,256 --chunk-shape 32,32,32"
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_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
zarrs_filter replace-value array_reenc.zarr array_replace.zarr ${ENCODE_ARGS} 65535 0 --fill-value 0
zarrs_filter <RUN.json>
run.json
[
{
"_comment": "Rechunk the input",
"filter": "reencode",
"input": "array.zarr",
"output": "$reencode0",
"shard_shape": [256, 256, 256],
"chunk_shape": [32, 32, 32]
},
{
"_comment": "Reencode the previous output as float32, automatically cast the fill value",
"filter": "reencode",
"output": "array_float32.zarr",
"data_type": "float32"
},
{
"filter": "crop",
"input": "$reencode0",
"output": "array_crop.zarr",
"offset": [256, 256, 256],
"shape": [768, 768, 768]
},
{
"filter": "replace_value",
"input": "$reencode0",
"output": "array_replace.zarr",
"value": 65535,
"replace": 0
},
{
"_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": "array_3bit.zarr",
"multiply": 0.00035,
"add": 0.0,
"data_type": "uint8",
"fill_value": 0
},
{
"_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": "array_8bit.zarr",
"multiply": 0.01275,
"add": 0.0,
"data_type": "uint8",
"fill_value": 0
},
{
"_comment": "Clamp the 3-bit output between 2 and 5 and set the fill value to 2",
"filter": "clamp",
"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": "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": "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": "array_3bit_clamp.zarr",
"output": "array_3bit_clamp_by2_continuous.zarr",
"stride": [2, 2, 2],
"discrete": false,
"data_type": "float32",
"shard_shape": [128, 128, 128],
"chunk_shape": [32, 32, 32]
},
{
"_comment": "Downsample clamped image by a factor of 2 with mode operator.",
"filter": "downsample",
"input": "array_3bit_clamp.zarr",
"output": "array_3bit_clamp_by2_discrete.zarr",
"stride": [2, 2, 2],
"discrete": true,
"shard_shape": [128, 128, 128],
"chunk_shape": [32, 32, 32]
},
{
"filter": "gradient_magnitude",
"input": "$reencode0",
"output": "array_gradient.zarr"
},
{
"filter": "gaussian",
"input": "$reencode0",
"output": "array_gaussian.zarr",
"sigma": [1.0, 1.0, 1.0],
"kernel_half_size": [3, 3, 3]
},
{
"filter": "summed_area_table",
"input": "$reencode0",
"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"
}
]
output
0 reencode
args: {}
encode: {"chunk_shape":[32,32,32],"shard_shape":[256,256,256]}
input: uint16 [1243, 1403, 1510] "array.zarr"
output: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
1 reencode
args: {}
encode: {"data_type":"float32"}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: float32 [1243, 1403, 1510] "array_float32.zarr" (overwrite)
2 crop
args: {"offset":[256,256,256],"shape":[768,768,768]}
encode: {}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: uint16 [768, 768, 768] "array_crop.zarr" (overwrite)
3 replace_value
args: {"value":65535,"replace":0}
encode: {}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: uint16 [1243, 1403, 1510] "array_replace.zarr" (overwrite)
4 rescale
args: {"multiply":0.00035,"add":0.0,"add_first":false}
encode: {"data_type":"uint8","fill_value":0}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: uint8 [1243, 1403, 1510] "array_3bit.zarr" (overwrite)
5 rescale
args: {"multiply":0.01275,"add":0.0,"add_first":false}
encode: {"data_type":"uint8","fill_value":0}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: uint8 [1243, 1403, 1510] "array_8bit.zarr" (overwrite)
6 clamp
args: {"min":2.0,"max":5.0}
encode: {"fill_value":2}
input: uint8 [1243, 1403, 1510] "array_8bit.zarr"
output: uint8 [1243, 1403, 1510] "array_3bit_clamp.zarr" (overwrite)
7 equal
args: {"value":5}
encode: {}
input: uint8 [1243, 1403, 1510] "array_3bit_clamp.zarr"
output: bool [1243, 1403, 1510] "array_clamp_equal_bool.zarr" (overwrite)
8 equal
args: {"value":5}
encode: {"data_type":"uint8","fill_value":0}
input: uint8 [1243, 1403, 1510] "array_3bit_clamp.zarr"
output: uint8 [1243, 1403, 1510] "array_3bit_max.zarr" (overwrite)
9 downsample
args: {"stride":[2,2,2],"discrete":false}
encode: {"data_type":"float32","chunk_shape":[32,32,32],"shard_shape":[128,128,128]}
input: uint8 [1243, 1403, 1510] "array_3bit_clamp.zarr"
output: float32 [621, 701, 755] "array_3bit_clamp_by2_continuous.zarr" (overwrite)
10 downsample
args: {"stride":[2,2,2],"discrete":true}
encode: {"chunk_shape":[32,32,32],"shard_shape":[128,128,128]}
input: uint8 [1243, 1403, 1510] "array_3bit_clamp.zarr"
output: uint8 [621, 701, 755] "array_3bit_clamp_by2_discrete.zarr" (overwrite)
11 gradient_magnitude
args: {}
encode: {}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: uint16 [1243, 1403, 1510] "array_gradient.zarr" (overwrite)
12 gaussian
args: {"sigma":[1.0,1.0,1.0],"kernel_half_size":[3,3,3]}
encode: {}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: uint16 [1243, 1403, 1510] "array_gaussian.zarr" (overwrite)
13 summed area table
args: {}
encode: {"data_type":"float32"}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: float32 [1243, 1403, 1510] "array_sat.zarr" (overwrite)
14 guided_filter
args: {"epsilon":40000.0,"radius":3}
encode: {"data_type":"float32"}
input: uint16 [1243, 1403, 1510] "/tmp/.tmpCbeEcJ/$reencode0bxiFEM"
output: float32 [1243, 1403, 1510] "array_guided_filter.zarr" (overwrite)
[00:00:02/00:00:02] reencode /tmp/.tmpCbeEcJ/$reencode0bxiFEM rw:34.78/28.90 p:0.00
[00:00:04/00:00:04] reencode array_float32.zarr rw:30.06/76.57 p:14.16
[00:00:00/00:00:00] crop array_crop.zarr rw:3.46/3.34 p:0.00
[00:00:02/00:00:02] replace_value array_replace.zarr rw:26.73/47.32 p:7.25
[00:00:01/00:00:01] rescale array_3bit.zarr rw:18.11/14.43 p:11.55
[00:00:01/00:00:01] rescale array_8bit.zarr rw:23.54/21.99 p:11.08
[00:00:00/00:00:00] clamp array_3bit_clamp.zarr rw:9.70/10.34 p:0.96
[00:00:00/00:00:00] equal array_clamp_equal_bool.zarr rw:10.61/9.32 p:4.56
[00:00:00/00:00:00] equal array_3bit_max.zarr rw:10.29/9.49 p:3.61
[00:00:02/00:00:02] downsample array_3bit_clamp_by2_continuous.zarr rw:7.01/1.95 p:71.76
[00:00:06/00:00:06] downsample array_3bit_clamp_by2_discrete.zarr rw:16.08/1.01 p:168.86
[00:00:20/00:00:20] gradient_magnitude array_gradient.zarr rw:147.16/14.38 p:289.05
[00:00:10/00:00:10] gaussian array_gaussian.zarr rw:36.19/22.01 p:181.06
[00:00:23/00:00:23] summed area table array_sat.zarr rw:190.51/215.68 p:54.39
[00:01:51/00:01:51] guided_filter array_guided_filter.zarr rw:29.57/59.96 p:2427.96