# Gabor Kernel

Hi,
I’m trying to create and visualize a Gabor kernel.
First I used Kernel.gabor from ImageFiltering.jl and it worked, I think (I still have to learn how to use it to convolve with an image, but okay).

``````gabor = Kernel.gabor(10, 10, 2, 22.5, 2, 1, 0)
colorview(RGB, zeroarray, gabor[1], zeroarray)
``````

But since I’ll be working with image processing, I need/want to get a better grasp of it.
So I’m following this guide for python (http://vision.psych.umn.edu/users/kersten/kersten-lab/courses/Psy5036W2017/Lectures/17_PythonForVision/Demos/html/2b.Gabor.html), and I made this far:

``````function gen_gabor(siz, ω, θ)
# siz(e) = width x height; A amplitude; ω frequency = 2πf; ρ phase
radius = [floor(Int, siz[1]/2.), floor(Int, siz[2]/2.)]
x1 = [Tuple(iter[i])[1] for i = 1:length(iter)]
y1 = [Tuple(iter[i])[2] for i = 1:length(iter)]
x = x1.*cos(θ) + y1.*sin(θ)
y = -x1.*sin(θ) + y1.*cos(θ)

gauss = (((ω^2)/(4pi^3))*exp((-ω^2)/(8pi^2))).*(4(x.^2 + y.^2))
sinusoid = cos.(ω.*x).*exp((pi^2)/2)
gabor = gauss.*sinusoid

ga = reshape(gauss, size(iter))
si = reshape(sinusoid, size(iter))
gb = reshape(gabor, size(iter))
return ga, si, gb
end

siz = (256, 256)
ω = .3
θ = pi/4
(gauss, sinusoid, gabor) = gen_gabor(siz, ω, θ)

Gray.(gabor)
``````

My question then is, why it doesn’t work?
If you have another approach to it, please I’d love to know.
Thanks,

The parentheses in your gaussian were misplaced. The x y terms are in the exponential, which is not what you wrote. In figuring this out, I also went ahead and wrote this in a more “julian” style, instead of the more pythonic (vectorized) approach.

``````function gen_gabor(sz, ω, θ)
r = (sz .÷ 2)
ga = zeros(sz)
si = zeros(sz)
gb = zeros(sz)

f(x, y) = ω^2 / (4pi^3) * exp(-ω^2/(8pi^2) * (4*x^2 + y^2))

for I in CartesianIndices(sz)
x̃, ỹ = Tuple(I) .- r
s, c = sincos(θ)
x, y = [c s; -s c] * [x̃, ỹ]

ga[I] = f(x, y)
si[I] = cos(ω*x) * exp((pi^2)/2)
gb[I] = ga[I]*si[I]
end
return ga, si, gb
end
``````

Note that if not for the purposes of the exercise, `ga` and `si` would not be necessary outputs of the function, and in that case should not be allocated at all.

1 Like

Hi, I love what you did there. Made everything look easier and cleaner. Thanks a lot.

For visualization, how’d you do it?

I guess I should scale those values, I have to learn how; Gray.(gabor) isn’t doing what I hoped.

Thanks again, I learnt a lot!

I used `ImageView` to visualize, using `Gray.(gb)` just like you did.

``````using ImageView

imshow(Gray.(gen_gabor((256,256), 0.5, π/5)[3]))
``````

If you’re seeing a very dark image using a different method, that’s because the values in the `gb` matrix are poorly normalized (some are negative, and even the positive ones are quite small). The `ImageView` viewer is doing some normalization/contrast adjustment automatically to show a better image (the same thing that the python demo was doing, by the way, as their matrix is identical to ours). I can get the following result (very similar to ImageView’s output) by rescaling all the values in the matrix to be between 0 and 0.8:

``````using Plots
# rescale formula [a, b] ↦ [y, z]
rescale(x, a, b, y, z) = (x - a) * (z - y)/ (b - a) + y

gb = gen_gabor((256,256), 0.3, π/4)[3]
plot(Gray.(rescale.(gb, minimum(gb), maximum(gb), 0.0, 0.8))
``````

Thank you so much!

To be honest I still couldn’t see any of the outputs. But it must be something broken on my end. `imshow` outputs a white image, and `plot` a grey background only.

To be honest I still couldn’t see any of the outputs. But it must be something broken on my end. `imshow` outputs a white image, and `plot` a grey background only.

Interesting that you can’t see it any which way… Did you check the values in the matrix prior to calling `Gray` to see if they’re reasonable? If you rescale them, do they successfully rescale so their minimum and maximum are 0 and 0.8 respectively?

You can add the `TestImages` package to see if `ImageView` can view things other than that plot (that you know should work). Heck, you can even try to visualize `rand()` and try to debug it that way…

Ok, I think `ImageView` is working; I could view something there.

Now for the matrices, something is wrong indeed. The original `gabor` has really big numbers, negative and positive, right?
Then `Gray` keeps them without scaling. Is that expected? I thought it would rescale them to the interval [0, 1].
And when I use `rescale` it does compress the values between .0 and .8 but the mean value is almost .8 (.799 something).

I must be doing something really stupid… sorry for that.

1 Like

I’m not quite seeing the same statistics, so maybe there is yet another difference between our gen_gabor functions? Here is mine again (this time with extraneous stuff removed). Do you mind trying again with this one? If it works you can compare source code to find the discrepancy.

``````function gen_gabor(sz, ω, θ)
r = (sz .÷ 2)
gb = zeros(sz)

f(x, y) = ω^2 / (4pi^3) * exp(-ω^2/(8pi^2) * (4*x^2 + y^2))

for I in CartesianIndices(sz)
x̃, ỹ = Tuple(I) .- r
s, c = sincos(θ)
x, y = [c s; -s c] * [x̃, ỹ]

gb[I] = f(x, y) * cos(ω*x) * exp((pi^2)/2)
end
return gb
end
``````

The statistics I see are:

``````julia> gb = gen_gabor((256,256), 0.3, π/4);

julia> minimum(gb), maximum(gb), mean(gb)
(-0.06360674975739578, 0.1008997906173088, 1.525878906249998e-5)
``````

There are values in `gb` like `-9.84825e-16`, which may be throwing you off, but note that the exponent there is negative, so they are small numbers.

After rescaling, the relationships should remain the same:

``````julia> gbrsc = rescale.(gb, extrema(gb)..., 0.0, 0.8);

julia> minimum(gbrsc), maximum(gbrsc), mean(gbrsc)
(0.0, 0.8, 0.3093956430013947)
``````

Yes. `Gray` converts each number independently (it is broadcast with `.`) so it has no sense of the overall image. I think also it would generally be undesirable for it to try to rescale or normalize an input matrix into a “pleasing” image. That sort of processing should happen elsewhere (in our case with `rescale`).

1 Like

Aff, I have it now!! Feels so good =]

You’re the best! Thank you!

1 Like