Coder Social home page Coder Social logo

imagefiltering.jl's Introduction

ImageFiltering

ImageFiltering implements blurring, sharpening, gradient computation, and other linear filtering operations, as well nonlinear filters like min/max.

Packages with overlapping functionality that also offer something extra:

Packages that appear to perform just a subset of what ImageFiltering does:

imagefiltering.jl's People

Contributors

asinghvi17 avatar bioturbonick avatar cormullion avatar dsantra92 avatar feanor12 avatar femtocleaner[bot] avatar gerrygralton avatar github-actions[bot] avatar goretkin avatar ianbutterworth avatar innerlee avatar jefffessler avatar jingpengw avatar johnnychen94 avatar juliatagbot avatar juliohm avatar jw3126 avatar katrinleinweber avatar kmsquire avatar ralphas avatar rdeits avatar sbrisard avatar staticfloat avatar stillyslalom avatar timholy avatar tkelman avatar tkf avatar tlnagy avatar yha avatar zygmuntszpak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

imagefiltering.jl's Issues

mapwindow doesn't work with 4D arrays

A = rand(5,5,5)
mapwindow(mean, A, [1,1,3])

seems to work fine

A = rand(5,5,5,5)
mapwindow(mean, A, [1,1,1,3])

returns the following error

ERROR: MethodError: no method matching ntuple(::getfield(ImageFiltering.MapWindow, Symbol("##25#26")), ::Type{Val{4}})Closest candidates are:
  ntuple(::F, ::Integer) where F at tuple.jl:136
  ntuple(::Any, ::Val{0}) at tuple.jl:158
  ntuple(::Any, ::Val{1}) at tuple.jl:159
  ...
Stacktrace:
 [1] docopy! at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:294 [inlined]
 [2] copy_win!(::Array{Float64,4}, ::Array{Float64,4}, ::CartesianIndex{4}, ::Pad{0}, ::CartesianIndex{4}) at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:287
 [3] make_buffer_values_realistic!(::Array{Float64,4}, ::Array{Float64,4}, ::NTuple{4,UnitRange{Int64}}, ::Pad{0}, ::NTuple{4,Base.OneTo{Int64}}) at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:240
 [4] compute_output_eltype(::typeof(mean), ::Array{Float64,4}, ::NTuple{4,UnitRange{Int64}}, ::Pad{0}, ::NTuple{4,Base.OneTo{Int64}}) at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:228
 [5] allocate_output(::Function, ::Array{Float64,4}, ::NTuple{4,UnitRange{Int64}}, ::Pad{0}, ::NTuple{4,Base.OneTo{Int64}}) at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:214
 [6] _mapwindow(::Function, ::Array{Float64,4}, ::NTuple{4,UnitRange{Int64}}, ::Pad{0}, ::NTuple{4,Base.OneTo{Int64}}) at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:77
 [7] #mapwindow#1(::String, ::NTuple{4,Base.OneTo{Int64}}, ::Symbol, ::Function, ::Function, ::Array{Float64,4}, ::Array{Int64,1}) at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:59
 [8] mapwindow(::Function, ::Array{Float64,4}, ::Array{Int64,1}) at /home/chantal/.julia/packages/ImageFiltering/8fmJ4/src/mapwindow.jl:56
 [9] top-level scope at none:0

Add preallocated `imgradients!`

I have a time-series of volumetric 'images' from which I need to calculate gradients, and each calculation spends a solid fraction of its runtime on GC:

julia> img = rand(128,128,1024);

julia> @time imgradients(img, KernelFactors.bickley)

  0.911337 seconds (688.35 k allocations: 814.017 MiB, 11.63% gc time)

I'd like to provide preallocated arrays for both output and padding.

`imfilter` ignores `Fill` values when`Fill` bounds are explicitly specified or inferred from a kernel

using ImageFiltering, , Test

A = rand(8,8)

# If you don't explicitly specify the amount of padding then the `Fill` value
# is taken into account and, as anticipated,  affects the outcome of the result. 
r1 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(0))
r2 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(10))
@test r1[4,4] == r2[4,4]
@test r1[1,1] != r2[1,1]

# If you specify the amount of padding as a tuple then the `Fill` value
# is not taken into account.
r1 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(0, (3,3)))
r2 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(10, (3,3)))
@test r1[4,4] == r2[4,4]
@test r1[1,1] != r2[1,1] # Test fails

r1 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(0, (3,3),(3,3)))
r2 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(10, (3,3), (3,3)))
@test r1[4,4] == r2[4,4]
@test r1[1,1] != r2[1,1] # Test fails

# If you specify the amount of padding as an array then the `Fill` value
# is not taken into account.
r1 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(0, [3,3],[3,3]))
r2 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(10, [3,3], [3,3]))
@test r1[4,4] == r2[4,4]
@test r1[1,1] != r2[1,1] # Test fails

# If you specify the kernel so that the minimum required padding is applied
# the `Fill` value is not taken into account.
r1 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(0, Kernel.gaussian((1,1),(3,3))))
r2 = imfilter(A, Kernel.gaussian((1,1),(3,3)), Fill(10, Kernel.gaussian((1,1),(3,3))))
@test r1[4,4] == r2[4,4]
@test r1[1,1] != r2[1,1] # Test fails

Lazy padarray?

I think it would be useful to have a lazy variant of padarray. E.g. a thin wrapper around the array that computes border values in getindex calls.
I have the feeling that this thing exists already somewhere? If not, is there interest of having that functionality here?

Convolutions for DL

I'd like to use this excellent package for the filters commonly used in deep learning. I tried a naive implementation here, but performance isn't great and I'm wondering if we need support in this package to improve that.

To give a rough outline of the semantics, we have a D×C×N image array where: D are the data dimension(s) (e.g. width and height), C is the channel dimension (e.g. colour) and N is a batch dimension (so we can convolve N independent images at once). This is convolved with a K×C×F filter (K being the filter dimension(s) and F being the number of filters / output channels) to produce a D′×F×N output array. Each slice along F is treated as a separate "filter" that spans the channel dimension, and the filter outputs are concatenated.

Hope that's clear and I'm happy to give more references if it's useful. Does this looks like something that's easy and appropriate for this package to support, or would it require an entirely new implementation?

