# Gabor Kernel

**URL:** <https://discourse.julialang.org/t/gabor-kernel/46380>\
**Category:** Visualization\
**Created:** [September 10, 2020, 1:18pm UTC](https://discourse.julialang.org/t/gabor-kernel/46380 "2020-09-10T13:18:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![rickybblock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rickybblock/32/17863_2.png) [@rickybblock](https://discourse.julialang.org/u/rickybblock)\
**Post date:** [September 10, 2020, 1:18pm UTC](https://discourse.julialang.org/t/gabor-kernel/46380/1 "2020-09-10T13:18:47Z")

</div>

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).

```julia
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 ([Notebook](http://vision.psych.umn.edu/users/kersten/kersten-lab/courses/Psy5036W2017/Lectures/17_PythonForVision/Demos/html/2b.Gabor.html)), and I made this far:

```julia
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.)]
    iter = CartesianIndices((-radius[1]:radius[1]+1, -radius[2]:radius[2]+1))
    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)

```

![gabor](https://global.discourse-cdn.com/julialang/original/3X/0/b/0bbaff2c0d4302735aa804c346f978faa45663f9.jpeg)

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

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 11, 2020, 8:57pm UTC](https://discourse.julialang.org/t/gabor-kernel/46380/2 "2020-09-11T20:57:43Z")

</div>

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.

```julia
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.

---

<div class="post-metadata">

**Author:** ![rickybblock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rickybblock/32/17863_2.png) [@rickybblock](https://discourse.julialang.org/u/rickybblock)\
**Post date:** [September 12, 2020, 1:09am UTC](https://discourse.julialang.org/t/gabor-kernel/46380/3 "2020-09-12T01:09:33Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 12, 2020, 10:35am UTC](https://discourse.julialang.org/t/gabor-kernel/46380/4 "2020-09-12T10:35:19Z")

</div>

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

```julia
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:

![gbimage](https://global.discourse-cdn.com/julialang/original/3X/7/a/7a60187d547b085543909913837cfe06b66545df.png)

```julia
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))

```

---

<div class="post-metadata">

**Author:** ![rickybblock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rickybblock/32/17863_2.png) [@rickybblock](https://discourse.julialang.org/u/rickybblock)\
**Post date:** [September 13, 2020, 2:45pm UTC](https://discourse.julialang.org/t/gabor-kernel/46380/5 "2020-09-13T14:45:15Z")

</div>

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.

I’ll accept your answers as solutions, obviously. =]

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 13, 2020, 9:26pm UTC](https://discourse.julialang.org/t/gabor-kernel/46380/6 "2020-09-13T21:26:49Z")

</div>

> 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…

---

<div class="post-metadata">

**Author:** ![rickybblock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rickybblock/32/17863_2.png) [@rickybblock](https://discourse.julialang.org/u/rickybblock)\
**Post date:** [September 16, 2020, 12:53am UTC](https://discourse.julialang.org/t/gabor-kernel/46380/7 "2020-09-16T00:53:38Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 16, 2020, 11:50am UTC](https://discourse.julialang.org/t/gabor-kernel/46380/8 "2020-09-16T11:50:22Z")

</div>

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.

```julia
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
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
julia> gbrsc = rescale.(gb, extrema(gb)..., 0.0, 0.8);

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

```

> [@rickybblock](#):
>
> Then `Gray` keeps them without scaling. Is that expected?

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`).

---

<div class="post-metadata">

**Author:** ![rickybblock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rickybblock/32/17863_2.png) [@rickybblock](https://discourse.julialang.org/u/rickybblock)\
**Post date:** [September 16, 2020, 12:32pm UTC](https://discourse.julialang.org/t/gabor-kernel/46380/9 "2020-09-16T12:32:07Z")

</div>

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

You’re the best! Thank you!
