Image

Обнаружение признаков, часть 1: производные изображения, градиенты и оператор Собеля

Применение основ исчисления к компьютерному зрению для обнаружения границ

Делиться

08c6c1ac41b7c889b4cd84d3b93ae519

Введение

Компьютерное зрение — обширная область анализа изображений и видео. Хотя многие, услышав о машинном зрении, в первую очередь думают о моделях машинного обучения, на самом деле существует гораздо больше алгоритмов, которые в некоторых случаях работают лучше, чем искусственный интеллект!

В компьютерном зрении область обнаружения признаков включает в себя определение отдельных интересующих областей на изображении. Эти результаты затем могут быть использованы для создания дескрипторов признаков — числовых векторов, представляющих локальные области изображения. После этого дескрипторы признаков нескольких фотографий одной сцены можно объединить для сопоставления изображений или даже реконструкции сцены.

В этой статье мы проведём аналогию из математического анализа, чтобы представить производные и градиенты изображений. Нам необходимо будет понять логику, лежащую в основе свёрточного ядра и, в частности, оператора Собеля — фильтра компьютерного зрения, используемого для обнаружения границ на изображении.

Интенсивность изображения

Интенсивность — одна из основных характеристик изображения. Каждый пиксель изображения имеет три компонента: R (красный), G (зелёный) и B (синий), принимающие значения от 0 до 255. Чем выше значение, тем ярче пиксель. Интенсивность пикселя — это средневзвешенное значение его компонентов R, G и B.

На самом деле существует несколько стандартов, определяющих различные веса. Поскольку мы собираемся сосредоточиться на OpenCV, мы будем использовать их формулу, которая приведена ниже:

1eb0a297b5df496894c23378214e897c

изображение = cv2.imread('image.png') B, G, R = cv2.split(изображение) изображение_в_оттенках_серого = 0,299 * R + 0,587 * G + 0,114 * B изображение_в_оттенках_серого = np.clip(изображение_в_оттенках_серого, 0, 255).astype('uint8') интенсивность = изображение_в_оттенках_серого.mean() печать(f»Интенсивность_изображения: {intensity:2f}»)

Изображения в оттенках серого

Изображения могут быть представлены с использованием различных цветовых каналов. Если каналы RGB представляют собой исходное изображение, применение приведённой выше формулы интенсивности преобразует его в формат оттенков серого, содержащий только один канал.

Поскольку сумма весов в формуле равна 1, изображение в градациях серого будет содержать значения интенсивности от 0 до 255, как и каналы RGB.

cb5d9ce69165606449398d067be6bccf

В OpenCV каналы RGB можно преобразовать в формат оттенков серого с помощью функции cv2.cvtColor(), что является более простым способом, чем метод, который мы только что рассмотрели выше.

image = cv2.imread('image.png') grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) intensity = grayscale_image.mean() print(f»Интенсивность изображения: {intensity:2f}»)

Вместо стандартной палитры RGB OpenCV использует палитру BGR. Они идентичны, за исключением того, что элементы R и B меняются местами. Для простоты в этой и следующих статьях серии мы будем использовать термины RGB и BGR как взаимозаменяемые.

При расчёте интенсивности изображения обоими методами в OpenCV результаты могут немного различаться. Это совершенно нормально, поскольку при использовании функции cv2.cvtColor OpenCV округляет преобразованные пиксели до ближайших целых чисел. Вычисление среднего значения даст небольшую разницу.

Производное изображения

Производные изображения используются для измерения скорости изменения интенсивности пикселей на изображении. Изображения можно рассматривать как функцию двух аргументов: I(x, y), где x и y определяют положение пикселя, а I — интенсивность этого пикселя.

Мы могли бы записать формально:

42c82292fb851d6c089031d11ca69c4a

Однако, учитывая тот факт, что изображения существуют в дискретном пространстве, их производные обычно аппроксимируются посредством сверточных ядер:

  • Для горизонтальной оси X: [-1, 0, 1]
  • Для вертикальной оси Y: [-1, 0, 1]ᵀ