Are the allocations from `imfilter!` expected?

Hello,

I was trying to use imfilter! with an array gx preallocated before calling the function with the hope of not allocating memory. I see 2.31 MiB allocated. Why is it happening? (should I expect it? I did not expect any allocations if the output array was preallocated)

thank you

A minimal working example:

using Images
using TestImages
using BenchmarkTools

function to_gray(image)
    x = Array{ColorTypes.Gray{Float32}, 2}(image)
    return Array{Float32}(x)
end

img = testimage("mandrill");
img = to_gray(img)
direction_x =  centered([-1 0 1])
gx = imfilter(img, direction_x);

@benchmark imfilter($img, $direction_x)
@benchmark imfilter!($gx, $img, $direction_x)

Prints the following:

BenchmarkTools.Trial: 
  memory estimate:  3.31 MiB
  allocs estimate:  58
  --------------
  minimum time:     4.126 ms (0.00% GC)
  median time:      4.597 ms (0.00% GC)
  mean time:        5.200 ms (7.27% GC)
  maximum time:     10.802 ms (28.68% GC)
  --------------
  samples:          960
  evals/sample:     1


BenchmarkTools.Trial: 
  memory estimate:  2.31 MiB
  allocs estimate:  56
  --------------
  minimum time:     4.101 ms (0.00% GC)
  median time:      4.419 ms (0.00% GC)
  mean time:        4.839 ms (5.47% GC)
  maximum time:     10.787 ms (25.44% GC)
  --------------
  samples:          1032
  evals/sample:     1

Fix imgradients on points

A decently long time ago I have added a version of imgradients that computes the gradients only at specific points of the image. After the modularization of Images.jl, part of the code was missed and nowadays a non-working version resides in the project: https://github.com/JuliaImages/ImageFiltering.jl/blob/master/src/specialty.jl#L66-L117

I still have the missing components locally on my machine:

# Auxiliary functions for computing N-dimensional gradients
function _gradientpad(img::AbstractArray, border::AbstractString="replicate")
    border  ["replicate", "circular", "reflect", "symmetric"] || error("border option not supported")
    padding = map(Int, [size(img)...] .> 1)

    padarray(img, padding, padding, border)
end

function _directional_kernel(dir::Int, extent::Dims, method::AbstractString)
    extent[dir] > 1 || error("invalid gradient direction")

    ndirs = length(extent)

    # smoothing weights
    weights = (method == "sobel"   ? [1.,2.,1.] :
               method == "prewitt" ? [1.,1.,1.] :
               method == "ando3"   ? [.112737,.274526,.112737] :
               error("Unknown gradient method: $method"))

    # finite difference scheme
    finitediff = (method  ["sobel","prewitt","ando3"] ? [-1.,0.,1.] :
                  error("Unknown gradient method: $method"))

    # centered difference
    idx = ones(Int, ndirs); idx[dir] = length(finitediff)
    kern = reshape(finitediff, idx...)
    # perpendicular smoothing
    for j in [1:dir-1;dir+1:ndirs]
        if extent[j] > 1
            idx = ones(Int, ndirs); idx[j] = length(weights)
            kern = broadcast(*, kern, reshape(weights, idx...))
        end
    end

    kern
end

but it needs review and type-stability checks.

I am opening this issue to remind me of doing this at some point 🙂 I am considering renaming the function to something more specific like impointgradients, please let me know if you find it unsatisfactory.

does not handle integer ...why???

I have data in integer and integer kernel.
after run imfilter on such data got this
ERROR: InexactError()
in unsafe_setindex! at /home/slava/.julia/v0.5/OffsetArrays/src/OffsetArrays.jl:153 [inlined]
in __imfilter_inbounds!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.FIRTiled{2}}, ::Array{Int16,2}, ::OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}, ::OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}, ::ImageFiltering.NoPad{ImageFiltering.Pad{0}}, ::CartesianRange{CartesianIndex{2}}, ::Float64) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:532
in _imfilter_inbounds!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.FIRTiled{2}}, ::Array{Int16,2}, ::OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}, ::OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}, ::ImageFiltering.NoPad{ImageFiltering.Pad{0}}, ::Tuple{UnitRange{Int64},UnitRange{Int64}}) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:499
in imfilter!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.FIRTiled{2}}, ::Array{Int16,2}, ::OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}, ::OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}, ::ImageFiltering.NoPad{ImageFiltering.Pad{0}}, ::Tuple{UnitRange{Int64},UnitRange{Int64}}) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:483
in _imfilter_tiled!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.FIRTiled{2}}, ::Array{Int16,2}, ::OffsetArrays.OffsetArray{Int16,2,Array{Int16,2}}, ::Tuple{OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}},OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}}, ::ImageFiltering.NoPad{ImageFiltering.Pad{0}}, ::Array{Array{Float64,2},1}, ::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:346
in imfilter!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.FIRTiled{2}}, ::Array{Int16,2}, ::OffsetArrays.OffsetArray{Int16,2,Array{Int16,2}}, ::Tuple{OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}},OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}}, ::ImageFiltering.NoPad{ImageFiltering.Pad{0}}, ::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:278
in imfilter!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.FIRTiled{2}}, ::Array{Int16,2}, ::Array{Int16,2}, ::Tuple{OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}},OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}}, ::ImageFiltering.Pad{0}) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:220
in imfilter!(::Array{Int16,2}, ::Array{Int16,2}, ::Tuple{OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}},OffsetArrays.OffsetArray{Float64,2,Array{Float64,2}}}, ::ImageFiltering.Pad{0}, ::ImageFiltering.Algorithm.FIRTiled{2}) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:143
in imfilter(::Array{Int16,2}, ::OffsetArrays.OffsetArray{Int16,2,Array{Int16,2}}) at /home/slava/.julia/v0.5/ImageFiltering/src/imfilter.jl:5

if I convert integer array data into float then it's ok - no error.

bug in similar() for BorderArrays

I came across this when trying to compose BorderArrays to set a different fill value for the front and back of the array. Code to demonstrate:

using ImageFiltering

b_front = BorderArray(zeros(10), Fill(1.0, (3,), (0,)))
b_both = BorderArray(b_front, Fill(1.0, (0,), (5,)))
b_sim = similar(b_both)
axes(b_sim) == axes(b_both)  # is false, should be true

