Learning/IVP/Session 09
Session 09🌊

Advanced Edge Detection

Laplacian of Gaussian (LoG) for scale-aware edge detection and zero-crossing analysis.


Learning Objectives

  • Understand LoG as a second-derivative edge detector
  • Apply LoG convolution to images
  • Perform local maxima suppression
  • Detect zero-crossings and superimpose on original

Laplacian of Gaussian (LoG)

LoG combines Gaussian smoothing (to suppress noise) with the Laplacian (second derivative) to detect edges. Edges appear as zero-crossings in the LoG response. The Gaussian σ controls the scale of detected edges.

Ex9_1 — LoG convolutionPython
import cv2
import numpy as np
from scipy.ndimage import gaussian_laplace

img = cv2.imread('scene.jpg', cv2.IMREAD_GRAYSCALE).astype(np.float32)

# LoG with sigma=2
sigma = 2.0
log_response = gaussian_laplace(img, sigma=sigma)

Local Maxima Suppression (LMS)

After LoG, suppress all non-maximum values to thin edge responses to single-pixel width. Compare each pixel to its neighbors; only keep values that are local maxima (or minima for negative responses).

Ex9_1 — Local maxima suppressionPython
from scipy.ndimage import maximum_filter, minimum_filter

# Threshold for significance
threshold = 0.5 * np.max(np.abs(log_response))

# Local maxima (positive LoG)
local_max = (log_response == maximum_filter(log_response, size=3))
significant_max = local_max & (log_response > threshold)

# Local minima (negative LoG)
local_min = (log_response == minimum_filter(log_response, size=3))
significant_min = local_min & (log_response < -threshold)

edge_map = significant_max | significant_min

Zero-Crossing Detection

A zero-crossing in the LoG response marks where the second derivative changes sign — the location of an edge. We detect these by checking sign changes between neighboring pixels.

Ex9_1 — Superimpose edges on originalPython
# Create output: original image with detected edges in red
img_rgb = cv2.cvtColor(img.astype(np.uint8), cv2.COLOR_GRAY2RGB)
output = img_rgb.copy()

# Mark edges in red
output[edge_map, 0] = 255   # R channel
output[edge_map, 1] = 0     # G channel
output[edge_map, 2] = 0     # B channel

import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.subplot(1,3,1), plt.imshow(img,          cmap='gray'), plt.title('Original'),  plt.axis('off')
plt.subplot(1,3,2), plt.imshow(log_response, cmap='RdBu'), plt.title('LoG'),       plt.axis('off')
plt.subplot(1,3,3), plt.imshow(output),                    plt.title('Edges'),     plt.axis('off')
plt.tight_layout()
plt.show()