Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/kernel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ function product2d(kf)
k1[1].*k1[2], k2[1].*k2[2]
end

"""
kern = box((m, n, ...))

Return a box kernel computing a moving average. `m, n, ...` specify the size of the kernel, which is centered around zero.
"""
box(sz::Dims) = broadcast(*, KernelFactors.box(sz)...)
# We don't support box(m::Int...) mostly because of `gaussian(σ::Real) = gaussian((σ, σ))` defaulting to
# isotropic 2d rather than a 1d Gaussian.

"""
```julia
diff1, diff2 = sobel()
Expand Down Expand Up @@ -380,6 +389,40 @@ function Base.convert(::Type{AbstractArray}, L::Laplacian{N}) where N
end
_reshape(L::Laplacian{N}, ::Val{N}) where {N} = L

"""
laplacian2d(alpha::Number)

Construct a weighted discrete Laplacian approximation in 2d. `alpha` controls the weighting of the faces
relative to the corners.

# Examples

```jldoctest
julia> Kernel.laplacian2d(0) # the standard Laplacian
3×3 OffsetArray(::Matrix{Float64}, -1:1, -1:1) with eltype Float64 with indices -1:1×-1:1:
0.0 1.0 0.0
1.0 -4.0 1.0
0.0 1.0 0.0

julia> Kernel.laplacian2d(1) # a corner-focused Laplacian
3×3 OffsetArray(::Matrix{Float64}, -1:1, -1:1) with eltype Float64 with indices -1:1×-1:1:
0.5 0.0 0.5
0.0 -2.0 0.0
0.5 0.0 0.5

julia> Kernel.laplacian2d(0.5) # equal weight for face-pixels and corner-pixels.
3×3 OffsetArray(::Matrix{Float64}, -1:1, -1:1) with eltype Float64 with indices -1:1×-1:1:
0.333333 0.333333 0.333333
0.333333 -2.66667 0.333333
0.333333 0.333333 0.333333
```
"""
function laplacian2d(alpha::Number=0)
lc = alpha/(1 + alpha)
lb = (1 - alpha)/(1 + alpha)
lm = -4/(1 + alpha)
return centered([lc lb lc; lb lm lb; lc lb lc])
end

"""
gabor(size_x,size_y,σ,θ,λ,γ,ψ) -> (k_real,k_complex)
Expand Down
13 changes: 13 additions & 0 deletions src/kernelfactors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
each stored in terms of their factors. The following kernels are
supported:

- `box`
- `sobel`
- `prewitt`
- `ando3`, `ando4`, and `ando5` (the latter in 2d only)
Expand Down Expand Up @@ -148,6 +149,18 @@ end

#### FIR filters

"""
kern1, kern2 = box(m, n)
kerns = box((m, n, ...))

Return a tuple of "flat" kernels, where, for example, `kern1[i] == 1/m` and has length `m`.
"""
function box(sz::Dims)
all(isodd, sz) || throw(ArgumentError("kernel dimensions must be odd, got $sz"))
return kernelfactors(ntuple(d -> centered([1/sz[d] for i=1:sz[d]]), length(sz)))
end
box(sz::Int...) = box(sz)

## gradients

"""
Expand Down
13 changes: 13 additions & 0 deletions test/specialty.jl
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ using ImageFiltering: IdentityUnitRange
z z z z edgecoef*c]
end
end
@test Kernel.laplacian2d(0.5) ≈ centered([ 1/3 1/3 1/3;
1/3 -8/3 1/3;
1/3 1/3 1/3])
end

@testset "box" begin
@test KernelFactors.box(3) == (centered([1/3, 1/3, 1/3]),)
@test KernelFactors.box(3, 5) == (centered(reshape([1/3, 1/3, 1/3], 3, 1)), centered([1/5, 1/5, 1/5, 1/5, 1/5]'))
@test KernelFactors.box((3,5,7)) == KernelFactors.box(3, 5, 7)
@test Kernel.box((3,)) == centered([1/3, 1/3, 1/3])
@test Kernel.box((3, 5)) == centered([1/3, 1/3, 1/3] .* [1/5, 1/5, 1/5, 1/5, 1/5]')
@test_throws ArgumentError KernelFactors.box((3, 4, 5))
@test_throws ArgumentError Kernel.box((3, 4, 5))
end

@testset "gaussian" begin
Expand Down