I'll make a PR shortly

No feasible version could be found for package: ImageFiltering

Got this while running Pkg.update() on v0.5.2-pre+1, unfortunately not sure which package is causing the error:

julia> Pkg.update()
INFO: Updating METADATA...
INFO: Updating cache of BufferedStreams...
INFO: Updating cache of Images...
INFO: Updating cache of Libz...
INFO: Updating cache of Media...
INFO: Updating cache of ColorTypes...
INFO: Updating cache of GLAbstraction...
INFO: Updating cache of MbedTLS...
INFO: Updating cache of Gadfly...
INFO: Updating cache of BinDeps...
INFO: Updating cache of Blink...
INFO: Updating cache of AxisAlgorithms...
INFO: Updating cache of ZMQ...
INFO: Updating cache of StatsBase...
INFO: Updating cache of IJulia...
INFO: Updating cache of Graphics...
INFO: Updating cache of MacroTools...
INFO: Updating cache of URIParser...
INFO: Updating cache of LineSearches...
INFO: Updating cache of GeometryTypes...
INFO: Updating cache of DataFrames...
INFO: Updating cache of GLVisualize...
INFO: Updating cache of Distributions...
INFO: Updating cache of GLWindow...
INFO: Updating cache of Atom...
INFO: Updating cache of DataArrays...
INFO: Updating cache of ForwardDiff...
INFO: Updating cache of Conda...
INFO: Updating cache of DiffBase...
INFO: Updating cache of Compose...
INFO: Updating cache of ColorVectorSpace...
INFO: Updating cache of FixedPointNumbers...
INFO: Updating cache of FileIO...
INFO: Updating cache of VT100...
INFO: Updating cache of Juno...
INFO: Updating cache of Compat...
INFO: Updating cache of Mux...
INFO: Updating cache of SHA...
INFO: Updating cache of Iterators...
INFO: Updating cache of JSON...
INFO: Updating cache of WoodburyMatrices...
INFO: Updating cache of AbstractTrees...
INFO: Updating cache of Homebrew...
INFO: Updating cache of YAML...
INFO: Updating cache of Interpolations...
INFO: Updating cache of Codecs...
INFO: Updating cache of StatsFuns...
INFO: Updating cache of KernelDensity...
INFO: Updating cache of ArrayFire...
INFO: Updating cache of Distances...
INFO: Updating cache of FreeType...
INFO: Updating cache of Colors...
INFO: Updating cache of DataStructures...
INFO: Updating cache of GLFW...
INFO: Updating cache of Optim...
INFO: Updating cache of SortingAlgorithms...
INFO: Updating cache of Calculus...
INFO: Updating cache of Requests...
INFO: Updating cache of FunctionalCollections...
INFO: Updating cache of PDMats...
INFO: Updating cache of PositiveFactorizations...
INFO: Updating cache of Nettle...
INFO: Updating cache of Reactive...
INFO: Updating cache of DualNumbers...
INFO: Updating JuliaParser master... b62e117a → f15bb47f
WARNING: Package Vega: skipping update (dirty)...
INFO: Updating UAParser master...
INFO: Updating GLPlot master... f52a32e7 → 4972cde4
INFO: Updating LogParser master...
INFO: Updating ECharts master... 7fc12d63 → f78ab311
INFO: Updating NoveltyColors master...
INFO: Computing changes...
ERROR: unsatisfiable package requirements detected: no feasible version could be found for package: ImageFiltering
  (you may try increasing the value of the
   JULIA_PKGRESOLVE_ACCURACY environment variable)
 in resolve(::Dict{String,Base.Pkg.Types.VersionSet}, ::Dict{String,Dict{VersionNumber,Base.Pkg.Types.Available}}) at ./pkg/resolve.jl:37
 in resolve(::Dict{String,Base.Pkg.Types.VersionSet}, ::Dict{String,Dict{VersionNumber,Base.Pkg.Types.Available}}, ::Dict{String,Tuple{VersionNumber,Bool}}, ::Dict{String,Base.Pkg.Types.Fixed}, ::Dict{String,VersionNumber}, ::Set{String}) at ./pkg/entry.jl:495
 in update(::String, ::Set{String}) at ./pkg/entry.jl:458
 in (::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#update,Tuple{String,Set{String}}})() at ./pkg/dir.jl:31
 in cd(::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#update,Tuple{String,Set{String}}}, ::String) at ./file.jl:59
 in cd(::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#update,Tuple{String,Set{String}}}, ::String) at /Users/rzwitc200/julia/usr/lib/julia/sys.dylib:?
 in #cd#1(::Array{Any,1}, ::Function, ::Function, ::String, ::Vararg{Any,N}) at ./pkg/dir.jl:31
 in update() at ./pkg/pkg.jl:210
julia> Pkg.status()
14 required packages:
 - ArrayFire                     0.0.3
 - Atom                          0.5.8
 - GLPlot                        0.0.5+             master
 - GLVisualize                   0.1.2
 - Gadfly                        0.5.2
 - IJulia                        1.3.3
 - Interact                      0.4.3
 - LogParser                     0.3.0+             master
 - Parameters                    0.6.0
 - Patchwork                     0.3.0
 - RDatasets                     0.2.0
 - Twitter                       0.3.0
 - UAParser                      0.4.0+             master
 - Vega                          0.6.6-             master (dirty)
109 additional packages:
 - ASTInterpreter                0.0.4
 - AbstractTrees                 0.0.4
 - ArgParse                      0.4.0
 - AxisAlgorithms                0.1.5
 - Benchmark                     0.1.0
 - BinDeps                       0.4.5
 - Blink                         0.5.0
 - BufferedStreams               0.2.1
 - COFF                          0.0.2
 - CRC                           1.2.0
 - Calculus                      0.1.15
 - CodeTools                     0.4.3
 - Codecs                        0.2.0
 - ColorBrewer                   0.3.0
 - ColorTypes                    0.2.12
 - ColorVectorSpace              0.1.12
 - Colors                        0.6.9
 - Compat                        0.12.0
 - Compose                       0.4.4
 - Conda                         0.4.0
 - Contour                       0.2.0
 - DWARF                         0.1.0
 - DataArrays                    0.3.11
 - DataFrames                    0.8.5
 - DataStructures                0.5.1
 - Dates                         0.4.4
 - DiffBase                      0.0.2
 - Distances                     0.3.2
 - Distributions                 0.11.1
 - DualNumbers                   0.2.3
 - ECharts                       0.0.0-             master (unregistered)
 - ELF                           0.1.0
 - FactCheck                     0.4.3
 - FileIO                        0.2.1
 - FixedPointNumbers             0.2.1
 - FixedSizeArrays               0.2.5
 - ForwardDiff                   0.3.3
 - FreeType                      1.1.0
 - FunctionalCollections         0.2.0
 - GLAbstraction                 0.2.1
 - GLFW                          1.2.1
 - GLWindow                      0.2.1
 - GZip                          0.2.20
 - Gallium                       0.0.4
 - GeometryTypes                 0.2.1
 - Graphics                      0.1.3
 - Hexagons                      0.0.4
 - Hiccup                        0.1.1
 - Homebrew                      0.4.2
 - HttpCommon                    0.2.6
 - HttpParser                    0.2.0
 - HttpServer                    0.1.7
 - Images                        0.5.14
 - Interpolations                0.3.6
 - Iterators                     0.2.0
 - JSON                          0.8.1
 - JuliaParser                   0.7.4+             master
 - Juno                          0.2.5
 - KernelDensity                 0.3.0
 - LNR                           0.0.2
 - Lazy                          0.11.5
 - Libz                          0.2.2
 - LineSearches                  0.1.4
 - Loess                         0.1.0
 - MachO                         0.0.4
 - MacroTools                    0.3.4
 - MbedTLS                       0.4.2
 - Measures                      0.0.3
 - Media                         0.2.4
 - MeshIO                        0.0.6
 - ModernGL                      0.1.1
 - Mustache                      0.1.3
 - Mux                           0.2.2
 - NIfTI                         0.1.1
 - NaNMath                       0.2.2
 - Nettle                        0.2.4
 - NoveltyColors                 0.3.0              master
 - OAuth                         0.4.1
 - ObjFileBase                   0.0.4
 - Optim                         0.7.4
 - PDMats                        0.5.3
 - Packing                       0.0.4
 - PositiveFactorizations        0.0.3
 - Quaternions                   0.1.1
 - RData                         0.0.4
 - Ratios                        0.0.4
 - Reactive                      0.3.6
 - Reexport                      0.0.3
 - Requests                      0.3.12
 - Rmath                         0.1.6
 - SHA                           0.3.0
 - SIUnits                       0.1.0
 - Showoff                       0.0.7
 - SignedDistanceFields          0.1.0
 - SortingAlgorithms             0.1.0
 - StatsBase                     0.12.0
 - StatsFuns                     0.3.1
 - StructIO                      0.0.2
 - TerminalUI                    0.0.2
 - TexExtensions                 0.0.3
 - TextWrap                      0.1.6
 - URIParser                     0.1.7
 - UnicodeFun                    0.0.2
 - VT100                         0.0.2
 - WebSockets                    0.2.1
 - WoodburyMatrices              0.2.1
 - YAML                          0.1.10
 - ZMQ                           0.4.0
 - Zlib                          0.1.12

mapwindow custom anchor

mapwindow is a very nice utility. I wonder if it would be possible to also change the anchor. At the moment only odd sized windows are allowed. Perhaps by allowing the anchor to be changed to the corner, even sized windows can be allowed as well.

Type conservation in imfilter

Hello

It looks like imfilter does not conserve types, for example imfilter(Array{Float32}, kernel) returns Array{Float64}

Add stride argument for mapwindow

Sometimes, I need to apply a function to a window, which slides over an image. Just like what mapwindow does, except that I want my window to move by bigger steps. Would it be an option to add an additional argument to mapwindow that allows to select how far the window moves in each dimension? For example in the case of Matrix it behaves as follows:

mapwindow(f, args...; stride=(3,2)) == mapwindow(f, args..., windowsize)[1:3:end,1:2:end]

except that the unnecessary computations are omitted. If there is interest in this I can implement it.

ERROR: ... lacks the proper padding sizes for an array with 2 dimensions

I'm not entirely sure what is happening here. I'm trying to filter an image before resizing it, as recommended by the Images.jl docs. Running:

reduction_factor = new_len/minimum(size(im)[1:2])
im = imfilter(im, KernelFactors.gaussian(0.75*reduction_factor))

Results in:

ERROR: ArgumentError: ImageFiltering.Pad{1}(:replicate, (2,), (2,)) lacks the proper padding sizes for an array with 2 dimensions
Stacktrace:                                                                                                              
 [1] padindices(::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::ImageFiltering.Pad{1}) at /home/sabae/.julia/v0.6/ImageFiltering/src/border.jl:240
 [2] padarray at /home/sabae/.julia/v0.6/ImageFiltering/src/border.jl:657 [inlined]                                      
 [3] imfilter! at /home/sabae/.julia/v0.6/ImageFiltering/src/imfilter.jl:702 [inlined]                                    
 [4] imfilter!(::Array{ColorTypes.RGB{Float64},2}, ::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::Tuple{OffsetArrays.OffsetArray{Float64,1,Array{Float64,1}}}, ::ImageFiltering.Pad
{0}, ::ImageFiltering.Algorithm.FIR) at /home/sabae/.julia/v0.6/ImageFiltering/src/imfilter.jl:613
 [5] imfilter!(::Array{ColorTypes.RGB{Float64},2}, ::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::Tuple{OffsetArrays.OffsetArray{Float64,1,Array{Float64,1}}}, ::ImageFiltering.Pad
{0}) at /home/sabae/.julia/v0.6/ImageFiltering/src/imfilter.jl:607
 [6] imfilter(::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::OffsetArrays.OffsetArray{Float64,1,Array{Float64,1}}) at /home/sabae/.julia/v0.6/ImageFiltering/src/imfilter.jl:5

Trying out different padding arguments doesn't lead to much success except for the Inner() scheme, which is what I'm using for now (since I'm resizing from thousands of pixels on a side down to hundreds, so these boundary conditions don't matter much to me)

Unintended type piracy?

When loading ImageFiltering:

WARNING: Method definition _bcs1(Any, Any) in module Broadcast at broadcast.jl:439 overwritten in module ImageFiltering at /builds/JuliaGPU/MakieGallery-jl/.julia/packages/ImageFiltering/Vjzap/src/ImageFiltering.jl:27.
WARNING: Method definition _bcs1(Any, Any) in module Broadcast at broadcast.jl:439 overwritten in module ImageFiltering at /builds/JuliaGPU/MakieGallery-jl/.julia/packages/ImageFiltering/Vjzap/src/ImageFiltering.jl:27.

Probably severe argument dropping

function imfilter!(out::AbstractArray, img::AbstractArray, kernel::ProcessedKernel, args...)
imfilter!(out, img, kernel, Pad(:replicate))
end

There the args... is just dropped silently. I guess that is a copy & paste mistake and the args... should be omitted here.

Edit: In case that's the correct observation, there's a pull request: #113

Not an issue: factorkernel(centered(ones(3,3))) all negative

Hey, when building the local 3x3 sum over an intensity image I came across the question whether it'd be not much less performant to use imfilter with a ones(3,3) kernel than to do it in a map or broadcast since edgehandling is way more convenient for imfilter. In order to speed things up, I called factorkernel ahead of filtering and stumbled over:

julia> ImageFiltering.factorkernel(centered(ones(Float64,3,3)))
([-1.0; ; -1.0; ; -1.0], [-1.0 -1.0 -1.0])

I know that the sign doesn't matter here since 1*1=(-1)*(-1) though I'm curious if there is a faster way if these are all positive (maybe because *1 can be optimized) etc.
What would be the best solution to my problem?
mapwindow(x->sum(x),...)
map(areasum.(Ref(layer),x),CartesianIndices(layer))
imfilter(layer, ImageFiltering.factorkernel(centered(ones(3,3))))
imfilter(layer, centered.((ones(3), ones(3))))

WARNING: Method definition _bcs1(Any, Any)

This warning is known?

WARNING: Method definition _bcs1(Any, Any) in module Broadcast at broadcast.jl:439 overwritten in module ImageFiltering at /home/juliohm/.julia/packages/ImageFiltering/qNVTb/src/ImageFiltering.jl:23

Possible bug with Inner() option

Consider the following example:

using GeoStatsImages
using ImageFiltering
using Plots

# load an example 100x100 image
img = training_image("Strebelle")[1:100,1:100,1]

# trivial smoothing kernel
kern = ones(30,30)

# works as expected
res = imfilter(img, centered(kern), Algorithm.FFT())
heatmap(res)

Screenshot from 2019-11-07 21-24-22

# now with the Inner() option
res = imfilter(img, centered(kern), Inner(), Algorithm.FFT())
heatmap(res)

Screenshot from 2019-11-07 21-26-04

There is some strange offset. Could you please confirm the bug?

Bug in 3d cascade

From https://discourse.julialang.org/t/best-approach-to-smooth-array-none-of-my-approaches-are-very-useful/17633/12?u=tim.holy (with some typos fixed):

using ImageFiltering, Test

a = rand(10,10,10);
b = similar(a);
kf2 = kernelfactors((ones(3)/3, ones(3)/3))
kf3 =  kernelfactors((ones(3)/3, ones(3)/3, [1.0]))
for i in 1:10
       b[:,:,i] = imfilter(a[:,:,i], kf2)
end
c = imfilter(a, kf3);
b == c

gives false. And it's not just floating-point roundoff: the only slice they agree on is c[:,:,10].

Messing up Pkg.update

Today trying Pkg.update() I keep getting

ERROR: GitError(Code:ENOTFOUND, Class:Repository, Could not find repository from 'ImageFiltering')
 in Type at .\libgit2\repository.jl:11
 in install at .\pkg\write.jl:38
 in resolve at .\pkg\entry.jl:530
 in resolve(::Dict{String,Base.Pkg.Types.VersionSet}, ::Dict{String,Dict{VersionNumber,Base.Pkg.Types.Available}}, ::Dict{String,Tuple{VersionNumber,Bool}}, ::Dict{String,Base.Pkg.Types.Fixed}) at .\pkg\entry.jl:476
 in edit(::Function, ::String) at .\pkg\entry.jl:30
 in rm(::String) at .\pkg\entry.jl:81
 in (::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#rm,Tuple{String}})() at .\pkg\dir.jl:31
 in cd(::Base.Pkg.Dir.##2#3{Array{Any,1},Base.Pkg.Entry.#rm,Tuple{String}}, ::String) at .\file.jl:48
 in #cd#1 at .\pkg\dir.jl:31
 in rm(::String) at .\pkg\pkg.jl:91

It's really annoying as it prevents me from doing this like Pkg.test which package do I need to remove that depends on ImageFiltering?

mapwindow functionality

The mapwindow functionality (which overlaps with RollingFunctions for the 1-D case) is a general and common Array operation outside the context of ImageFiltering. I wonder why it lives here? Might it be more accessible for general users in a package like RollingFunctions and then imported and extended here?

Filtering non-color element type

The docs seems to suggest that arrays with arbitrary element types can be filtered, but it fails depending on kernel size, e.g.,

using GeometryTypes
x = rand(Point{2,Float64},100)
y = centered(rand(31))    # smaller sizes work fine
imfilter(x,y)   # MethodError: no method matching realfloat(::Array{Point{2,Float64},1})

imfilter works fine in this example if the kernel is smaller or if explicitly choosing

imfilter(x, y, ImageFiltering.FIR())

If FFT is not supported for types other than numbers/Colorants, I think at least FIR should be automatically chosen regardless of kernel size for those types.
Ideally, maybe FFT can be supported for other types by the user providing custom channelview or somthing similar.

imfilter! is slower with an Array source than an OffsetArray

Could imfilter use the secret sauce from the specialization for OffsetArray in more cases? I've not wrapped my head fully around all the indexing permutations, but here's a simple benchmark test case:

This hits the fast OffsetArray implementation:

img = rand(0:1, 1024, 1024)
const kern = ImageFiltering.factorkernel(centered([10 2 10; 2 1 2; 10 2 10]))
src = ImageFiltering.padarray(Int, img, Pad(:reflect, 1,1))
dest = similar(img)
@benchmark imfilter!($dest, $src, kern, ImageFiltering.NoPad())
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     11.882 ms (0.00% GC)
  median time:      11.904 ms (0.00% GC)
  mean time:        11.910 ms (0.00% GC)
  maximum time:     13.976 ms (0.00% GC)
  --------------
  samples:          420
  evals/sample:     1

Theoretically, I think this could be faster as it does fewer computations than the one above (it skips the outside edge, yes?), but it falls back to the generic implementation:

src = img
dest = OffsetArray(similar(img, size(img).-2), (1, 1))
@benchmark imfilter!($dest, $src, kern, ImageFiltering.NoPad())
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     19.408 ms (0.00% GC)
  median time:      19.470 ms (0.00% GC)
  mean time:        19.501 ms (0.00% GC)
  maximum time:     21.914 ms (0.00% GC)
  --------------
  samples:          257
  evals/sample:     1

This restores a bit of performance and hits the specialized method, but it's still a bit slower:

src = OffsetArray(img, (0,0))
dest = OffsetArray(similar(img, size(img).-2), (1, 1))
@benchmark imfilter!($dest, $src, kern, ImageFiltering.NoPad())
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     13.947 ms (0.00% GC)
  median time:      13.965 ms (0.00% GC)
  mean time:        13.985 ms (0.00% GC)
  maximum time:     18.823 ms (0.00% GC)
  --------------
  samples:          358
  evals/sample:     1

`imfilter` with `KernelFactors.IIRGaussian()` and `OffsetArray` causes bounds error

using Images, TestImages, ImageFiltering, OffsetArrays

img1 = Gray{Float64}.(testimage("mandrill"))
img2 = OffsetArray(img1, 3, 0)
sigma = 1.0
N = 2
kerng = KernelFactors.IIRGaussian(sigma)
kern = ntuple(d->kerng, Val(N))

# Error
img_smoothed_main = imfilter(img2, kern, NA())

The error is:

julia> img_smoothed_main = imfilter(img2, kern, NA())
ERROR: BoundsError: attempt to access Base.Slice{UnitRange{Int64}} with indices 4:515 at index [1:3]
Stacktrace:
 [1] throw_boundserror(::Base.Slice{UnitRange{Int64}}, ::Tuple{UnitRange{Int64}}) at ./abstractarray.jl:492
 [2] checkbounds at ./abstractarray.jl:457 [inlined]
 [3] getindex at ./indices.jl:302 [inlined]
 [4] _imfilter_dim!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.IIR}, ::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9}, ::CartesianIndices{0,Tuple{}}, ::Base.Slice{UnitRange{Int64}}, ::CartesianIndices{1,Tuple{Base.Slice{UnitRange{Int64}}}}, ::Fill{Gray{Float64},0}) at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:1306
 [5] _imfilter_inplace_tuple! at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:1269 [inlined]
 [6] imfilter!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.IIR}, ::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::Tuple{ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9},ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9}}, ::Fill{Gray{Float64},0}) at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:1226
 [7] imfilter_na_separable! at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:1448 [inlined]
 [8] _imfilter_na!(::ComputationalResources.CPU1{ImageFiltering.Algorithm.IIR}, ::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::Tuple{ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9},ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9}}, ::NA{0}) at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:676
 [9] imfilter! at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:663 [inlined]
 [10] imfilter!(::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::Tuple{ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9},ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9}}, ::NA{0}, ::ImageFiltering.Algorithm.IIR) at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:612
 [11] imfilter at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:606 [inlined]
 [12] imfilter(::OffsetArray{Gray{Float64},2,Array{Gray{Float64},2}}, ::Tuple{ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9},ImageFiltering.KernelFactors.TriggsSdika{Float64,3,3,9}}, ::NA{0}) at /home/zygmunt/.julia/packages/ImageFiltering/bMda8/src/imfilter.jl:5
 [13] top-level scope at none:0

