Giter Site home page Giter Site logo

imagebase.jl's Introduction

ImageBase

Build Status Coverage

This is a twin package to ImageCore with functions that are used among many of the packages in JuliaImages. The main purpose of this package is to reduce unnecessary compilation overhead from external dependencies.

This package reexports ImageCore so can be a direct replacement of it.

Check the reference page for more information of the functions.

imagebase.jl's People

Contributors

jagoosw avatar johnnychen94 avatar timholy avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

jagoosw t-bltg

imagebase.jl's Issues

recursive `restrict` as pyramid

A second thought on JuliaImages/Images.jl#971 (comment)

gaussian_pyramid -> maybe ImageFiltering with new name build_pyramid and supports generic kernels. (EDIT @timholy: I don't think we can, gaussian_pyramid requires imresize from ImageTransformations. This might be a good candidate for remaining in Images.jl.)

It might be useful to define a more generic version of build_pyramid here with function f input.

# apply `f(restrict(img, dims))` recursively for `n_scales` times
build_pyramid(f=identity, img; dims::Dims, n_scales::Int)
# apply `f(restrict(img, dims))` recursively until `all(size(smallest_img) .< stop_size)` holds
build_pyramid(f=identity, img; stop_size)

When f(x) = imfilter(img, KernelFactors.IIRGaussian(sigma), NA()) then it becomes a gaussian pyramid.

The benefit is that we get a more generic version, and since we don't rely on either imresize or imfilter, we can keep this function in ImageBase.


FWIW, building pyramid also falls into the reduce diagram: build_pyramid(f, x::AbstractArray, n) = reduce((x,y)->push!(x, f(restrict(last(x)))), 1:n; init=[x])

Adding Gaussian Pyramid

After I couldn't find a gaussian pyramid implementation in Julia I quickly made a simple implementation:

struct Pyramid{T,M<:AbstractMatrix{T}} <: AbstractMatrix{T}
    data::Vector{M}
end

function Pyramid(data::AbstractMatrix; min_resolution=1024, mode=Linear())
    ranges(d) = (LinRange(1, size(data, 1), size(d, 1)), LinRange(1, size(data, 2), size(d, 2)))
    ET = ImageBase.restrict_eltype(first(data))
    resized = convert(Matrix{ET}, data)
    pyramid = [interpolate(eltype(ET), ET, ranges(resized), resized, Gridded(mode))]
    while any(x -> x > min_resolution, size(resized))
        resized = restrict(resized)
        interp = interpolate(eltype(ET), ET, ranges(resized), resized, Gridded(mode))
        push!(pyramid, interp)
    end
    Pyramid(pyramid)
end

function (p::Pyramid)(x::LinRange, y::LinRange)
    xystep = step.((x, y))
    maxsize = size(p.data[1])
    val, idx = findmin(p.data) do data 
        steps = step.(LinRange.(1, maxsize, size(data)))
        norm(xystep .- steps)
    end
    level = p.data[idx]
    return level(x, y)
end

function Base.size(p::Pyramid)
    return size(p.data[1])
end
function Base.show(io::IO, ::MIME"text/plain", p::Pyramid)
    show(io, p)
end
function Base.show(io::IO, p::Pyramid)
    println(io, "Pyramid with levels: $(size.(p.data))")
end

Is this something we want to add to ImageBase?

Some `@test_broken` now seem to pass on 1.10

minfinite, maxfinite, maxabsfinite: Error During Test at /home/pkgeval/.julia/packages/ImageBase/z0ixH/test/statistics.jl:104
  Expression evaluated to non-Boolean
  Expression: #= /home/pkgeval/.julia/packages/ImageBase/z0ixH/test/statistics.jl:104 =# @inferred maximum_finite(A; dims = 1)
       Value: N0f8[0.976N0f8 0.957N0f8 … 0.796N0f8 0.529N0f8]
minfinite, maxfinite, maxabsfinite: Error During Test at /home/pkgeval/.julia/packages/ImageBase/z0ixH/test/statistics.jl:105
  Expression evaluated to non-Boolean
  Expression: #= /home/pkgeval/.julia/packages/ImageBase/z0ixH/test/statistics.jl:105 =# @inferred minimum_finite(A; dims = 1)
       Value: N0f8[0.059N0f8 0.267N0f8 … 0.435N0f8 0.09N0f8]
...

etc. I guess this means that the @inferred macro now goes through but then the test is written in a way where it doesn't handle that gracefully.

cc @timholy

precompilation fails on master

(@v1.12) pkg> add ImageBase
[...]
Precompiling all packages...
  ✗ ImageBase
  0 dependencies successfully precompiled in 4 seconds. 21 already precompiled.
  1 dependency errored.
  For a report of the errors see `julia> err`. To retry use `pkg> precompile`

julia> err
PkgPrecompileError: The following 1 direct dependency failed to precompile:

ImageBase 

Failed to precompile ImageBase [c817782e-172a-44cc-b673-b171935fbb9e] to "/tmp/depot/compiled/v1.12/ImageBase/jl_AMhQry".
ERROR: LoadError: UndefVarError: `Color` not defined in `ImageBase.FiniteDiff`
Julia Version 1.12.0-DEV.766
Commit 9d8ecaa899d (2024-06-21 17:00 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 24 × Intel(R) Xeon(R) CPU E5-2430 0 @ 2.20GHz
  WORD_SIZE: 64
  LLVM: libLLVM-17.0.6 (ORCJIT, sandybridge)
Threads: 1 default, 0 interactive, 1 GC (on 24 virtual cores)
Environment:
  JULIA_DEPOT_PATH = /tmp/depot

FiniteDiff: support Bool array

Just need to eagerly promote the array to float types

julia> ImageBase.FiniteDiff.fdiff(rand(Bool, 4, 4), dims=1)
ERROR: InexactError: Bool(-1)

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

`maxabsfinite` is breaking

# in Images
julia> maxabsfinite(rand(RGB, 4, 4))
2.219370615838762

# in ImageBase
julia> maxabsfinite(rand(RGB, 4, 4))
RGB{Float64}(0.9807213248971391,0.9620842090794137,0.9778493728627977)

I also notice that kwargs are not tested.

julia> maxfinite(rand(RGB, 4, 4); dims=1)
ERROR: MethodError: no method matching reducedim_init(::ImageBase.Map12{typeof(isfinite), typeof(identity), typeof(typemin)}, ::typeof(ImageBase.maxc), ::Matrix{RGB{Float64}}, ::Int64)
Closest candidates are:
  reducedim_init(::Any, ::typeof(min), ::AbstractArray, ::Any) at reducedim.jl:129
  reducedim_init(::Any, ::typeof(max), ::AbstractArray, ::Any) at reducedim.jl:129
  reducedim_init(::Any, ::typeof(&), ::Union{Base.AbstractBroadcasted, AbstractArray}, ::Any) at reducedim.jl:159
  ...
Stacktrace:
 [1] _mapreduce_dim(f::ImageBase.Map12{typeof(isfinite), typeof(identity), typeof(typemin)}, op::Function, #unused#::Base._InitialValue, A::Matrix{RGB{Float64}}, dims::Int64)
   @ Base ./reducedim.jl:324
 [2] #mapreduce#672
   @ ./reducedim.jl:310 [inlined]
 [3] maxfinite(A::Matrix{RGB{Float64}}; kwargs::Base.Iterators.Pairs{Symbol, Int64, Tuple{Symbol}, NamedTuple{(:dims,), Tuple{Int64}}})
   @ ImageBase ~/Documents/Julia/ImageBase.jl/src/statistics.jl:34
 [4] top-level scope
   @ REPL[7]:1

Looks like we need more comprehensive tests and compatibility tests for these functions.

More generic `restrict` support on various arrays with offsets

https://github.com/JuliaImages/ImageBase.jl/pull/4/files#r691967154

Ideally, we should not dispatch on array type OffsetArray in

function restrict(A::OffsetArray{T,N}, dim::Integer) where {T,N}
indsA = axes(A)
newinds = map(UnitRange, ntuple(i->i==dim ? restrict_indices(indsA[dim]) : indsA[i], Val(N)))
# By shifting it back to normal array, the internal for loop becomes faster because
# it requires less indexing computation
OffsetArray(restrict(A.parent, dim), newinds)
end

deprecate `varfinite` in favor of `varmult_finite`

Because it is unclear what operation is applied when we compute abs2(c::RGB), in ColorVectorSpace v0.9 we've removed abs2 and deprecated var in favor of varmult. Then we reimplemented abs2 again with proper deprecation (see also JuliaGraphics/ColorVectorSpace.jl#172)

In #17 efforts are paid to provide a consistent and more functional API for meanfinite, minimum_finite, maximum_finite and sumfinite to their corresponding mean, minimum, maximum and sum. It makes sense to do the same thing for varfinite here.

The proposed API is:

varmult(op, itr; corrected::Bool=true, mean=Statistics.mean(itr), dims=:)
varmult_finite(op, itr; corrected::Bool=true, mean=Statistics.mean(itr), dims=:)

with deprecation

# ⋅ is the inner product
@deprecate var(A; kwargs...) varmult_finite(, A; kwargs...)

cc: @jagoosw

move `mapwindow` and `extremefilt!` to ImageBase

These two functions have very similar semantics so it might be worth having a common supporting function here

  • mapwindow in ImageFiltering generates a new pixel from a square local patch
  • extremefilt! in ImageMorphology selects an existing pixel from direct neighborhoods

However, I'm not sure if it's possible to implement this efficiently. Such a failure example is JuliaImages/ImageFiltering.jl#225...

implement a lazy `ImageBase.fdiff` array?

A few months ago I've reimplemented Images.forwarddiffx #11 stuff in ImageBase for ImageSmooth usage. Now when I'm trying to migrate Images.div I realize that fdiff is still not very ideal.

For instance, to implement divergence in terms of fdiff, it is:

function fdiv!(dst::AbstractArray, V₁, Vs::AbstractArray...)
    # negative adjoint of gradient operator
    tmp .= fdiff(V₁; dims=1, rev=true)
    dst .= tmp
    for i in 1:length(Vs)
        dst .+= fdiff!(tmp, Vs[i]; dims=i+1, rev=true)
    end
    return dst
end

The idea is to implement a lazy DiffArray so that we can get rid of the tmp allocation.

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.