Выделение границ: градиент яркости и оператор Собеля
Границы объектов — это места, где яркость резко меняется. Найти их — значит найти «контур» картинки.
Граница (edge) — линия в изображении, вдоль которой яркость резко меняется. Математически это место большого градиента яркости.
Почему границы — это градиент
Идём по строке пикселей: 10, 10, 10, 200, 200, 200. Там, где значение скачком меняется с 10 на 200, проходит граница тёмного и светлого. Скорость изменения — это градиент: на ровном участке он близок к нулю, на перепаде — большой. Значит, чтобы найти границы, нужно измерить, насколько резко меняется яркость в каждой точке.
Оператор Собеля
Собель — это пара свёрточных ядер. Одно (Gx) оценивает перепад по горизонтали, другое (Gy) — по вертикали. В каждой точке считаем оба и комбинируем в магнитуду градиента sqrt(Gx**2 + Gy**2): чем она больше, тем «сильнее» граница.
image = [
[10, 10, 10, 200, 200, 200],
[10, 10, 10, 200, 200, 200],
[10, 10, 10, 200, 200, 200],
[10, 10, 10, 200, 200, 200],
]
Gx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
Gy = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]]
def apply3(img, k, y, x):
acc = 0
for ky in range(3):
for kx in range(3):
acc += img[y - 1 + ky][x - 1 + kx] * k[ky][kx]
return acc
H, W = len(image), len(image[0])
print("Магнитуда градиента (Собель):")
for y in range(1, H - 1):
row = []
for x in range(1, W - 1):
gx = apply3(image, Gx, y, x)
gy = apply3(image, Gy, y, x)
mag = round((gx * gx + gy * gy) ** 0.5)
row.append(mag)
print(row)
Вывод:
Магнитуда градиента (Собель): [0, 760, 760, 0] [0, 760, 760, 0]
Смотрите: на ровных участках (тёмная зона слева, светлая справа) магнитуда — 0, а ровно на стыке тёмного и светлого — всплеск 760. Вертикальная граница «загорелась». Если нарисовать магнитуду как картинку, мы увидим контур — линию там, где был перепад.
Почему два ядра
Gx реагирует на вертикальные границы (перепад слева-направо), Gy — на горизонтальные. Объединяя их через магнитуду, детектор находит границы любого направления. Дополнительно по Gx и Gy можно вычислить направление границы — это пригодится продвинутым методам (Canny, HOG).
От Собеля к Canny
Чистый Собель даёт «толстые» и зашумлённые границы. Классический детектор Canny улучшает результат: сначала сглаживает картинку Гауссом (убирает шум), считает градиент, потом утончает границы до линии в один пиксель и отсекает слабые перепады двойным порогом. Результат — аккуратный контур. Но в основе всё та же идея: граница = большой градиент яркости.
Итог
- Граница — место резкого изменения яркости, то есть большого градиента.
- Собель — два ядра (
Gx,Gy) для горизонтального и вертикального перепадов. - Магнитуда
sqrt(Gx**2+Gy**2)«загорается» на границах. - Canny добавляет сглаживание, утончение и двойной порог поверх той же идеи.