I have a 2D array of colours in Julia
using Images
white = RGB{Float32}(1, 1, 1)
green = RGB{Float32}(0.1, 1, 0.1)
blue = RGB{Float32}(0, 0.1, 1)
A = [white white;
green blue;
blue blue]
I want to turn each RGB
colour into a Array{Float32, 3}
in the higher dimension. This is what I tried:
B = map(A) do a
[a.r, a.g, a.b]
end
size(B) == (3, 2, 3) # (rows, cols, channels)
# => false
Instead, B
is a 2D-matrix of 1D-arrays.
Does Julia have a map-like method for expanding the dimensions of a matrix?
You should use ImageCore's channelview
instead:
julia> Av = channelview(A)
3×3×2 reinterpret(reshape, Float32, ::Array{RGB{Float32},2}) with eltype Float32:
[:, :, 1] =
1.0 0.1 0.0
1.0 1.0 0.1
1.0 0.1 1.0
[:, :, 2] =
1.0 0.0 0.0
1.0 0.1 0.1
1.0 1.0 1.0
The color channel is the first dimension (the fastest dimension). You can check that by setting some values and seeing the impact on the original, since Av
is a view of A
:
julia> Av[1,2,1] = -5
-5
julia> Av[1,2,2] = -10
-10
julia> A
3×2 Array{RGB{Float32},2} with eltype RGB{Float32}:
RGB{Float32}(1.0,1.0,1.0) RGB{Float32}(1.0,1.0,1.0)
RGB{Float32}(-5.0,1.0,0.1) RGB{Float32}(-10.0,0.1,1.0)
RGB{Float32}(0.0,0.1,1.0) RGB{Float32}(0.0,0.1,1.0)
In both cases we tweaked the red channel, because of using 1
as the first index.
map
doesn't work because it is elementwise, so it can only allocate an output with the same size as the input. It's not difficult to allocate your output array in this case:
function RGBtoT_loop(x::Array{RGB{T}, N}) where {T,N}
# allocate output array without any (valid) instances
result = Array{T, N+1}(undef, size(x)..., 3)
# write RGB values into output array
for i in CartesianIndices(x)
result[i, 1] = x[i].r
result[i, 2] = x[i].g
result[i, 3] = x[i].b
end
result
end
EDIT: I figured out how to do the same thing by broadcasting the getfield
method where getfield(RGBvalue, 1)
is equivalent to RGBvalue.r
. Interestingly, ndims(A)
and thus the Tuple of ones is calculated at compile-time from A
's type parameters, so this method ends up type-stable and only allocates 1 thing at run-time: the result array.
RGBtoT(x) = getfield.(x, reshape(1:3, ntuple(i->1, ndims(x))..., 3) )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With