Другими словами, мы можем переписать приведенные выше уравнения в следующем виде:

a2ce04f679868802003b435e7a54830b

Чтобы лучше понять логику работы ядер, давайте обратимся к примеру ниже.

Пример

Предположим, у нас есть матрица размером 5×5 пикселей, представляющая фрагмент изображения в оттенках серого. Элементы этой матрицы показывают интенсивность пикселей.

403b54e336334e4aa53064b341463fc5

Для вычисления производной изображения можно использовать свёрточные ядра. Идея проста: взяв пиксель изображения и несколько пикселей в его окрестности, мы находим сумму поэлементного умножения с заданным ядром, представляющим фиксированную матрицу (или вектор).

В нашем случае мы будем использовать трёхэлементный вектор [-1, 0, 1]. Из приведенного выше примера возьмём пиксель в позиции (1, 1) со значением, например, -3.

Поскольку размер ядра (выделено жёлтым) равен 3×1, нам потребуется, чтобы левый и правый элементы -3 соответствовали этому размеру, поэтому мы берём вектор [4, -3, 2]. Затем, суммируя поэлементное произведение, получаем значение -2:

730c4be2a29fbddc3004d8bb21cb6258

Значение -2 представляет собой производную для исходного пикселя. Если внимательно присмотреться, можно заметить, что производная пикселя -3 — это всего лишь разность между самым правым пикселем (2) -3 и самым левым пикселем (4).

Зачем использовать сложные формулы, если можно вычислить разность между двумя элементами? Действительно, в этом примере мы могли бы просто вычислить разность интенсивностей между элементами I(x, y + 1) и I(x, y – 1). Но в реальности мы можем справиться и с более сложными сценариями, когда нам нужно обнаружить более сложные и менее очевидные признаки. По этой причине удобно использовать обобщение ядер, матрицы которых уже известны, для обнаружения предопределённых типов признаков.

На основании значения производной можно сделать некоторые наблюдения:

  • Если значение производной в данной области изображения значимо, это означает, что интенсивность там резко меняется. В противном случае заметных изменений яркости не наблюдается.
  • Если значение производной положительно, то это означает, что слева направо область изображения становится ярче; если отрицательно, то область изображения становится темнее в направлении слева направо.

Проводя аналогию с линейной алгеброй, ядра можно рассматривать как линейные операторы на изображениях, которые преобразуют локальные области изображения.

Аналогично мы можем вычислить свёртку с вертикальным ядром. Процедура останется той же, за исключением того, что теперь мы перемещаем наше окно (ядро) вертикально по матрице изображения.

eb9ef3892b32513d6736c2329c8deea8

Вы можете заметить, что после применения фильтра свёртки к исходному изображению размером 5×5 оно стало размером 3×3. Это нормально, поскольку мы не можем применить свёртку таким же образом к пикселям на краях (иначе мы выйдем за границы).

Для сохранения размерности изображения обычно используется метод заполнения, заключающийся во временном расширении/интерполяции границ изображения или заполнении их нулями, благодаря чему свертку можно рассчитать и для граничных пикселей.

По умолчанию библиотеки, такие как OpenCV, автоматически заполняют границы, чтобы гарантировать одинаковую размерность входных и выходных изображений.

Градиент изображения

Градиент изображения показывает, насколько быстро изменяется интенсивность (яркость) в данном пикселе в обоих направлениях (X и Y).

6de77abb131b889025efa9433887134a

Формально градиент изображения можно записать как вектор производных изображения по осям X и Y.

Величина градиента

Величина градиента представляет собой норму вектора градиента и может быть найдена по следующей формуле:

764c6750e966e290f3280f892523b587

Градиентная ориентация

Используя найденные Gx и Gy, можно также вычислить угол вектора градиента:

268cedc3d687f9e338f140835de1e030

