JuliaImages / ImagesAPI.jl

Lightweight API definitions reusable in other packages
MIT License
5 stars 4 forks source link

Proposal: add abstract types ImageAlgorithm and ImageFilter #2

Open johnnychen94 opened 5 years ago

johnnychen94 commented 5 years ago

I propose to add two abstract types

abstract type AbstractImageAlgorithm end
abstract type AbstractImageFilter<: AbstractImageAlgorithm end

where filters are algorithms whose input and output are both images, so that they can be stacked together, i.e., new_img = old_img |> filter1 |> filter2 |> ...|> filterN.

These two types serve in two ways: as the root of the unified algorithms hierarchy system, and as a placeholder in ImagesAPI.jl


use case:

# ImagesAPI.jl
remove_noise(img, ::AbstractImageFilter) = img
# ImageNoise.jl
using ImageAPIs: AbstractImageFilter, denoise

abstract type AbstractImageDenoiseFilter <: AbstractImageFilter end
struct BlockMatching3dFiltering <: AbstractImageDenoiseFilter end
remove_noise(img::GenericImage, f::AbstractImageDenoiseFilter) = f(img)

function (f::BlockMatching3dFiltering)(img::GenericImage)
...
end

related issues:

https://github.com/JuliaImages/Images.jl/issues/772 https://github.com/zygmuntszpak/ImageBinarization.jl/issues/23 https://github.com/zygmuntszpak/ImageBinarization.jl/issues/26

cc: @zygmuntszpak

Tokazama commented 5 years ago

Just going off of what is found in DataAPI.jl, the original strategy was to use an "API" package as strictly general methods with very little definition. So adding abstract types would be a little different than purely following that approach.

That being said, I think whatever fits our needs best is more important than sticking to the original idea. Centering our API around abstract types may be a good way to provide a consistent front end structure that's compatible with whatever happens in the background of packages.

Note: I really like the idea of creating an abstract interface to filters.

zygmuntszpak commented 5 years ago

What if one wants to use a sequence of filters that mutate the original image? Should we have an AbstractMutatingImageFilter type?

johnnychen94 commented 5 years ago

That's why I propose to create two methods in https://github.com/JuliaImages/ImagesAPI.jl/pull/3

mutation-or-not is implementation detail, it's not the nature of the algorithm

johnnychen94 commented 5 years ago

Some further development based on this can be:

we can create a new concept Pipeline: which is either Array{<:AbstractImageFilter} or a DirectedAcyclicGraph{<:AbstractImageFilter}

For example:

corruption = [AdditiveGaussianNoise(0.0, 0.1),
    MotionBlur(0.2),
    DownScale(0.5)]

apply(img, corruption)

stacking filters together into a network becomes very popular in deep learning. In signal processing, we have filter bank as well.

zygmuntszpak commented 5 years ago

Some further development based on this can be:

we can create a new concept Pipeline: which is either Array{<:AbstractImageFilter} or a DirectedAcyclicGraph{<:AbstractImageFilter}

For example:

corruption = [AdditiveGaussianNoise(0.0, 0.1),
    MotionBlur(0.2),
    DownScale(0.5)]

apply(img, corruption)

stacking filters together into a network becomes very popular in deep learning. In signal processing, we have filter bank as well.

Perhaps Pilpeline should make use of https://github.com/tkoolen/TypeSortedCollections.jl :

TypeSortedCollections provides the TypeSortedCollection type, which can be used to store type-heterogeneous data in a way that allows operations on the data to be performed in a type-stable manner. It does so by sorting a type-heterogeneous input collection by type upon construction, and storing these elements in a Tuple of concretely typed Vectors, one for each type. TypeSortedCollections provides type stable methods for map!, foreach, broadcast!, and mapreduce that take at least one TypeSortedCollection.