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

Кстати об особенностях

Если вы читаете этот блог, должен быть один из двух различных сценариев, которые привели вас сюда.

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

Что ж, если вы последний, то вы, должно быть, сталкивались с задачей извлечения функций из изображения, и одна из основных функций, о которой все говорят, - это края.

Так что же такое Edge?

Край на изображении - это граница или контур, на которых происходит значительное изменение некоторых физических аспектов изображения, например отражения поверхности, освещенности или расстояния до видимые поверхности со стороны зрителя.

Давайте разберемся, что это означает, на примере:

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

Итак, зачем нам ребра?

  • Часто это первый шаг в восстановлении информации из изображения.
  • Края обычно встречаются на границе двух областей изображения.
  • Их можно использовать для сегментирования областей, идентификации объектов и даже обнаружения лиц.

Итак, чтобы подвести итог ...

Край в изображении - это значительное локальное изменение интенсивности изображения,
обычно связанное с разрывом либо интенсивности изображения, либо
первой производной интенсивности изображения.

Обнаружение краев

Задача обнаружения края - это, по сути, обнаружение значительных локальных изменений в изображении.

Изображение можно рассматривать как массив, значения которого были выбраны из непрерывной функции интенсивности изображения.

Градиент - это мера изменения функции. Следовательно, значительные локальные изменения в изображении могут быть обнаружены путем аппроксимации градиента изображения. Также необходимо отметить, что градиент в двумерном пространстве эквивалентен первой производной и может быть выражен как:

Где величину края можно записать как:

А направление градиента можно записать как:

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

Давайте посмотрим:

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

Достаточно! Где Эм Эдджес?

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

  1. Фильтрация: вычисление градиента действительно дает нам значительные локальные изменения интенсивности изображения, однако на него может влиять скрытый шум в самом изображении. Чтобы предотвратить это, первым шагом в любом алгоритме обнаружения краев должно быть удаление шума при сохранении прочности краев.
  2. Улучшение краев. Иногда после фильтрации края и локальные области в какой-то мере теряют свою интенсивность. Чтобы противостоять этому, края могут быть усилены или локальные изменения интенсивности могут быть увеличены, чтобы восстановить часть утраченной силы.
  3. Обнаружение: Здесь нужно соблюдать строгость! Мы принимаем только те ориентации пикселей, которые считаются краем. Теперь, чтобы вычислить эту квалификацию, мы должны установить полосу, так сказать, порог, в зависимости от того, какой градиент может быть классифицирован как кромка.

Посмотрите на алгоритмы.

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

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

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

Чтобы опробовать оператора самостоятельно, воспользуйтесь следующим фрагментом

import cv2
ddepth = cv2.CV_16S
window_name = ('Nobel Sobel')
# reading the smooth image and converting it into grayscale
gray = cv2.cvtColor(cv2.imread('<your_image>.jpg'),cv2.COLOR_BGR2GRAY)
# calculating edges from the image
# Gradient-X
grad_x = cv2.Sobel(gray, ddepth, 1, 0, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
# Gradient-Y
grad_y = cv2.Sobel(gray, ddepth, 0, 1, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
cv2.imshow(window_name,grad)
cv2.waitKey(0)

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

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

Для опробования оператора используйте следующий код:

import cv2
ddepth = cv2.CV_16S
window_name = ('A Scharr Affair')
# reading the smooth image and converting it into RGB color space
gray = cv2.cvtColor(cv2.imread('<your_image>.jpg'),cv2.COLOR_BGR2GRAY)
# calculating edges from the image
# Gradient-x
grad_x = cv2.Scharr(gray, ddepth, 0,1)
# Gradient-Y
grad_y = cv2.Scharr(gray, ddepth, 0, 1)
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
cv2.imshow(window_name,grad)
cv2.waitKey(0)

А теперь давайте представим большие пушки!

Алгоритм обнаружения Canny Edge использует следующие шаги для обнаружения или вычисления границ заданного изображения.

  • Подавление шума: фильтр Гаусса используется для удаления шума с изображения.
  • Расчет градиентов: определение интенсивности изображения по градиентам.
  • Подавление без максимума: для этого на каждом пикселе пиксель проверяется, является ли он локальным максимумом в его окрестности в направлении градиента, в противном случае граница подавляется.
  • Пороговое значение гистерезиса: используется для определения того, является ли вычисленное ребро надежным или нет. Для этого берется полоса градиентов интенсивности, если край лежит между полосой и ее верхним значением, тогда это верный край, в противном случае он отбрасывается.

Ниже приведен фрагмент кода для вычисления края с использованием алгоритма обнаружения края Canny. Вперед, попробуйте сами :)

import cv2
window_name = ('Canny All The Way')
# reading the smooth image and converting it into RGB color space
gray = cv2.cvtColor(cv2.imread('<your_image>.jpg'),cv2.COLOR_BGR2GRAY)
edge = cv2.Canny(gray, 100, 250)
cv2.imshow(window_name,edge)
cv2.waitKey(0)

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

Эффективное и элегантное решение этой проблемы было реализовано доктором Адрианом Роузброком из pyimagesearch. Обязательно ознакомьтесь с алгоритмом здесь.

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

Давайте теперь пойдем глубже!

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

Да! Вы правильно угадали, я говорю об алгоритмах, предполагающих глубокое обучение. Они были модным словом той эпохи, и это справедливо. В последнее время широко известны применения алгоритмов глубокого обучения для обработки изображений. Если вы новичок в глубоком обучении, я рекомендую вам пройти этот потрясающий плейлист от 3 Blue 1 Brown. Если у вас есть некоторый опыт работы с алгоритмами глубокого обучения и вы хотите точно знать, как они помогают нам в обработке изображений, пройдите через этот репозиторий, который я создал с моим другом Аюшом Тхакуром.

Целостно вложенное обнаружение краев

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

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

Из-за этого недостатка был предложен метод, названный Holisitically Nested Edge Detection (HED). Он использует обрезанную VGG, подобную сверточной нейронной сети, для задачи прогнозирования изображения в изображение.

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

Полный код HED с Python и OpenCV можно найти здесь.

Оценка производительности

Ни один хороший алгоритм нельзя похвалить и поздравить, не оценив его производительность. Изображение, рассчитанное по краям, нельзя рассматривать и оценивать субъективно. Должна быть какая-то согласованная объективная метрика производительности. Было замечено, что в алгоритмах обнаружения кромок могут быть три типа ошибок:

  • Отсутствуют допустимые края.
  • Ошибки в локализации краев.
  • Классификация шума по краям.

Возьмем, к примеру, добродетель Пратта.

Некоторые другие показатели оценки включают пиковое отношение сигнала к шуму и среднеквадратичную ошибку, которые рассматривают обнаружение фронтов как типичную проблему обработки сигнала.

Резюме

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

Итак, каким будет ваше решение?

использованная литература

  1. Машинное зрение Рамеша Джайна, Рангачар Кастури.
  2. Практический Python и OpenCV от доктора Адриана Роузброка.
  3. Обработка изображений - документация OpenCV.
  4. Введение в обработку изображений.
  5. Приключения в обработке изображений с TensorFlow