1

I want to use the plotting functionality of Plots.jl with an image loaded using the load_image() function of ArrayFire.

What I have is :

AFArray: 1000×300×3 Array{Float32,3}

What I want is :

300×1000 Array{RGB{Any},2} with eltype RGB

I couldn't be able to find direct conversion in documentations. Is there any efficient way to do this?

atachsin
  • 173
  • 10

1 Answers1

2

I don't know specifically about ArrayFire arrays, but in general you can use reinterpret for operations like this. If you want the new array to reside on the cpu, then copy it over.

Then, ideally, you could just do

rgb = reinterpret(RGB{Float32}, A)

Unfortunately, MxNx3 is not the optimal layout for RGB arrays, since you want the 3-values to be located sequentially. So you should either make sure that the array has 3xMxN-layout, or you can do permutedims(A, (3, 1, 2)).

Finally, to get a matrix, you must drop the leading singleton dimension, otherwise you get a 1xMxN array.

So,

rgb = dropdims(reinterpret(RGB{Float32}, permutedims(A, (3, 1, 2))); dims=1)

I assumed that you actually want RGB{Float32} instead of RGB{Any}.

BTW, I'm not sure how this will work if you want to keep the final array on the GPU.

Edit: You might consider reshape instead of dropdims, it seems slightly faster on my pc.

DNF
  • 11,584
  • 1
  • 26
  • 40
  • thanks for your answer sir but that takes almost a full minute on my GPU taking 40% of its capacity on a single 100kb jpg, where the crucial part in my program is the speed. Also, the RGB channels are needlessly scaled to 255, and all I see on the screen is white. I want to say that my main reason to use Plots is to make use of its labels and axes, by reading the files directly into GPU my code became 3 times faster, should I keep trying the reinterpret function, or is there any better way to draw axes on an image with ticks and labels? – atachsin Oct 19 '20 at 17:18
  • 1
    On my computer `dropdims(reinterpret(RGB{Float32}, permutedims(A, (3, 1, 2))); dims=1)` takes <700microseconds for a 1000x300x3 array, and just 300 nanoseconds for a 3x1000x300 array. So I assume it must be communication with the GPU that takes the time. What does your code look like? Skipping the GPU would be faster. As for saturation, 0 is black and 1 is white, so everything should be scaled inside that interval. – DNF Oct 19 '20 at 17:49
  • that's interesting, I have a function called `createBigFrame` that combines 30 images into a single with `load_image` function inside which gives me `AFArray: 1000×300×3 Array{Float32,3}` in 0.03 seconds, after that I ran your code on a separate block and it took 76 seconds – atachsin Oct 20 '20 at 07:22
  • 1
    Yes, I assume it's the communication between the cpu and the gpu that is taking the time. I'm no expert on Images.jl, but I don't know if you can use `RGB` arrays on the gpu. In that case, if you really want `Array{RGB, 2}`, you may be better off dropping the gpu, since the data ends up back on the cpu anyway. Perhaps there is some way to do this *entirely* on the gpu, but I don't know how. – DNF Oct 20 '20 at 07:34
  • 1
    BTW, this type of question could be well suited to ask on https://discourse.julialang.org (remember to include a link to this question, in that case.) – DNF Oct 20 '20 at 07:37
  • Thanks for determining what the problem is, that helps me a lot. – atachsin Oct 20 '20 at 07:43
  • 1
    You can transfer back to the CPU with `Array(afa)` where `afa` is your `AFArray`. See the README: https://github.com/JuliaGPU/ArrayFire.jl – tholy Oct 20 '20 at 12:33
  • Transferring the array to CPU with `Array(afa)` and then doing the conversion eliminated the waiting time. – atachsin Oct 26 '20 at 01:09