Tag a new version

The master branch fixes issue #116 , which is severe. Could you please tag a new version of the package?

Define Replicate(), Symmetric() and other border options like Inner() instead of using strings

Can you please confirm the new syntax for the following two operations:

img = ones(10,10,10)
kern = ones(3,3,3)

imfilter_fft(img, kern, "inner")
imfilter_fft(img, kern, "symmetric")

Am I correct to say that the new version is:

imfilter(img, centered(kern), Inner(), Algorithm.FFT())
imfilter(img, centered(kern), "symmetric", Algorithm.FFT())

Why Inner() is treated with a separate type unlike other options that are triggered with strings?

Optimized Median Filter

I have an implementation of median filter based on A Fast Two-Dimensional Median Filtering Algorithm. The algorithm scales very well with window size. Though the paper desribes a method specifically for 2-D images and median filter, it can easily be extended to work with N-D images and any percentile filter e.g, minima.

Comparison with mapwindow for 256x256 grayscale N0f8 image -

window size time for proposed method (ms) time for mapwindow (ms)
(3,3) 3.81 14.27
(5,5) 4.30 36.02
(7,7) 4.86 71.21
(11,11) 6.07 183.70
(21,21) 9.07 736.39

However, the algorithm only works for image types with discrete pixel values. It also doesn't scale well with increased precision of pixel values as the histogram size increases exponentially.