Пример

Давайте рассмотрим, как вручную вычислить градиенты на основе приведённого выше примера. Для этого нам понадобятся вычисленные матрицы 3×3 после применения ядра свёртки.

Если мы возьмем верхний левый пиксель, он имеет значения Gₓ = -2 и Gᵧ = 11. Мы можем легко вычислить величину и ориентацию градиента:

0d183b66749377238dd3ed4beaa48204

Для всей матрицы 3×3 получаем следующую визуализацию градиентов:

78b3726ff01638c5b02e17d4a0c0a371

На практике рекомендуется нормализовать ядра перед применением их к матрицам. Мы не стали этого делать ради простоты примера.

Оператор Собеля

Изучив основы производных и градиентов изображений, теперь пора перейти к оператору Собеля, который используется для их аппроксимации. В отличие от предыдущих ядер размером 3×1 и 1×3, оператор Собеля определяется парой ядер размером 3×3 (для обеих осей):

8f3065299fefe1969e013d3f2af4ee16

Это даёт оператору Собеля преимущество, поскольку ранее измеряемые ядра измеряли только одномерные изменения, игнорируя другие строки и столбцы в окрестности. Оператор Собеля учитывает больше информации о локальных регионах.

Ещё одно преимущество заключается в том, что алгоритм Собеля более устойчив к шуму. Рассмотрим фрагмент изображения ниже. Если вычислить производную вокруг красного элемента в центре, который находится на границе между тёмными (2) и светлыми (7) пикселями, то получим 5. Проблема в том, что есть шумный пиксель со значением 10.

64d94523a2e5c59a54f51ce2756ed321

Если применить горизонтальное одномерное ядро вблизи красного элемента, оно придаст значительную значимость пикселю со значением 10, который является явным выбросом. В то же время оператор Собеля более надёжен: он учитывает значение 10, а также пиксели со значением 7 вокруг него. В некотором смысле оператор Собеля применяет сглаживание.

При одновременном сравнении нескольких ядер рекомендуется нормализовать ядра матрицы, чтобы обеспечить их одинаковый масштаб. Одним из наиболее распространённых применений операторов в анализе изображений является обнаружение признаков.

В случае операторов Собеля и Шарра они обычно используются для обнаружения краев — зон, где интенсивность пикселей (и ее градиент) резко меняется.

OpenCV

Для применения операторов Собеля достаточно использовать функцию OpenCV cv2.Sobel. Рассмотрим её параметры:

производная_x = cv2.Собель(изображение, cv2.CV_64F, 1, 0) производная_y = cv2.Собель(изображение, cv2.CV_64F, 0, 1)

  • Первый параметр — это входное изображение NumPy.
  • Второй параметр (cv2.CV_64F) — это глубина данных выходного изображения. Проблема в том, что операторы, как правило, могут создавать выходные изображения, содержащие значения, выходящие за пределы диапазона 0–255. Поэтому нам необходимо указать тип пикселей, которые мы хотим получить в выходном изображении.
  • Третий и четвёртый параметры представляют порядок производной по осям x и y соответственно. В нашем случае нам нужна только первая производная по осям x и y, поэтому мы передаём значения (1, 0) и (0, 1).

Давайте рассмотрим следующий пример, где нам дано входное изображение судоку:

0efc64dbd75ac0a45637566ee601b578

Применим фильтр Собеля:

