Edge detection with the Sobel operator

An edge is a place where image intensity changes sharply, such as the boundary of an object. Intensity change is measured by the gradient, the vector of how fast the brightness changes in the horizontal and vertical directions. The Sobel operator estimates both with two 3 × 3 kernels. SOBEL_X responds to horizontal change (and so to vertical edges), SOBEL_Y to vertical change (and so to horizontal edges). Each kernel combines a derivative across the edge with smoothing along it, which makes it less sensitive to noise than a plain difference.

Python
import math


def convolve(image, kernel):
    kh, kw = len(kernel), len(kernel[0])
    return [
        [
            sum(image[r + i][c + j] * kernel[i][j] for i in range(kh) for j in range(kw))
            for c in range(len(image[0]) - kw + 1)
        ]
        for r in range(len(image) - kh + 1)
    ]


SOBEL_X = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
SOBEL_Y = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]]

vertical_edge = [[0, 0, 100, 100, 100] for _ in range(5)]
gx = convolve(vertical_edge, SOBEL_X)
gy = convolve(vertical_edge, SOBEL_Y)
magnitude = [[round(math.hypot(a, b)) for a, b in zip(row_x, row_y)] for row_x, row_y in zip(gx, gy)]
print(magnitude[1])
print(round(math.degrees(math.atan2(gy[1][0], gx[1][0]))))

horizontal_edge = [[0] * 5, [0] * 5, [100] * 5, [100] * 5, [100] * 5]
print(convolve(horizontal_edge, SOBEL_Y)[0])
Read the full lesson