Skip to content

Commit 469b393

Browse files
authored
Merge pull request #46 from lorenzoh/lorenzoh/fastai-fixes
Fixing some bugs and making some transforms more generic
2 parents a040aa5 + cc45e73 commit 469b393

File tree

8 files changed

+65
-11
lines changed

8 files changed

+65
-11
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
## [Unreleased]
1010

11+
## [0.2.3]
12+
13+
### Changed
14+
15+
- `BufferedThreadsafe` now properly passes through explicit random state
16+
- `ScaleKeepAspect` no longer sometimes produces a black border
17+
- *fix* `Sequence |> Sequence` now has a method
18+
- `ToTensor` now works on different color types and N-dimensional arrays
19+
- `MaskMulti` now has a constructor for `IndirectArray`s
20+
1121
## [0.1.5] - 2021-04-17
1222

1323
### Added

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "DataAugmentation"
22
uuid = "88a5189c-e7ff-4f85-ac6b-e6158070f02e"
33
authors = ["lorenzoh <lorenz.ohly@gmail.com>"]
4-
version = "0.2.3"
4+
version = "0.2.4"
55

66
[deps]
77
ColorBlendModes = "60508b50-96e1-4007-9d6c-f475c410f16b"
@@ -10,6 +10,7 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
1010
ImageDraw = "4381153b-2b60-58ae-a1ba-fd683676385f"
1111
ImageTransformations = "02fcd773-0e25-5acc-982a-7f6622650795"
1212
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
13+
IndirectArrays = "9b13fd28-a010-5f03-acff-a1bbcff69959"
1314
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
1415
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1516
MosaicViews = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389"

src/DataAugmentation.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module DataAugmentation
33
using ColorBlendModes
44
using CoordinateTransformations
55
using Distributions: Sampleable, Uniform, Categorical
6+
using IndirectArrays: IndirectArray
67
using ImageDraw
78
using Images
89
using Images: Colorant, permuteddimsview

src/buffered.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ struct BufferedThreadsafe <: Transform
7979
end
8080
end
8181

82+
getrandstate(btfm::BufferedThreadsafe) = getrandstate(btfm.buffereds[1])
8283
Base.show(io::IO, bt::BufferedThreadsafe) = print(io, "BufferedThreadsafe($(bt.buffereds[1].tfm))")
8384

8485

src/items/mask.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ end
3131

3232
MaskMulti(a::AbstractArray{<:Gray{T}}, args...) where T = MaskMulti(reinterpret(T, a), args...)
3333
MaskMulti(a::AbstractArray{<:Normed{T}}, args...) where T = MaskMulti(reinterpret(T, a), args...)
34+
MaskMulti(a::IndirectArray, classes = a.values, bounds = Bounds(size(a))) =
35+
MaskMulti(a.index, classes, bounds)
3436

3537
Base.show(io::IO, mask::MaskMulti{N, T}) where {N, T} =
3638
print(io, "MaskMulti{$N, $T}() with size $(size(itemdata(mask))) and $(length(mask.classes)) classes")

src/preprocessing.jl

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,23 +166,58 @@ function apply!(buf, ::ImageToTensor, image::Image; randstate = nothing)
166166
end
167167

168168
function imagetotensor(image::AbstractArray{C, N}, T = Float32) where {C<:Color, N}
169-
T.(permuteddimsview(channelview(image), ((i for i in 2:N+1)..., 1)))
169+
T.(permuteddimsview(_channelview(image), ((i for i in 2:N+1)..., 1)))
170170
end
171171

172+
#=
172173
function imagetotensor(image::AbstractArray{C, N}, T = Float32) where {TC, C<:Color{TC, 1}, N}
173-
return T.(channelview(image))
174+
return T.(_channelview(image))
174175
end
176+
=#
175177

176178

