Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Обнаружение краев OpenCV в Python с помощью cv2.Canny()

Введение

Обнаружение границ — это то, что мы делаем естественно, но это не так просто, когда дело доходит до определения правил для компьютеров. Хотя были разработаны различные методы, метод господства был разработан Джоном Ф. Кэнни в 1986 г. и получил меткое название метода Кэнни.

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

Обнаружение хитрого края

Что такое метод Канни? Он состоит из четырех отдельных операций:

  • Сглаживание по Гауссу
  • Вычисление градиентов
  • Немаксимальное подавление
  • Пороговое значение гистерезиса

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

Градиенты изображения использовались в более ранних приложениях для обнаружения границ. В частности, фильтры Собеля и Шарра полагаются на градиенты изображения. Фильтр Собеля сводится к двум ядрам (Gx и Gy), где Gx обнаруживает горизонтальные изменения, в то время как Gy обнаруживает вертикальные изменения:

G

x

=

[

-
1

0

+
1

-
2

0

+
2

-
1

0

+
1

]

G

y

=

[

-
1

-
2

-
1

0

0

0

+
1

+
2

+
1

]

Когда вы перемещаете их по изображению, каждая из них «подхватывает» (подчеркивает) линии в соответствующей ориентации. Ядра Шарра работают одинаково, но с разными значениями:

G

x

=

[

+
3

0

-
3

+
10

0

-
10

+
3

0

-
3

]

G

y

=

[

+
3

+
10

+
3

0

0

0

-
3

-
10

-
3

]

Эти фильтры, свернутые с изображением, создадут карты объектов:

Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Изображение предоставлено: Дэвидукеннеди.

Для этих карт объектов вы можете вычислить величина градиента и градиентная ориентация – т.е. насколько интенсивным является изменение (насколько вероятно, что что-то является краем) и в каком направлении оно указывает. Поскольку Gy обозначает вертикальное изменение (Y-градиент), а Gx обозначает горизонтальное изменение (X-градиент), вы можете вычислить величину, просто применив теорему Пифагора, чтобы получить гипотенузу треугольника, образованного «левым» и «правильные» направления:

$$
{G} = {sqrt {{{G} _{x}}^{2}+{{G} _{y}}^{2}}}
$$

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

Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Изображение предоставлено: Дэвидукеннеди.

Однако — вы можете видеть, сколько шума было уловлено также и от конструкции кирпичей! Градиенты изображения очень чувствительны к шуму. Именно поэтому фильтры Собеля и Шарра использовались в качестве компонента, но не единственного подхода в методе Кэнни. Здесь также помогает сглаживание по Гауссу.

Немаксимальное подавление

Заметная проблема с фильтром Собеля заключается в том, что края не очень четкие. Это не похоже на то, что кто-то взял карандаш и нарисовал линию, чтобы создать линейное изображение. Края на изображениях обычно не такие четкие, так как свет постепенно рассеивается. Однако мы можем найти общую линию по краям и подавить остальные пиксели вокруг нее, получив вместо этого чистую тонкую линию разделения. Это известно как немаксимальное подавление! Немаксимальные пиксели (меньше, чем тот, с которым мы их сравниваем в небольшом локальном поле, таком как ядро ​​​​3 × 3) подавляются. Эта концепция применима к большему количеству задач, чем эта, но давайте пока привяжем ее к этому контексту.

Пороговое значение гистерезиса

Многие некраи могут и, вероятно, будут оцениваться как края из-за условий освещения, материалов на изображении и т. д. Из-за различных причин, по которым происходят эти просчеты — трудно провести автоматическую оценку того, что такое край и чем он не является. 'т. Вы можете пороговые градиенты и включать только более сильные, предполагая, что «настоящие» края более интенсивны, чем «поддельные» края.

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

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

Давайте загрузим изображение и выполним его в оттенках серого (Канни, так же как Собель/Шарр требует, чтобы изображения были в оттенках серого):

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('finger.jpg', cv2.IMREAD_GRAYSCALE)
img_blur = cv2.GaussianBlur(img, (3,3), 0)

plt.imshow(img_blur, cmap='gray')

Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

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

Обнаружение краев на изображениях с помощью cv2.Canny()

Алгоритм Канни можно применять с помощью OpenCV. Canny() Метод:

cv2.Canny(input_img, lower_bound, upper_bound)

Ознакомьтесь с нашим практическим руководством по изучению Git с рекомендациями, принятыми в отрасли стандартами и прилагаемой памяткой. Перестаньте гуглить команды Git и на самом деле изучить это!

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