Comparison with mapwindow for 256x256 grayscale N0f16 image -

window size time for proposed method (ms) time for mapwindow (ms)
(3,3) 97.60 14.20
(5,5) 75.05 36.25
(7,7) 67.52 71.70
(11,11) 59.60 188.72
(21,21) 52.41 743.58

Can we use this median filter in Images.jl specifically for N0f8 images? I would be happy to submit a pull request. My code is available here.

I'm greedy, want more speed!

There's lots of nice features in this package but benchmarking my use cases didn't turn out as well as I had hoped. To keep things simple, let's limit this discussion to single threaded FIR filtering of a 1000x1000 Float32 image with a non-separable 7x7 Float32 kernel, border replication.

My baseline is a simplified version of an old imfilter implementation I have posted before; you might recognize it. More specifically run this:

using ImageFiltering
using BenchmarkTools

function my_padarray{T}(img::Matrix{T}, pad1, pad2)
    I1 = clamp((1 - pad1):(size(img, 1) + pad1), 1, size(img, 1))
    I2 = clamp((1 - pad2):(size(img, 2) + pad2), 1, size(img, 2))
    return img[I1, I2]
end

function my_imfilter{T}(img::Matrix{T}, kernel::Matrix{T})
    m, n = size(kernel)
    A = my_padarray(img, m ÷ 2, n ÷ 2)
    offsets = ((0:m-1) - (m - 1) ÷ 2) .+ ((0:n-1) - (n - 1) ÷ 2)' * size(A, 1)
    I = kernel .!= 0
    kernel_values = kernel[I]
    kernel_offsets = offsets[I]
    start_index = m ÷ 2 + (n ÷ 2) * size(A, 1)
    return low_imfilter(A[:], kernel_values, kernel_offsets, size(A, 1),
                        size(A, 2), size(img, 1), size(img, 2), start_index)
