Gabor Filter in Edge Detection

Toronto skyline with Gabor Filter

Gabor Filter in Edge Detection is a technique for improving image edge detection. Previously in our articles, we explored a simple technique for edge detection using OpenCV – Canny Edge Detection. Apart from reading our image, using only few lines of code we obtained mediocre results. Consequently, we want to explore how to get more accurate results. Upon doing a Google Search on the internet, you will find articles about Gabor Filter that fall into two camps. On one hand are articles that elaborate the complex college level math behind the theory. On the other hand are articles describing results of applying Gabor Filters but fall short of showing how to do so. As a result, we want to show how we can use Gabor Filter in edge detection without all the math.

Concepts

Think of Gabor Filters as a sine wave imposed on a bell curve (Gaussian) in 2D space. In 2D space, the sine wave is directional. Meanwhile the bell curve peaks at a point and tapers off in all directions. Combining the two results in a directional wave that focuses on a point in space within a local area. We suggest searching in your favorite search engine for an image of the Gabor Filter to better visualize this. When applying this to an image, we expose several favorable properties:

  • It emphasizes edge pixels.
  • Pixels immediately adjacent become suppressed.
  • It is directional
  • Pixels farther away have less influence (Local area)

Since the filter exhibits both a sine wave and bell curve nature, parameters common to both affect our filter:

  • sigma σ – Standard Deviation – Property of our bell curve. Smaller values emphasize values closer to the center
  • theta θ – Direction – Identifies direction of our sine wave
  • lambda λ – Wavelength – Distance between peaks in our sine wave
  • gamma γ – Ellipticity – Determines how elliptic our 2D bell curve is
  • psi φ – Offset – Defines the phase offset of our sine wave

At the heart of applying Gabor Filter in edge detection is applying each filter (for each direction) to the pixels of an image. Subsequently, we superimpose each result to create a final image. If you are interested to explore more the parameters, an article from University of Groningen in Netherlands explains this further.

Importing Libraries and OpenCV

Firstly as in all our articles, we begin by importing OpenCV and declaring a helper function. Again, the helper function is to help us display the image using matplotlib in Jupyter notebook.

import cv2
import numpy as np
from matplotlib import pyplot as plt

#The line below is necessary to show Matplotlib's plots inside a Jupyter Notebook
%matplotlib inline

from matplotlib import pyplot as plt

#Use this helper function if you are working in Jupyter Lab
#If not, then directly use cv2.imshow(<window name>, <image>)

def showimage(myimage, figsize=[10,10]):
    if (myimage.ndim>2):  #This only applies to RGB or RGBA images (e.g. not to Black and White images)
        myimage = myimage[:,:,::-1] #OpenCV follows BGR order, while matplotlib likely follows RGB order
        
    fig, ax = plt.subplots(figsize=figsize)
    ax.imshow(myimage, cmap = 'gray', interpolation = 'bicubic')
    plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis
    plt.show()

At this point, we import an image for processing

myimage = cv2.imread("Burano1.jpg")
showimage(myimage)
Burano Italy for Gabor Filter in Edge Detection
Burano Italy for Gabor Filter in Edge Detection

Practical application of Gabor Filter in Edge Detection

Now that we have our pre-requisites declared, we will create two functions. Firstly a function to create our Gabor Filters. Secondly a function to apply the filter and superimpose the results.

If you recall, the Gabor Filter has a directional element (Theta). In other words to cover edges in different directions, we need more than one Gabor Filter. Therefore we decided to create 16 filters evenly distributed around 180 degrees. This is greatly simplified using OpenCV’s built-in getGaborKernel function. Owing to this, our function returns 16 filters as a list.

def create_gaborfilter():
    # This function is designed to produce a set of GaborFilters 
    # an even distribution of theta values equally distributed amongst pi rad / 180 degree
    
    filters = []
    num_filters = 16
    ksize = 35  # The local area to evaluate
    sigma = 3.0  # Larger Values produce more edges
    lambd = 10.0
    gamma = 0.5
    psi = 0  # Offset value - lower generates cleaner results
    for theta in np.arange(0, np.pi, np.pi / num_filters):  # Theta is the orientation for edge detection
        kern = cv2.getGaborKernel((ksize, ksize), sigma, theta, lambd, gamma, psi, ktype=cv2.CV_64F)
        kern /= 1.0 * kern.sum()  # Brightness normalization
        filters.append(kern)
    return filters

Correspondingly, we create a function to apply our filters.

def apply_filter(img, filters):
# This general function is designed to apply filters to our image
    
    # First create a numpy array the same size as our input image
    newimage = np.zeros_like(img)
    
    # Starting with a blank image, we loop through the images and apply our Gabor Filter
    # On each iteration, we take the highest value (super impose), until we have the max value across all filters
    # The final image is returned
    depth = -1 # remain depth same as original image
    
    for kern in filters:  # Loop through the kernels in our GaborFilter
        image_filter = cv2.filter2D(img, depth, kern)  #Apply filter to image
        
        # Using Numpy.maximum to compare our filter and cumulative image, taking the higher value (max)
        np.maximum(newimage, image_filter, newimage)
    return newimage

At this point, we have our two functions defined and we can proceed to apply this to our image.

# We create our gabor filters, and then apply them to our image
gfilters = create_gaborfilter()
image_g = apply_filter(myimage, gfilters)

showimage(image_g)
Image with Gabor Filter in Edge Detection applied

Evidently upon closer examination, notice how edges have a “glow” to them. The edges of windows seem highlighted as well as edges of houses and the pier.

Applying Canny Edge Detection again

Up to the present time we have applied our Gabor Filter. Subsequently we apply Canny Edge detection on our new image. Finally we will show the result of Canny Edge detection before and after Gabor Filters.

min_interval = 120
max_interval = 250
image_edge_g = cv2.Canny(image_g,min_interval,max_interval)

# Using Numpy's function to append the two images horizontally
side_by_side = np.hstack((image_edge,image_edge_g))
showimage(side_by_side,[20,10])
Image with Canny Edge Detection only
Image with Canny Edge Detection only
Image with Gabor Filter and Canny Edge Detection

Conclusions

Comparatively, applying Gabor Filters in Edge Detection made significant improvements. By and large lines are cleaner and object edges are better detected. Explicitly, the wooden piers and building edges are better highlighted. Straightaway, by applying Gabor Filter, we achieve better results than directly applying Canny. Of course, by further tuning our parameters, we potentially can achieve even better results.

FreedomvcAbout Alan Wong
Alan is a part time Digital enthusiast and full time innovator who believes in freedom for all via Digital Transformation. 
兼職人工智能愛好者,全職企業家利用數碼科技釋放潛能與自由。

LinkedIn

Leave a Reply