177-
function imagetotensor!(buf, image::AbstractArray{<:AbstractRGB, N}) where N
179+
# TODO: relax color type constraint, implement for other colors
180+
# single-channel colors need a `channelview` that also expands the array
181+
function imagetotensor!(buf, image::AbstractArray{<:Color, N}) where N
178182
permutedims!(
179183
buf,
180-
channelview(image),
181-
(2, 3, 1))
184+
_channelview(image),
185+
(2:N+1..., 1))
182186
end
183-
tensortoimage(a::AbstractArray{T, 3}) where T = colorview(RGB, permuteddimsview(a, (3, 1, 2)))
184-
tensortoimage(a::AbstractArray{T, 2}) where T = colorview(Gray, a)
185187

188+
function tensortoimage(a::AbstractArray)
189+
nchannels = size(a)[end]
190+
if nchannels == 3
191+
return tensortoimage(RGB, a)
192+
elseif nchannels == 1
193+
return tensortoimage(Gray, a)
194+
else
195+
error("Found image tensor with $nchannels color channels. Pass in color type
196+
explicitly.")
197+
end
198+
end
199+
200+
function tensortoimage(C::Type{<:Color}, a::AbstractArray{T, N}) where {T, N}
201+
perm = (N, 1:N-1...)
202+
return _colorview(C, permuteddimsview(a, perm))
203+
end
204+
205+
206+
function _channelview(img)
207+
chview = channelview(img)
208+
# for single-channel colors, expand the color dimension anyway
209+
if size(img) == size(chview)
210+
chview = reshape(chview, 1, size(chview)...)
211+
end
212+
return chview
213+
end
214+
215+
function _colorview(C::Type{<:Color}, img) where T
216+
if size(img, 1) == 1
217+
img = reshape(img, size(img)[2:end])
218+
end
219+
return colorview(C, img)
220+
end
186221

187222
# OneHot encoding
188223

src/projective/affine.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ end
4040

4141

4242
function getprojection(scale::ScaleKeepAspect{N}, bounds; randstate = nothing) where N
43+
# If no scaling needs to be done, return a noop transform
44+
scale.minlengths == length.(bounds.rs) && return IdentityTransformation()
45+
4346
# Offset `minlengths` by 1 to avoid black border on one side
4447
ratio = maximum((scale.minlengths .+ 1) ./ length.(bounds.rs))
45-
upperleft = SVector{N, Float32}(minimum.(bounds.rs)) .- 1
48+
upperleft = SVector{N, Float32}(minimum.(bounds.rs)) .- 0.5
4649
P = scaleprojection(Tuple(ratio for _ in 1:N))
4750
if upperleft != SVector(0, 0)
48-
P = P Translation(-upperleft)
51+
P = P Translation((Float32.(P(upperleft)) .+ 0.5f0))
4952
end
5053
return P
5154
end
@@ -55,7 +58,7 @@ function projectionbounds(tfm::ScaleKeepAspect{N}, P, bounds::Bounds{N}; randsta
5558
ratio = maximum((tfm.minlengths) ./ origsz)
5659
sz = floor.(Int,ratio .* origsz)
5760
bounds_ = transformbounds(bounds, P)
58-
bs_ = offsetcropbounds(sz, bounds_, ntuple(_ -> 1., N))
61+
bs_ = offsetcropbounds(sz, bounds_, ntuple(_ -> 0.5, N))
5962
return bs_
6063
end
6164

src/sequence.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ compose(seq::Sequence, tfm::Transform) = Sequence(seq.transforms..., tfm)
2626
compose(tfm::Transform, seq::Sequence) = compose(tfm, seq.transforms...)
2727
compose(::Identity, seq::Sequence) = seq
2828
compose(seq::Sequence, ::Identity) = seq
29+
compose(seq1::Sequence, seq2::Sequence) = compose(seq1.transforms..., seq2.transforms...)
2930

3031

3132
function apply(seq::Sequence, items::Tuple; randstate = getrandstate(seq))

0 commit comments

Comments
 (0)