JuliaImages / ImageFiltering.jl

Julia implementations of multidimensional array convolution and nonlinear stencil operations
Other
99 stars 49 forks source link

Can't make imfilter! for specific indices work. #167

Closed Kunz-David closed 4 years ago

Kunz-David commented 4 years ago

Hi, I have a question about how to use imfilter! so that is computes only on provided inds. I am having trouble making a simple example work. Here is my code:

using ImageFiltering, Images, ComputationalResources

# Create a sample image:
tile_size = 50
board_size = 4 # must be even
mini_board = [zeros(tile_size, tile_size) ones(tile_size, tile_size);
              ones(tile_size, tile_size) zeros(tile_size, tile_size)]
chessboard = repeat(mini_board, outer=(convert(Integer,(board_size/2)), convert(Integer,(board_size/2))))
img = chessboard

# Create a filter:
sigma = 3
filter_size = 21
gaus = ImageFiltering.KernelFactors.gaussian(sigma, filter_size)
kernel = kernelfactors((gaus, gaus))

# params of imfilter function
imgfilt = similar(img)
inds = CartesianIndex(50, 50) # simple inds

# The filtering that errors:
imfilter!(CPU1(Algorithm.FIRTiled()), imgfilt, img, kernel, "symmetric", inds)

From the documentation I thought this would work, but it doesn't. I get an error like this:

ERROR: MethodError: no method matching factorkernel(::Tuple{ImageFiltering.KernelFactors.ReshapedOneD{Float64,2,0,OffsetArrays.OffsetArray{Float64,1,Array{Float64,1
}}},ImageFiltering.KernelFactors.ReshapedOneD{Float64,2,1,OffsetArrays.OffsetArray{Float64,1,Array{Float64,1}}}})
Closest candidates are:
  factorkernel(::AbstractArray{T,2}) where T at /Users/MrTrololord/.julia/packages/ImageFiltering/jhBno/src/imfilter.jl:1493
  factorkernel(::AbstractArray) at /Users/MrTrololord/.julia/packages/ImageFiltering/jhBno/src/imfilter.jl:1489
  factorkernel(::ImageFiltering.Kernel.Laplacian) at /Users/MrTrololord/.julia/packages/ImageFiltering/jhBno/src/imfilter.jl:1490
Stacktrace:
 [1] imfilter!(::CPU1{ImageFiltering.Algorithm.FIRTiled{0}}, ::Array{Float64,2}, ::Array{Float64,2}, ::Tuple{ImageFiltering.KernelFactors.ReshapedOneD{Float64,2,0,O
ffsetArrays.OffsetArray{Float64,1,Array{Float64,1}}},ImageFiltering.KernelFactors.ReshapedOneD{Float64,2,1,OffsetArrays.OffsetArray{Float64,1,Array{Float64,1}}}}, :
:String, ::CartesianIndex{2}) at /Users/MrTrololord/.julia/packages/ImageFiltering/jhBno/src/imfilter.jl:585
 [2] top-level scope at /Users/MrTrololord/Google_Drive/cvut/bakalarka/LAP_julia/test/try4.jl:182

Is there perhaps a dispatch problem here?

This is the fuction at imfilter.jl:585:

function imfilter!(r::AbstractResource, out::AbstractArray, img::AbstractArray, kernel, args...)
    imfilter!(r, out, img, factorkernel(kernel), args...)
end

The kernel I use has:

julia> typeof(kernel) <: ImageFiltering.ProcessedKernel
true

Isn't there supposed to be a function that takes this kind of kernel and also has args..?

(Disclaimer; I am new to Julia so this might just be me not using the function correctly. Sorry for that.)

johnnychen94 commented 4 years ago
# this is only one index, it need indices
- inds = CartesianIndex(50, 50)
+ inds = (40:60, 40:60)

# only NoPad strategy is supported for inds
- imfilter!(CPU1(Algorithm.FIRTiled()), imgfilt, img, kernel, "symmetric", inds)
+ imfilter!(CPU1(Algorithm.FIRTiled()), imgfilt, img, kernel, NoPad(), inds)

Edit: labeled it as a bug because this confusing error message is introduced by an oversight on dispatching.

Kunz-David commented 4 years ago

Ahh, now I see. Thanks for the answer @johnnychen94. I was hoping there would be a way to make this work on a discontinuous indices. How hard do you think it would be adapt the code for that usage? Do you see any other way to make it work in this use-case other than just running the loop for every index that is separate?

(Sorry for the long delay.)