Skip to content

Commit

Permalink
add ConvertEltype operation
Browse files Browse the repository at this point in the history
  • Loading branch information
Evizero committed Jul 3, 2017
1 parent 12394fc commit aac513e
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 1 deletion.
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# v0.2.0

New operations:

- `ConvertEltype`: Convert the array elements to the given type

Other changes:

- `Either` can now lazily combine affine operations with operations
such as `Crop`, `Zoom`, and `Resize`. This is because a new kind
of support was introduced called `Augmentor.supports_affineview`,
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ look at the corresponding section of the
| | `CropSize` | Crop area around the center with specified size.
| | `CropRatio` | Crop to specified aspect ratio.
| | `RCropRatio` | Crop random window of specified aspect ratio.
| *Conversion:* | `ConvertEltype` | Convert the array elements to the given type.
| *Layout:* | `SplitChannels` | Separate the color channels into a dedicated array dimension.
| | `CombineChannels` | Collapse the first dimension into a specific colorant.
| | `PermuteDims` | Reorganize the array dimensions into a specific order.
Expand Down
1 change: 1 addition & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
julia 0.6
MappedArrays 0.0.3
ImageCore 0.1.2
ImageTransformations 0.3.0
ImageFiltering 0.1.4
Expand Down
38 changes: 38 additions & 0 deletions docs/usersguide/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ functionality.
| Cropping | :class:`Crop` :class:`CropNative` :class:`CropSize` :class:`CropRatio` |
| | :class:`RCropRatio` |
+-----------------------+----------------------------------------------------------------------------+
| Conversion | :class:`ConvertEltype` |
+-----------------------+----------------------------------------------------------------------------+
| Information Layout | :class:`SplitChannels` :class:`CombineChannels` :class:`PermuteDims` |
| | :class:`Reshape` |
+-----------------------+----------------------------------------------------------------------------+
Expand Down Expand Up @@ -554,6 +556,42 @@ Resizing
| .. image:: https://raw.githubusercontent.com/JuliaML/FileStorage/master/Augmentor/testpattern_small.png | .. image:: https://raw.githubusercontent.com/JuliaML/FileStorage/master/Augmentor/operations/Resize.png |
+---------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------+

Conversion
--------------------

.. class:: ConvertEltype

Convert the element type of the given array/image into the
given ``eltype``. This operation is especially useful for
converting color images to grayscale (or the other way
around). That said the operation is not specific to color
types and can also be used for numeric arrays (e.g. with
separated channels).

Note that this is an element-wise convert function. Thus it
can not be used to combine or separate color channels. Use
:class:`SplitChannels` or :class:`CombineChannels` for those
purposes.

.. code-block:: jlcon
julia> op = ConvertEltype(Gray)
Convert eltype to Gray
julia> img = testpattern()
300×400 Array{RGBA{N0f8},2}:
[...]
julia> augment(img, op)
300×400 Array{Gray{N0f8},2}:
[...]
+----------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+
| Input | Output for ``ConvertEltype(GrayA)`` |
+================================================================================================================+================================================================================================================+
| .. image:: https://raw.githubusercontent.com/JuliaML/FileStorage/master/Augmentor/testpattern_small.png | .. image:: https://raw.githubusercontent.com/JuliaML/FileStorage/master/Augmentor/operations/ConvertEltype.png |
+----------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+

Information Layout
--------------------

Expand Down
7 changes: 7 additions & 0 deletions src/Augmentor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Augmentor

using ColorTypes
using ColorTypes: AbstractGray
using MappedArrays
using ImageCore
using ImageTransformations
using ImageFiltering
Expand All @@ -19,11 +20,16 @@ using Base.PermutedDimsArrays: PermutedDimsArray

export

Gray,
RGB,

SplitChannels,
CombineChannels,
PermuteDims,
Reshape,

ConvertEltype,

Rotate90,
Rotate180,
Rotate270,
Expand Down Expand Up @@ -61,6 +67,7 @@ include("types.jl")
include("operation.jl")

include("operations/channels.jl")
include("operations/convert.jl")