import cv2 import matplotlib.pyplot as plt image = cv2.imread(«data/input/sudoku.png») image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) derived_x = cv2.Scharr(image, cv2.CV_64F, 1, 0) derived_y = cv2.Scharr(image, cv2.CV_64F, 0, 1) derived_combined = cv2.addWeighted(derivative_x, 0.5, derived_y, 0.5, 0) min_value = min(derivative_x.min(), derived_y.min(), derived_combined.min()) max_value = max(derivative_x.max(), derived_y.max(), derived_combined.max()) print(f»Диапазон значений: ({min_value:.2f}, {max_value:.2f})») fig, axes = plt.subplots(1, 3, figsize=(16, 6), constrained_layout=True) axes[0].imshow(derivative_x, cmap='gray', vmin=min_value, vmax=max_value) axes[0].set_title(«Горизонтальная производная») axes[0].axis('off') image_1 = axes[1].imshow(derivative_y, cmap='gray', vmin=min_value, vmax=max_value) axes[1].set_title(«Вертикальная производная») axes[1].axis('off') image_2 = axes[2].imshow(derivative_combined, cmap='gray', vmin=min_value, vmax=max_value) axes[2].set_title(«Комбинированная производная») axes[2].axis('off') color_bar = fig.colorbar(image_2, ax=axes.ravel().tolist(), orientation='vertical', fraction=0.025, pad=0.04) plt.savefig(«data/output/sudoku.png») plt.show()

В результате мы видим, что горизонтальные и вертикальные производные очень хорошо распознают линии! Более того, сочетание этих линий позволяет нам обнаружить оба типа объектов:

8fd6b707924ff78324d3a64b008d6297

Оператор Шарра

Другой популярной альтернативой ядру Sober является оператор Шарра:

77878a82fa58e0326787627cc7846c26

Несмотря на существенное сходство со структурой оператора Собеля, ядро Шарра обеспечивает более высокую точность в задачах выделения контуров. Оно обладает рядом важных математических свойств, которые мы не будем рассматривать в этой статье.

OpenCV

Использование фильтра Шарра в OpenCV очень похоже на то, что мы видели выше с фильтром Собеля. Разница лишь в названии метода (остальные параметры те же):

производная_x = cv2.Scharr(изображение, cv2.CV_64F, 1, 0) производная_y = cv2.Scharr(изображение, cv2.CV_64F, 0, 1)

Вот результат, который мы получаем с помощью фильтра Шарра:

cfd186eba1e2b4ef38bef04e8375cc85

В данном случае сложно заметить разницу в результатах для обоих операторов. Однако, взглянув на цветовую карту, можно увидеть, что диапазон возможных значений, получаемых оператором Шарра, значительно шире (-800, +800), чем для оператора Собеля (-200, +200). Это нормально, поскольку ядро Шарра имеет большие константы.

Это также хороший пример того, почему нам нужно использовать специальный тип cv2.CV_64F. В противном случае значения были бы ограничены стандартным диапазоном от 0 до 255, и мы бы потеряли ценную информацию о градиентах.

Примечание. Применение методов сохранения непосредственно к изображениям cv2.CV_64F приведёт к ошибке. Чтобы сохранить такие изображения на диске, их необходимо преобразовать в другой формат и оставить только значения от 0 до 255.

Заключение

Применяя основы математического анализа к компьютерному зрению, мы изучили важнейшие свойства изображений, позволяющие обнаруживать пики интенсивности. Эти знания полезны, поскольку обнаружение особенностей — распространённая задача анализа изображений, особенно в условиях ограничений на обработку изображений или когда алгоритмы машинного обучения не используются.

Мы также рассмотрели пример использования OpenCV, чтобы понять, как работает обнаружение рёбер с операторами Собеля и Шарра. В следующих статьях мы изучим более сложные алгоритмы обнаружения объектов и рассмотрим примеры OpenCV.

Ресурсы

  • Преобразования цветов | OpenCV
  • Производные Собеля | OpenCV
  • Градиенты изображений | OpenCV
  • Оператор Собеля | Википедия

Все изображения, если не указано иное, принадлежат автору.

Источник: towardsdatascience.com

✅ Найденные теги: новости, Обнаружение

ОСТАВЬТЕ СВОЙ КОММЕНТАРИЙ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

Астрономы будут получать оповещения о небесных явлениях в течение нескольких минут после их обнаружения. Теренс О'Брайен, редактор раздела «Выходные». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной…

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых