Статьи

Canny Edge Detector с использованием Python

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

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

Но что такое ребра? Края — это особенности изображения, которые можно использовать для оценки и анализа структуры объектов на изображении. Они представляют значительные локальные изменения, которые произошли в интенсивности изображения (то есть значение пикселя). Края обычно появляются на границе между двумя разными областями изображения.

В этом уроке я опишу алгоритм детектора ребер Канни и то, как мы можем реализовать его в Python.

Алгоритм детектора краев Canny назван в честь его изобретателя Джона Ф. Кэнни , который изобрел алгоритм в 1986 году. Детектор краев Canny обычно принимает изображение в градациях серого в качестве входных данных и создает изображение, показывающее местоположение разрывов интенсивности в качестве выходных данных (т. Е. Краев). ,

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

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

Затем алгоритм находит как величину, так и направление градиента, вычисляя x-производную и y-производную, тем более что знание направления градиента фактически позволяет нам найти направление ребер.

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

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

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

Итак, в основном, здесь происходит то, что мы выбираем все граничные точки, которые находятся выше верхнего порога t1 , а затем исследуем, существуют ли соседи этих точек, которые рассматриваются ниже верхнего порога t1 и выше нижнего порога t2 . В этом случае такие соседи будут частью края.

Таким образом, ширина гауссова ядра, используемого для сглаживания входного изображения, и пороговые значения t1 (верхний) и t2 (нижний), используемые трекером, являются параметрами, которые определяют эффект детектора краев Canny.

В этом разделе я опишу два способа реализации детектора краев Canny. Один способ использует библиотеку scikit-image , а другой — библиотеку OpenCV .

Если у вас еще не установлен scikit-image на вашем компьютере, установите его, следуя инструкциям, приведенным на странице установки scikit-image .

Поскольку я использую машину с Ubuntu , мне просто нужно было запустить следующую команду в моем терминале, чтобы запустить библиотеку:

1
sudo apt-get install python-skimage

В библиотеке scikit-image есть функция scikit-image canny() которую мы можем использовать, чтобы применить детектор края Canny к нашему изображению. Обратите внимание, что эта функция является частью feature модуля.

Прежде чем двигаться вперед, давайте поэкспериментируем с игрушечным изображением. Вы можете использовать любое изображение, хотя. Я собираюсь использовать изображение boat.png, показанное ниже (нажмите на ссылку, чтобы загрузить изображение):

Оригинальное изображение лодки

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

1
2
3
4
5
6
7
from skimage import io
from skimage import feature
 
im = io.imread(‘boat.png’)
edges = feature.canny(im)
io.imshow(edges)
io.show()

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

scikit_canny_edge_detector

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

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

Как и в библиотеке scikit-image , в OpenCV также есть функция canny() для применения алгоритма детектора краев Canny к изображению. Следующий скрипт показывает, как мы можем использовать OpenCV чтобы найти края в нашем изображении:

1
2
3
4
5
6
7
import cv2
import matplotlib.pyplot as plt
 
im = cv2.imread(‘boat.png’)
edges = cv2.Canny(im,25,255,L2gradient=False)
plt.imshow(edges,cmap=’gray’)
plt.show()

Обратите внимание, что я передал следующее в качестве аргументов функции Canny() :

  • im : имя изображения
  • lower threshold : 25
  • upper threshold : 255
  • L2gradient=False : это означает, что используется L1-норма . Если установлено значение True , будет использоваться L2-норма .

Затем для построения результатов была использована библиотека matplotlib . Чтобы узнать больше об этой библиотеке, посмотрите мой учебник: Введение в библиотеку Python Matplotlib .

Результат приведенного выше сценария выглядит следующим образом:

opencv_canny_edge_detector

В этом уроке мы узнали о детекторе краев Canny и увидели, как scikit-image и OpenCV позволяют нам легко реализовать этот детектор с помощью нескольких строк кода.