Входное изображение будет размыто методом Канни, но часто вам будет полезно его размыть. до тоже входит. Метод применяет к входным данным размытие по Гауссу 5 × 5, прежде чем выполнять остальные операции, но даже при этом размытии все еще может просачиваться некоторый шум, поэтому мы размыли изображение перед тем, как передать его в алгоритм:


edge = cv2.Canny(img_blur, 20, 30)

fig, ax = plt.subplots(1, 2, figsize=(18, 6), dpi=150)
ax[0].imshow(img, cmap='gray')
ax[1].imshow(edge, cmap='gray')

Это приводит к:

Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

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

Автоматическое пороговое значение для cv2.Canny()?

Можете ли вы найти оптимальный набор пороговых значений? Да, но это не всегда работает. Вы можете сделать свой собственный расчет для некоторого хорошего значения, а затем настроить диапазон с помощью sigma вокруг этого порога:

lower_bound = (1-sigma)*threshold
upper_bound = (1+sigma)*threshold

После появления sigma, скажем, 0.33 - граница будет 0.66*threshold и 1.33*threshold, допуская ~ 1/3 диапазона вокруг него. Хотя, найдя threshold вот что сложнее. OpenCV предоставляет нам метод Оцу (отлично подходит для бимодальных изображений) и метод треугольника. Давайте попробуем оба из них, а также возьмем простую медиану значений пикселей в качестве третьего варианта:

otsu_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_OTSU)
triangle_thresh, _ = cv2.threshold(img_blur, 0, 255, cv2.THRESH_TRIANGLE)
manual_thresh = np.median(img_blur)

def get_range(threshold, sigma=0.33):
    return (1-sigma) * threshold, (1+sigma) * threshold

otsu_thresh = get_range(otsu_thresh)
triangle_thresh = get_range(triangle_thresh)
manual_thresh = get_range(manual_thresh)

print(f"Otsu's Threshold: {otsu_thresh} nTriangle Threshold: {triangle_thresh} nManual Threshold: {manual_thresh}")

Это приводит к:

Otsu's Threshold: (70.35, 139.65) 
Triangle Threshold: (17.419999999999998, 34.58) 
Manual Threshold: (105.18999999999998, 208.81)

Это совсем другие! Судя по значениям, которые мы видели ранее, мы можем предположить, что метод Треугольника работает здесь лучше всего. Ручной порог не очень информативен, так как он просто берет среднее значение пикселя и в конечном итоге имеет высокий базовый порог, который далее умножается на широкий диапазон для этого изображения. Метод Оцу страдает от этого меньше, но тем не менее страдает.

Если мы запустим Canny() метод с этими пороговыми диапазонами:

edge_otsu = cv2.Canny(img_blur, *otsu_thresh)
edge_triangle = cv2.Canny(img_blur, *triangle_thresh)
edge_manual = cv2.Canny(img_blur, *manual_thresh)

fig, ax = plt.subplots(1, 3, figsize=(18, 6), dpi=150)
ax[0].imshow(edge_otsu, cmap='gray')
ax[1].imshow(edge_triangle, cmap='gray')
ax[2].imshow(edge_manual, cmap='gray')

Примечание: Функция ожидает несколько аргументов, а наши пороги представляют собой один кортеж. Мы можем разрушать кортеж на несколько аргументов, добавив к нему префикс *. Это также работает со списками и множествами и является отличным способом предоставления нескольких аргументов после их получения программными средствами.

Это приводит к:

Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Метод Треугольника здесь сработал очень хорошо! Это не гарантирует, что он будет хорошо работать и в других случаях.

Обнаружение границ видео в реальном времени с помощью cv2.Canny()

Наконец, давайте применим обнаружение границ Canny к видео в режиме реального времени! Мы будем отображать обрабатываемое видео (каждый кадр по мере его обработки), используя cv2.imshow() который отображает окно с кадром, который мы хотели бы отобразить. Тем не менее, мы также сохраним видео в файл MP4, который позже можно будет просмотреть и поделиться им.

Чтобы загрузить видео с помощью OpenCV, мы используем VideoCapture() метод. Если мы пройдем в 0 - он будет записывать с текущей веб-камеры, поэтому вы также можете запустить код на своей веб-камере! Если вы передадите имя файла, он загрузит файл:

