From a0f1e28e1ac70c9b74aad5ec57b2eb570499b2f9 Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Wed, 3 Nov 2021 04:40:22 +0800 Subject: [PATCH] add CUDA testset for `Gabor` and `LogGabor` Currently we don't have very native CUDA support for these two kernels, so the test set mainly serves as "okay, we can convert the lazy kernel array to CuArray by following the steps in tests and then use GPU to do multiplication and fft" --- test/cuda/Project.toml | 2 ++ test/cuda/gaborkernels.jl | 66 +++++++++++++++++++++++++++++++++++++++ test/cuda/runtests.jl | 4 +++ 3 files changed, 72 insertions(+) create mode 100644 test/cuda/gaborkernels.jl diff --git a/test/cuda/Project.toml b/test/cuda/Project.toml index da371cd..6673f9a 100644 --- a/test/cuda/Project.toml +++ b/test/cuda/Project.toml @@ -1,10 +1,12 @@ [deps] CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" ImageBase = "c817782e-172a-44cc-b673-b171935fbb9e" ImageFiltering = "6a3955dd-da59-5b1f-98d4-e7296123deb5" ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19" ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1" ImageQualityIndexes = "2996bd0c-7a13-11e9-2da2-2f5ce47296a9" +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990" diff --git a/test/cuda/gaborkernels.jl b/test/cuda/gaborkernels.jl new file mode 100644 index 0000000..4b217f7 --- /dev/null +++ b/test/cuda/gaborkernels.jl @@ -0,0 +1,66 @@ +@testset "GaborKernels" begin + +@testset "Gabor" begin + # Gray + img = float32.(TestImages.shepp_logan(127)) + kern = Kernel.Gabor(size(img), 3.0f0, 0f0) + img_freq = fft(channelview(img)) + kern_freq = ifftshift(fft(kern)) + out = abs.(ifft(img_freq .* kern_freq)) + + # TODO(johnnychen94): currently Gabor can't be converted to CuArray directly and thus + # FFTW is applied in the CPU side. + img_cu = CuArray(img) + img_freq = fft(channelview(img_cu)) + kern_freq = CuArray(ifftshift(fft(kern))) + out_cu = abs.(ifft(img_freq .* kern_freq)) + + @test out ≈ Array(out_cu) + + # RGB + img = float32.(testimage("monarch")) + kern = Kernel.Gabor(size(img), 3.0f0, 0f0) + kern_freq = reshape(ifftshift(fft(kern)), 1, size(kern)...) + img_freq = fft(channelview(img), 2:3) + out = colorview(RGB, abs.(ifft(img_freq .* kern_freq))) + + img_cu = CuArray(img) + kern_freq = CuArray(reshape(ifftshift(fft(kern)), 1, size(kern)...)) + img_freq = fft(channelview(img_cu), 2:3) + out_cu = colorview(RGB, abs.(ifft(img_freq .* kern_freq))) + + @test out ≈ Array(out_cu) +end + +@testset "LogGabor" begin + # Gray + img = float32.(TestImages.shepp_logan(127)) + kern = Kernel.LogGabor(size(img), 1.0f0/6, 0f0) + kern_freq = OffsetArrays.no_offset_view(ifftshift(kern)) + img_freq = fft(channelview(img)) + out = abs.(ifft(kern_freq .* img_freq)) + + # TODO(johnnychen94): remove this no_offset_view wrapper + img_cu = CuArray(img) + kern_freq = CuArray(OffsetArrays.no_offset_view(ifftshift(kern))) + img_freq = fft(channelview(img_cu)) + out_cu = abs.(ifft(kern_freq .* img_freq)) + + @test out ≈ Array(out_cu) + + # RGB + img = float32.(testimage("monarch")) + kern = Kernel.LogGabor(size(img), 1.0f0/6, 0f0) + kern_freq = reshape(ifftshift(kern), 1, size(kern)...) + img_freq = fft(channelview(img), 2:3) + out = colorview(RGB, abs.(ifft(img_freq .* kern_freq))) + + img_cu = CuArray(img) + kern_freq = CuArray(reshape(ifftshift(kern), 1, size(kern)...)) + img_freq = fft(channelview(img_cu), 2:3) + out_cu = colorview(RGB, abs.(ifft(img_freq .* kern_freq))) + + @test out ≈ Array(out_cu) +end + +end diff --git a/test/cuda/runtests.jl b/test/cuda/runtests.jl index 5789d00..f86b6dc 100644 --- a/test/cuda/runtests.jl +++ b/test/cuda/runtests.jl @@ -7,11 +7,15 @@ using ImageBase using ImageQualityIndexes using Test using Random +using FFTW +using OffsetArrays +using CUDA.Adapt CUDA.allowscalar(false) @testset "ImageFiltering" begin if CUDA.functional() include("models.jl") + include("gaborkernels.jl") end end