Обнаружение кромок является важной техникой анализа изображений, когда кто-то заинтересован в распознавании объектов по их контурам, а также считается важным шагом в восстановлении информации из изображений.
Например, важные функции, такие как линии и кривые, могут быть извлечены с помощью обнаружения краев, которые затем обычно используются компьютерным зрением более высокого уровня или алгоритмами обработки изображений. Хороший алгоритм обнаружения краев будет выделять расположение основных краев на изображении, в то же время игнорируя любые ложные края, вызванные шумом.
Но что такое ребра? Края — это особенности изображения, которые можно использовать для оценки и анализа структуры объектов на изображении. Они представляют значительные локальные изменения, которые произошли в интенсивности изображения (то есть значение пикселя). Края обычно появляются на границе между двумя разными областями изображения.
В этом уроке я опишу алгоритм детектора ребер Канни и то, как мы можем реализовать его в Python.
Canny Edge Detector
Алгоритм детектора краев Canny назван в честь его изобретателя Джона Ф. Кэнни , который изобрел алгоритм в 1986 году. Детектор краев Canny обычно принимает изображение в градациях серого в качестве входных данных и создает изображение, показывающее местоположение разрывов интенсивности в качестве выходных данных (т. Е. Краев). ,
Я не хочу идти здесь по математике, но я опишу, что происходит за кулисами в алгоритме детектора краев Канни с точки зрения высокого уровня.
Первое, что делает детектор краев Canny, — это использование гауссовой свертки для сглаживания входного изображения и удаления шума. Первый оператор производной затем применяется к сглаженному изображению, чтобы выделить те области изображения с высокими первыми пространственными производными.
Затем алгоритм находит как величину, так и направление градиента, вычисляя x-производную и y-производную, тем более что знание направления градиента фактически позволяет нам найти направление ребер.
Затем алгоритм выполняет то, что называется немаксимальным подавлением , где он отслеживает вершину гребней, которые поднимаются от краев, и устанавливает те пиксели, которые не находятся на вершине гребня, в ноль, в результате чего в результате получается тонкая линия.
Другими словами, мы проверяем, считается ли градиент, вычисленный на предыдущем шаге, максимальным среди соседних точек, лежащих как в положительном, так и в отрицательном направлениях градиента. Если градиент был максимальным, он считается частью края, и наоборот.
Процесс отслеживания, описанный выше, контролируется двумя порогами, t1
и t2
, так что t1>t2
, называемый порогом гистерезиса . Отслеживание начинается в точке на гребне выше t1
, а затем продолжается в обоих направлениях из этой точки, пока высота гребня не станет меньше t2
.
Итак, в основном, здесь происходит то, что мы выбираем все граничные точки, которые находятся выше верхнего порога t1
, а затем исследуем, существуют ли соседи этих точек, которые рассматриваются ниже верхнего порога t1
и выше нижнего порога t2
. В этом случае такие соседи будут частью края.
Таким образом, ширина гауссова ядра, используемого для сглаживания входного изображения, и пороговые значения t1 (верхний) и t2 (нижний), используемые трекером, являются параметрами, которые определяют эффект детектора краев Canny.
Реализация Python
В этом разделе я опишу два способа реализации детектора краев Canny. Один способ использует библиотеку scikit-image
, а другой — библиотеку OpenCV
.
Canny Edge Detector Использование scikit-image
Если у вас еще не установлен 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()
к изображению (я не передавал никаких пользовательских параметров, кроме нашего изображения, и оставил его по умолчанию для функции). Наконец, мы показываем наш результат, который показывает обнаруженные ребра. Результат приведенного выше скрипта выглядит следующим образом:
Вы можете поиграться с параметрами, чтобы получить разные результаты по обнаружению краев. Но результат выглядит хорошо с этими обнаруженными краями, не так ли ?!
Canny Edge Detector Использование OpenCV
В этом разделе мы увидим, как мы можем использовать 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 .
Результат приведенного выше сценария выглядит следующим образом:
Вывод
В этом уроке мы узнали о детекторе краев Canny и увидели, как scikit-image
и OpenCV
позволяют нам легко реализовать этот детектор с помощью нескольких строк кода.