end

function low_imfilter{T}(A::Vector{T}, coefficients::Vector{T},
                         offsets::Vector{Int}, in_height::Int, in_width::Int,
                         out_height::Int, out_width::Int, start_index::Int)
    B = zeros(T, out_height, out_width)
    num_coefficients = length(coefficients)
    for n = 1:out_width
        for m = 1:out_height
            index = m + (n - 1) * in_height + start_index
            sum = zero(T)
            for k = 1:num_coefficients
                @inbounds sum += A[index + offsets[k]] * coefficients[k]
            end
            @inbounds B[m, n] = sum
        end
    end
    return B
end

img = rand(Float32, 1000, 1000)
raw_kernel = rand(Float32, 7, 7)
kernel = centered(raw_kernel)
out1 = imfilter(img, kernel, Pad(:replicate), Algorithm.FIR())
out2 = my_imfilter(img, raw_kernel)
println(maximum(abs.(out1 - out2)))
println(@benchmark imfilter!(out1, img, kernel, Pad(:replicate), Algorithm.FIR()))
println(@benchmark my_imfilter(img, raw_kernel))
println(@benchmark imfilter!(out1, img, kernel, Pad(:replicate), Algorithm.FFT()))

I get the results

5.722046f-6
BenchmarkTools.Trial: 
  samples:          52
  evals/sample:     1
  time tolerance:   5.00%
  memory tolerance: 1.00%
  memory estimate:  23.16 kb
  allocs estimate:  97
  minimum time:     94.29 ms (0.00% GC)
  median time:      95.31 ms (0.00% GC)
  mean time:        96.62 ms (0.00% GC)
  maximum time:     107.49 ms (0.00% GC)
