I’m very new to Julia. I’m trying to replace my Matlab code with Julia. I compared TIFF image loading speeds in Matlab and Julia, but the Matlab’s imread() is way faster than the Images’ load(). Is there any way to speed up the TIFF image loading?
The followings are codes I used. The test image was a 565 x 552 RGB image (~2MB).
Matlab
fname = "test_image.tiff";
tic;
for n = 1:5
img = double(imread(fname));
end
toc;
> Elapsed time is 0.149297 seconds.
> Elapsed time is 0.039244 seconds.
> Elapsed time is 0.040094 seconds.
Julia
using Images
fname = "test_image.tiff"
juliaRead() = begin
for n ∈ 1:5
load(fname)
end
end
@time juliaRead()
> 3.442524 seconds (1.83 M allocations: 137.901 MiB, 37.48% gc time, 33.34% compilation time: 55% of which was recompilation)
> 1.193470 seconds (2.29 k allocations: 20.828 MiB, 98.60% gc time)
> 1.196542 seconds (2.29 k allocations: 20.828 MiB, 98.45% gc time)
julia> using GMT
julia> @btime gdalread("hawaii_south.tiff");
16.711 ms (101 allocations: 1.05 MiB)
and for comparison
julia> using Images
julia> @btime load("hawaii_south.tiff");
189.968 ms (199612 allocations: 34.36 MiB)
But Matlab is the clear winner.
>> tic; for n = 1:5, img = imread('hawaii_south.tiff'); end; toc
Elapsed time is 0.015118 seconds.
Note that I dropped the double(...) to make the times comparable and note also that Matlab time is multiplied by 5. If we divide by it we get 0.0030236
Note that the original post’s timings are almost completely garbage collection. I wonder why loading five images incurs a second worth of garbage, though.
The variation in times is really big. Especially a 100x for Matlab. This is suspicious. Most likely some deferred processing is taking place. Perhaps the file is simply memory mapped and nothing else.
Have you tried:
using TiffImages
img = TiffImages.load(filepath; mmap=true);
Am I reading that code right? To work around a problem with mmapping on Windows, a preemptive GC.gc is called regardless of lazy/mmap flags and with no way to opt out?
That’s right. I’m using windows operating system. Thank you for your comments. Since almost all machines in my environment are Windows, that would be great if there is a way to get the same speed on Windows. If you know any way to speed up, that would be very helpful.
There is one update.
I’ve tried using OpenCV.jl. It’s seems the best option I can take on my Windows10 machine.
I summarized the runtime comparison what I’ve tried so far. The test image is a 565 x 552 RGB image (~2MB).
Package
time
OpenCV.jl
3.6 ms
GMT.jl
14.5 ms
TiffImages.jl
305.4 ms
Matlab
8.0 ms
Versions
julia v1.9.0
Matlab R2022a
OpenCV v4.5.3
TiffImages v0.6.4
GMT v1.1.0
Codes
julia
using OpenCV
using TiffImages
using GMT
filetif = "test_image.tiff"
@btime OpenCV.imread(filetif)
3.631 ms (20 allocations: 720 bytes)
@btime TiffImages.load(filetif)
305.342 ms (413 allocations: 4.16 MiB)
@btime GMT.gdalread(filetif)
14.536 ms (141 allocations: 2.09 MiB)
Matlab
filetif = "test_image.tiff"
tic;
for i = 1:1000
img = imread(filetif);
end
toc;
Elapsed time is 7.980724 seconds for 1000 images
-> 7.980724 ms for each.
@Kadii I love that you tried using OpenCV.jl, it’s great that OpenCV.jl can read it the fastest but then it must be noticed that OpenCV.jl doesn’t work really well with other image processing libraries in Julia that are provided by JuliaImages. So despite saving time on imread, you are forced to stay in OpenCV’s world atm mostly in OpenCV.jl.
@Ashwani_Rathee Thank you for your advise. I’ve been faced the problem you mentioned.
I realized that I could convert OpenCV::Mat to ::Array by simply calling its slices. I haven’t tried yet but I’m hoping I can pass it to JuliaImages’ functions and it works.
"""
tif_load(path)
Loads a TIFF image after temporarily disabling garbage collection,
then re-sets GC to its initial state. This is a workaround for
the 75-90% GC overhead otherwise seen when loading TIFF images.
"""
function tif_load(path)
initial_gc_state = GC.enable(false)
img = load(path)
GC.enable(initial_gc_state)
img
end
which does a pretty good job:
julia> @time TiffImages.load("test.tif"); # test.tif is a 532 x 532 RGB image
0.193545 seconds (298 allocations: 1.513 MiB, 98.69% gc time)
julia> @time tif_load("test.tif");
0.001620 seconds (298 allocations: 1.513 MiB)
Author of TiffImages here, I consider it a bug if we’re slower than Matlab
Are you also on Windows, I presume? Does your tif_load function work with the mmap=true flag set too?
I wonder if we still need that GC.load call at all (or if there’s a better solution), which was introduced in https://github.com/tlnagy/TiffImages.jl/pull/79. Unfortunately, I don’t regularly use a Windows machine so this performance gotcha has evaded me.