Image pooling

Is there a package that implements image pooling?

In more detail: I have a big image and need to downsize it. Say my image is of size 1000x1000 and I want to bring it down to 100x100. What I want to do is tile it with 10x10 blocks and replace each block by its median or mean, maximum… This operation is called pooling I think.
More generally I would like to be able to replace each 10x10 block by say a 4x4 block with respect to some function "f : 10x10 -> 4x4"
Is there a package that implements these kinds of operations?

You can low-pass filter the image using https://github.com/JuliaImages/Images.jl/blob/master/README.md
And then subsample it manually.

1 Like

Related to the question, you may try Images.resize as discussed in this thread:

Code optimization is still under development though.

That has bad performance (also not exactly equivalent, but that does probably not matter in practice). For example applying naively the 10x10 median filter and then subsampling does 100 times more work then necessary.

The package https://github.com/JuliaArrays/TiledIteration.jl probably provides the functionality you want, at least low level support for it, e.g.,

julia> using TiledIteration

julia> A = rand(1000,1000);   # our big array

julia> asmall = map(TileIterator(indices(A), (100,100))) do tileinds
                    median(A[tileinds...])
                end;


julia> Asmall = reshape(asmall,10,10);

julia> Asmall[1,1] == median(A[1:100,1:100])
true

julia> Asmall[end,end] == median(A[901:end,901:end])
true

julia> size(Asmall)
(10, 10)

I have not verified that this actually does exactly what you want, maybe the final array must be permuted somehow.

2 Likes

Looks promising, I will check it out, thanks!

Try restrict, which (should have) good performance while also antialiasing. You can call resize for the final (less-than-a-factor-of-2) resizing.

Hello,
probably this known, but when you apply restrict, what happens if my input matrix has NaN values, I did tried for my case, and I see that more empty regions appear, I suppose that the ouput within each cell is NaN if there is at least one during the computation. It would be feasible to say that if there is NaNs but at least one real value or more, then operate on those and give out a real value and not a NaN?

I think you are looking for what gdaladdo does. Likely possible to achieve with ArchGDAL.

indeed, it seems likely, let’s hope ArchGDAL has a single and simple function like restrict. :crossed_fingers:

It probably wouldn’t be hard to modify restrict to do that, though it would very likely have a performance impact so it would be best to keep the current implementation intact. One possibility would be to pass a function as an argument that would tally the local neighborhood. E.g., the current algorithm might accept

directweight(val, w) = val, w

and your version

nanweight(val, w) = isnan(val) ? (zero(val), zero(w)) : (val, w)

Then you pass directweight or nanweight as the first argument of restrict depending on which behavior you want.

A PR would be gratefully accepted!

2 Likes