BenchmarkTools.Trial: 
  samples:          117
  evals/sample:     1
  time tolerance:   5.00%
  memory tolerance: 1.00%
  memory estimate:  11.56 mb
  allocs estimate:  43
  minimum time:     41.90 ms (0.00% GC)
  median time:      42.52 ms (0.00% GC)
  mean time:        42.91 ms (0.59% GC)
  maximum time:     55.41 ms (1.00% GC)
BenchmarkTools.Trial: 
  samples:          83
  evals/sample:     1
  time tolerance:   5.00%
  memory tolerance: 1.00%
  memory estimate:  68.13 mb
  allocs estimate:  465
  minimum time:     41.95 ms (2.90% GC)
  median time:      49.43 ms (3.95% GC)
  mean time:        60.55 ms (21.51% GC)
  maximum time:     138.11 ms (65.60% GC)

I.e. my baseline runs more than twice as fast as the ImageFiltering FIR implementation (and slightly faster than the FFT implementation, included for comparison) despite allocating temporary memory and not doing any tiling tricks.

Are there any low-hanging optimizations left (maybe open Julia issues I've lost track of) or is this an expected trade-off for the generality of ImageFiltering? Where to start looking? Profiling unsurprisingly pins time on the the inner loop but difficult to say whether iteration/indexing is doing a good job.

mapwindow no longer works with Int window

julia> mapwindow(median, rand(10), -1:1)
10-element Array{Float64,1}:
 0.0333407
 0.11721  
 0.206572 
 0.227984 
 0.227984 
 0.158748 
 0.158748 
 0.258269 
 0.258269 
 0.203693 

julia> mapwindow(median, rand(10), 3)
ERROR: MethodError: Cannot `convert` an object of type Array{Int64,1} to an object of type CartesianIndex
This may have arisen from a call to the constructor CartesianIndex(...),
since type constructors fall back to convert methods.
Stacktrace:
 [1] make_buffer_values_realistic! at /home/arthurb/.julia/v0.6/ImageFiltering/src/mapwindow.jl:238 [inlined]
 [2] compute_output_eltype(::Base.#median, ::Array{Float64,1}, ::UnitRange{Int64}, ::ImageFiltering.Pad{0}, ::Tuple{Base.OneTo{Int64}}) at /home/arthurb/.julia/v0.6/ImageFiltering/src/mapwindow.jl:227
 [3] allocate_output at /home/arthurb/.julia/v0.6/ImageFiltering/src/mapwindow.jl:213 [inlined]
 [4] _mapwindow at /home/arthurb/.julia/v0.6/ImageFiltering/src/mapwindow.jl:76 [inlined]
 [5] #mapwindow#1(::Symbol, ::Function, ::Function, ::Array{Float64,1}, ::Int64, ::String, ::Tuple{Base.OneTo{Int64}}) at /home/arthurb/.julia/v0.6/ImageFiltering/src/mapwindow.jl:58
 [6] mapwindow(::Function, ::Array{Float64,1}, ::Int64) at /home/arthurb/.julia/v0.6/ImageFiltering/src/mapwindow.jl:55

Can the dependency on Colors be dropped?

As discussed in #42 , many people are only interested in the filtering operations and mapwindow functionality that the package provides. Do you think it is a good idea to split out the Color dependency, or maybe split out the mapwindow and filtering operations on arrays? It would be nice to have all those packages with similar functionality merged into a "best of all worlds" solution for filtering arrays.

Integral Image type

I'd like to do this the correct way as you envisioned. I looked at MappedArrays and IndirectArrays (I presume you meant the actual code itself for these packages as I could not find any docs).

If I understood correctly, there will be an IntegralImage{.....} <: AbstractArray type and we will re-define some functions from Base and add some other ones to do what boxdiff and integral_image currently do. The constructor for this type will create the integral_image.

Also, should it assume that if I is an IntegralImage and one does I[3:5, 4:10] then they want the boxdiff or will that be confusing?

Another feature could be that if someone passes an Image type to the newer boxdiff then it automatically gets the integral image and returns the correct result.

Linear extrapolation for boundary values?

The image padding machinery doesn't allow for extrapolation. This causes significant errors in the calculation of the derivative at the border, as noted in the documentation:

Ignore the values at the border since we expect them to be erroneous.

I took a look at the source to see whether I could bang out a fix in an hour, but was stymied by how heavily the current padding framework relies on indexing. Any suggestions on how one would implement this boundary condition?

imfilter inaccuracy problem

julia> using ImageFiltering

julia> x = ones(5,5);

julia> ∇x = [1 -1];

julia> imfilter(x,reflect(∇x),"circular")  zeros(5,5) # expected to be true
false

Feature request: Specify a tuple of padding styles

Hi:

It would be nice to have the possibility to specify a tuple of padding styles in the call to imfilter:
I am thinking, for example, where the array to be filtered has dimensions with different physical meanings.
The particular use case I have in mind is one where the first two dimensions are periodic boundaries, so "circular" works fine, but for the 3rd dimension (temporal) is more suited for "replicate", or another style.

I'm thinking something like:

using ImageFiltering
borders = ("circular","circular","replicate")
imfilter(f,w,borders)

This can be worked around by calling twice imfilter with different kernels, each with it's own border style, so it is by no means an urgent matter.

Additionally, with some orientation, I think I would be able to dig into this.

mapwindow does not support Inner

julia> using ImageFiltering; mapwindow(first, randn(10), (1,), Inner())
ERROR: MethodError: no method matching copy_win!(::Array{Float64,1}, ::Array{Float64,1}, 

happens with both master and #45.

Test failure if run with multiple threads

Split off from #86:

$ JULIA_NUM_THREADS=2 julia runtests.jl 
Skipping Base.active_repl
Skipping Base.active_repl_backend
Skipping Base.active_repl
Skipping Base.active_repl_backend
Test Summary: | Pass  Total
Border        |  102    102
[ Info: Two warnings are expected
┌ Warning: Likely overflow or conversion error detected. Consider specifying the output type, e.g., `imfilter(UInt16, img, kernel, ...)`
└ @ ImageFiltering ~/.julia/dev/ImageFiltering/src/imfilter.jl:625
Test Summary: | Pass  Total
1d            |   60     60
┌ Warning: Likely overflow or conversion error detected. Consider specifying the output type, e.g., `imfilter(Int32, img, kernel, ...)`
└ @ ImageFiltering ~/.julia/dev/ImageFiltering/src/imfilter.jl:625
Test Summary: | Pass  Total
2d widening   |    3      3
Test Summary: | Pass  Total
3d            |   18     18
Test Summary: | Pass  Total
tiling        |   10     10
Test Summary: | Pass  Total
FIR/FFT       | 1191   1191

Error thrown in threaded loop on thread 0: Base.DimensionMismatch(msg="requested indices (1:8, 0:9) and kernel indices (Base.Slice(-1:1), Base.Slice(0:0)) do not agree with indices of padded input, (Base.Slice(0:9), Base.Slice(1:8))")Borders (issue #85): Test Failed at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:335
  Expression: imfilter(A, Kernel.gaussian((1, 1), (3, 3)), Fill(0, (1, 0)))
    Expected: DimensionMismatch("requested indices (1:8, 0:9) and kernel indices (Base.Slice(-1:1), Base.Slice(0:0)) do not agree with indices of padded input, (Base.Slice(0:9), Base.Slice(1:8))")
  No exception thrown
Stacktrace:
 [1] macro expansion at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:335 [inlined]
 [2] macro expansion at /usr/local/julia/julia-1.0/usr/share/julia/stdlib/v1.0/Test/src/Test.jl:1083 [inlined]
 [3] top-level scope at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:239

Error thrown in threaded loop on thread 0: Base.DimensionMismatch(msg="requested indices (1:8, 0:9) and kernel indices (Base.Slice(-1:1), Base.Slice(0:0)) do not agree with indices of padded input, (Base.Slice(1:8), Base.Slice(0:9))")Borders (issue #85): Test Failed at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:336
  Expression: imfilter(A, Kernel.gaussian((1, 1), (3, 3)), Fill(0, (0, 1)))
    Expected: DimensionMismatch
  No exception thrown
Stacktrace:
 [1] macro expansion at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:336 [inlined]
 [2] macro expansion at /usr/local/julia/julia-1.0/usr/share/julia/stdlib/v1.0/Test/src/Test.jl:1083 [inlined]
 [3] top-level scope at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:239

Error thrown in threaded loop on thread 0: Base.DimensionMismatch(msg="requested indices (1:8, 0:9) and kernel indices (Base.Slice(-1:1), Base.Slice(0:0)) do not agree with indices of padded input, (Base.Slice(1:8), Base.Slice(1:8))")Borders (issue #85): Test Failed at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:337
  Expression: imfilter(A, Kernel.gaussian((1, 1), (3, 3)), Fill(0, (0, 0)))
    Expected: DimensionMismatch
  No exception thrown
Stacktrace:
 [1] macro expansion at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:337 [inlined]
 [2] macro expansion at /usr/local/julia/julia-1.0/usr/share/julia/stdlib/v1.0/Test/src/Test.jl:1083 [inlined]
 [3] top-level scope at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:239
Test Summary:       | Pass  Fail  Total
Borders (issue #85) |   35     3     38
ERROR: LoadError: LoadError: Some tests did not pass: 35 passed, 3 failed, 0 errored, 0 broken.
in expression starting at /home/tim/.julia/dev/ImageFiltering/test/2d.jl:238
in expression starting at /home/tim/.julia/dev/ImageFiltering/test/runtests.jl:12

Rename to ImageFiltering?

ImagesFiltering sounds a little awkward to me--how about renaming to ImageFiltering?

Just a suggestion.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.