include("operations/noop.jl")
include("operations/cache.jl")
Expand Down
80 changes: 80 additions & 0 deletions src/operations/convert.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""
ConvertEltype <: Augmentor.Operation
Description
--------------
Convert the element type of the given array/image into the given
`eltype`. This operation is especially useful for converting
color images to grayscale (or the other way around). That said
the operation is not specific to color types and can also be used
for numeric arrays (e.g. with separated channels).
Note that this is an element-wise convert function. Thus it can
not be used to combine or separate color channels. Use
[`SplitChannels`](@ref) or [`CombineChannels`](@ref) for those
purposes.
Usage
--------------
ConvertEltype(eltype)
Arguments
--------------
- **`eltype`** : The eltype of the resulting array/image.
Examples
--------------
```julia
julia> using Augmentor, Colors
julia> A = rand(RGB, 10, 10) # three color channels
10×10 Array{RGB{Float64},2}:
[...]
julia> augment(A, ConvertEltype(Gray)) # convert to grayscale
10×10 Array{Gray{Float64},2}:
[...]
julia> augment(A, ConvertEltype(Gray{Float32})) # more specific
10×10 Array{Gray{Float32},2}:
[...]
```
see also
--------------
[`CombineChannels`](@ref), [`SplitChannels`](@ref), [`augment`](@ref)
"""
struct ConvertEltype{T} <: Operation
eltype::Type{T}
end

@inline supports_lazy(::Type{<:ConvertEltype}) = true

function applyeager(op::ConvertEltype{T}, img::AbstractArray) where T
convert(Array{T}, img)
end

function applylazy(op::ConvertEltype{T}, img::AbstractArray) where T
mappedarray(c->convert(T,c), img)
end

function showconstruction(io::IO, op::ConvertEltype)
print(io, typeof(op).name.name, '(')
ImageCore.showcoloranttype(io, op.eltype)
print(io, ')')
end

function Base.show(io::IO, op::ConvertEltype)
if get(io, :compact, false)
print(io, "Convert eltype to ")
ImageCore.showcoloranttype(io, op.eltype)
else
print(io, "Augmentor.")
showconstruction(io, op)
end
end
75 changes: 75 additions & 0 deletions test/operations/tst_convert.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
@testset "ConvertEltype" begin
@test (ConvertEltype <: Augmentor.AffineOperation) == false
@test (ConvertEltype <: Augmentor.ImageOperation) == false
@test (ConvertEltype <: Augmentor.Operation) == true

@testset "constructor" begin
@test_throws MethodError ConvertEltype()
@test typeof(@inferred(ConvertEltype(Float64))) <: ConvertEltype <: Augmentor.Operation
@test typeof(@inferred(ConvertEltype(RGB))) <: ConvertEltype <: Augmentor.Operation
@test typeof(@inferred(ConvertEltype(RGB{N0f8}))) <: ConvertEltype <: Augmentor.Operation
@test str_show(ConvertEltype(Float64)) == "Augmentor.ConvertEltype(Float64)"
@test str_show(ConvertEltype(RGB)) == "Augmentor.ConvertEltype(RGB{Any})"
@test str_show(ConvertEltype(Gray{N0f8})) == "Augmentor.ConvertEltype(Gray{N0f8})"
@test str_showconst(ConvertEltype(Float64)) == "ConvertEltype(Float64)"
@test str_showconst(ConvertEltype(RGB{N0f8})) == "ConvertEltype(RGB{N0f8})"
@test str_showcompact(ConvertEltype(Float64)) == "Convert eltype to Float64"
@test str_showcompact(ConvertEltype(Gray)) == "Convert eltype to Gray{Any}"
end
@testset "eager" begin
@test Augmentor.supports_eager(ConvertEltype) === true
@test Augmentor.supports_eager(ConvertEltype{Float64}) === true
let img = @inferred(Augmentor.applyeager(ConvertEltype(Gray), rgb_rect))
@test typeof(img) == Array{Gray{N0f8},2}
@test img == convert.(Gray, rgb_rect)
end
let img = @inferred(Augmentor.applyeager(ConvertEltype(Gray{Float32}), rgb_rect))
@test typeof(img) == Array{Gray{Float32},2}
@test img == convert.(Gray{Float32}, rgb_rect)
end
let img = @inferred(Augmentor.applyeager(ConvertEltype(Float32), checkers))
@test typeof(img) == Array{Float32,2}
@test img == convert(Array{Float32}, checkers)
end
let img = @inferred(Augmentor.applyeager(ConvertEltype(RGB), checkers))
@test typeof(img) == Array{RGB{N0f8},2}
@test img == convert.(RGB, checkers)
end
end
@testset "affine" begin
@test Augmentor.supports_affine(ConvertEltype) === false
end
@testset "affineview" begin
@test Augmentor.supports_affineview(ConvertEltype) === false
end
@testset "lazy" begin
@test Augmentor.supports_lazy(ConvertEltype) === true
@test Augmentor.supports_lazy(ConvertEltype{Float64}) === true
@test @inferred(Augmentor.supports_lazy(typeof(ConvertEltype(Gray)))) === true
let img = @inferred(Augmentor.applylazy(ConvertEltype(Gray), rgb_rect))
@test typeof(img) <: ReadonlyMappedArray{Gray{N0f8},2}
@test img == convert.(Gray, rgb_rect)
end
let img = @inferred(Augmentor.applylazy(ConvertEltype(Gray{Float32}), rgb_rect))
@test typeof(img) <: ReadonlyMappedArray{Gray{Float32},2}
@test img == convert.(Gray{Float32}, rgb_rect)
end
let img = @inferred(Augmentor.applylazy(ConvertEltype(Float32), checkers))
@test typeof(img) <: ReadonlyMappedArray{Float32,2}
@test img == convert(Array{Float32}, checkers)
end
let img = @inferred(Augmentor.applylazy(ConvertEltype(RGB), checkers))
@test typeof(img) <: ReadonlyMappedArray{RGB{N0f8},2}
@test img == convert.(RGB, checkers)
end
end
@testset "view" begin
@test Augmentor.supports_view(ConvertEltype) === false
end
@testset "stepview" begin
@test Augmentor.supports_stepview(ConvertEltype) === false
end
@testset "permute" begin
@test Augmentor.supports_permute(ConvertEltype) === false
end
end
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ImageCore, ImageFiltering, ImageTransformations, CoordinateTransformations, Interpolations, OffsetArrays, StaticArrays, ColorTypes, FixedPointNumbers, TestImages, IdentityRanges, Base.Test
using ImageCore, ImageFiltering, ImageTransformations, CoordinateTransformations, Interpolations, OffsetArrays, StaticArrays, ColorTypes, FixedPointNumbers, TestImages, IdentityRanges, MappedArrays, Base.Test
using ImageInTerminal

# check for ambiguities
Expand Down Expand Up @@ -35,6 +35,7 @@ rgb_rect = rand(RGB{N0f8}, 2, 3)
tests = [
"tst_utils.jl",
"operations/tst_channels.jl",
"operations/tst_convert.jl",
"operations/tst_noop.jl",
"operations/tst_cache.jl",
"operations/tst_rotation.jl",
Expand Down

0 comments on commit aac513e

Please sign in to comment.