def edge_detection_video(filename):
    cap = cv2.VideoCapture(filename)
    
    fourcc = cv2.VideoWriter_fourcc(*'MP4V')
    out = cv2.VideoWriter('output.mp4', fourcc, 30.0, (int(cap.get(3)), int(cap.get(4))), isColor=False)
    
    while cap.isOpened():
        (ret, frame) = cap.read()
        if ret == True:
            frame = cv2.GaussianBlur(frame, (3, 3), 0)
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            edge = cv2.Canny(frame, 50, 100)
            out.write(edge)
            cv2.imshow('Edge detection', edge)
        else:
            break

        if cv2.waitKey(10) & 0xFF == ord('q'):
            break

    cap.release()
    out.release()
    cv2.destroyAllWindows()

edge_detection_video('secret_video.mp4')

Ассоциация VideoWriter принимает несколько параметров — имя выходного файла, FourCC (четыре кода кодека, обозначающие кодек, используемый для кодирования видео), частоту кадров и разрешение в виде кортежа. Чтобы не угадывать и не изменять размер видео — мы использовали ширину и высоту исходного видео, полученные с помощью VideoCapture экземпляр, содержащий данные о самом видео, такие как ширина, высота, общее количество кадров и т. д.

Пока захват открыт, пытаемся прочитать следующий кадр с cap.read(), который возвращает код результата и следующий кадр. Код результата True or False, обозначающий наличие следующего кадра или его отсутствие. Только когда будет кадр, попробуем его обработать дальше, иначе разорвем петлю. Для каждого действительного кадра мы пропускаем его через размытие по Гауссу, конвертируем в оттенки серого, запускаем cv2.Canny() на нем и напишите его, используя VideoWriter на диск и отображать с помощью cv2.imshow() для живого просмотра.

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

Когда вы запускаете метод с secret_video.mp4 input — вы увидите всплывающее окно и, как только оно закончится, файл в вашем рабочем каталоге:

Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Заключение

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

Двигаясь дальше — практическое глубокое обучение компьютерному зрению

Ваша любознательная натура заставляет вас идти дальше? Рекомендуем ознакомиться с нашим "Курс": «Практическое глубокое обучение компьютерному зрению с помощью Python».

Обнаружение границ OpenCV в Python с помощью cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Еще один курс по компьютерному зрению?

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

Мы хотим сосредоточиться на демистификация, практичность, понимание, интуиция и реальные проекты. Хочу учиться КАК Вы можете внести разнообразие? Мы проведем вас от того, как наш мозг обрабатывает изображения, до написания классификатора глубокого обучения исследовательского уровня для рака молочной железы, до сетей глубокого обучения, которые «галлюцинируют», обучая вас принципам и теории посредством практической работы, вооружая вас ноу-хау и инструменты, чтобы стать экспертом в применении глубокого обучения для решения задач компьютерного зрения.

Что внутри?

  • Первые принципы зрения и как научить компьютеры «видеть»
  • Различные задачи и приложения компьютерного зрения
  • Ремесленные инструменты, которые облегчат вашу работу
  • Поиск, создание и использование наборов данных для компьютерного зрения
  • Теория и применение сверточных нейронных сетей
  • Обработка смещения домена, совпадения и других смещений в наборах данных
  • Передача обучения и использование времени обучения и вычислительных ресурсов других в ваших интересах
  • Создание и обучение современного классификатора рака молочной железы
  • Как применить здоровую дозу скептицизма к господствующим идеям и понять последствия широко распространенных методов
  • Визуализация «концептуального пространства» ConvNet с использованием t-SNE и PCA
  • Тематические исследования того, как компании используют методы компьютерного зрения для достижения лучших результатов
  • Правильная оценка модели, визуализация скрытого пространства и выявление внимания модели
  • Выполнение исследования предметной области, обработка ваших собственных наборов данных и создание модельных тестов
  • Передовые архитектуры, развитие идей, что делает их уникальными и как их реализовать
  • KerasCV — WIP-библиотека для создания современных пайплайнов и моделей.
  • Как разбирать и читать статьи и реализовывать их самостоятельно
  • Выбор моделей в зависимости от вашего применения
  • Создание сквозного конвейера машинного обучения
  • Ландшафт и интуиция при обнаружении объектов с помощью Faster R-CNN, RetinaNets, SSD и YOLO
  • Экземпляр и семантическая сегментация
  • Распознавание объектов в реальном времени с помощью YOLOv5
  • Обучение детекторам объектов YOLOv5
  • Работа с трансформерами с использованием KerasNLP (надежная библиотека WIP)
  • Интеграция Transformers с ConvNets для создания подписей к изображениям
  • DeepDream
  • Оптимизация модели глубокого обучения для компьютерного зрения

Отметка времени:

Больше от Стекабьюс