Виявлення меж OpenCV у Python за допомогою cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Виявлення меж OpenCV у Python за допомогою cv2.Canny()

Вступ

Виявлення меж — це те, що ми робимо природно, але це не так просто, коли йдеться про визначення правил для комп’ютерів. Хоча були розроблені різні методи, метод панування був розроблений Джоном Ф. Кенні в 1986 році, і його влучно названо методом Канні.

Він швидкий, досить надійний і працює майже найкраще, ніж може працювати для цього типу техніки. Наприкінці посібника ви знатимете, як виконувати виявлення країв у реальному часі на відео та створювати щось на кшталт:

Canny Edge Detection

Що таке метод Canny? Він складається з чотирьох окремих операцій:

  • Гаусове згладжування
  • Обчислення градієнтів
  • Немаксимальне придушення
  • Поріг гістерезису

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

Градієнти зображення використовувалися в попередніх програмах для виявлення країв. Зокрема, фільтри Собеля та Шарра покладаються на градієнти зображення. Фільтр Sobel зводиться до двох ядер (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

]

Коли ви проводите ними по зображенню, кожна з них «піднімає» (підкреслює) лінії у своїй відповідній орієнтації. Ядра Scharr працюють однаково, з різними значеннями:

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. Вертикальний пошук. Ai.

Кредит зображення: Davidwkennedy

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

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

Використовуючи величину та орієнтацію, ви можете створити зображення з виділеними краями:

Виявлення меж OpenCV у Python за допомогою cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Кредит зображення: Davidwkennedy

Проте – ви бачите, скільки шуму також було вловлено через тектуру цегли! Градієнти зображення дуже чутливі до шуму. Ось чому фільтри Собеля і Шарра були використані як компонент, але не єдиний підхід у методі Канні. Гаусове згладжування також допомагає тут.

Немаксимальне придушення

Помітною проблемою фільтра Sobel є те, що краї не дуже чіткі. Це не те, що хтось узяв олівець і намалював лінію, щоб створити лінійне зображення. Краї зазвичай не такі чіткі на зображеннях, оскільки світло розсіюється поступово. Однак ми можемо знайти спільну лінію на краях і придушити решту пікселів навколо неї, утворюючи натомість чисту, тонку лінію розділення. Це відоме як немаксимальне придушення! Немаксимальні пікселі (менші за ті, з якими ми їх порівнюємо в невеликому локальному полі, такому як ядро ​​3×3) пригнічуються. Ця концепція застосовна до більшої кількості завдань, але давайте поки прив’яжемо її до цього контексту.

Поріг гістерезису

Багато некраїв можуть і, ймовірно, будуть оцінені як краї через умови освітлення, матеріали на зображенні тощо. Через різні причини виникають ці прорахунки – важко зробити автоматизовану оцінку того, чим є край, а чим ні. 't. Ви можете встановити поріг градієнтів і включити лише сильніші з них, припускаючи, що «справжні» краї інтенсивніші, ніж «фальшиві».

Порогове значення працює майже так само, як і зазвичай: якщо градієнт нижче нижнього порогу, видаліть його (обнуліть), а якщо він вище заданого верхнього порогу, збережіть його. Усе, що знаходиться між нижньою та верхньою межами, знаходиться в «сірій зоні». Якщо будь-який край між порогами з’єднаний з a остаточний край (над порогом) – вони також вважаються ребрами. Якщо вони не з’єднані, вони, ймовірно, є результатом неправильно розрахованої переваги.

Це поріг гістерезису! По суті, це допомагає очистити кінцевий результат і видалити помилкові краї, залежно від того, що ви класифікуєте як помилкові краї. Щоб знайти хороші порогові значення, ви, як правило, експериментуєте з різними нижніми та верхніми межами для порогів або використовуєте автоматичний метод, наприклад метод Оцу чи метод трикутника.

Давайте завантажимо зображення в градації сірого (Canny, так само як Sobel/Scharr вимагають, щоб зображення були градаціями сірого):

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. Вертикальний пошук. Ai.

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

Виявлення країв на зображеннях за допомогою cv2.Canny()

Алгоритм Canny можна застосувати за допомогою OpenCV Canny() метод:

cv2.Canny(input_img, lower_bound, upper_bound)

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

Знайти правильний баланс між нижньою межею та верхньою межею може бути складно. Якщо обидва низькі – у вас буде мало країв. Якщо нижня межа низька, а верхня висока – у вас буде шум. Якщо обидва високі і близько один до одного – у вас буде мало переваг. Правильне місце має рівно достатній проміжок між межами та має їх у правильному масштабі. Експериментуйте!

Вхідне зображення буде розмите за допомогою методу Canny, але часто вам буде корисно його розмити перед тим це також входить. Цей метод застосовує розмиття за Гауссом 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. Вертикальний пошук. Ai.

Значення 20 та 30 тут не довільно – я перевірив метод на різних параметрах і вибрав набір, який, здавалося, дає пристойний результат. Чи можемо ми спробувати це автоматизувати?

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

Чи можете ви знайти оптимальний набір порогових значень? Так, але це не завжди працює. Ви можете зробити власний розрахунок для певного хорошого значення, а потім налаштувати діапазон за допомогою a 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. Вертикальний пошук. Ai.

Метод трикутника спрацював тут досить добре! Це не гарантує, що він добре працюватиме в інших випадках.

Виявлення меж у реальному часі на відео за допомогою 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() для живого перегляду.

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

Коли ви запускаєте метод з a secret_video.mp4 введення – ви побачите спливаюче вікно, а коли воно буде завершено, файл у вашому робочому каталозі:

Виявлення меж OpenCV у Python за допомогою cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Висновок

У цьому посібнику ми розглянули, як працює виявлення країв Canny, а також його складові частини – гаусове згладжування, фільтри Собеля та градієнти зображення, немаксимальне придушення та порогове значення гістерезису. Нарешті, ми дослідили методи автоматичного пошуку порогового діапазону для виявлення краю Canny cv2.Canny(), і застосував цю техніку на відео, забезпечуючи виявлення країв у реальному часі та зберігаючи результати у відеофайлі.

Йти далі – практичне глибоке навчання для комп’ютерного зору

Ваша допитлива природа змушує вас йти далі? Ми рекомендуємо перевірити наш Курс: «Практичне глибоке навчання комп’ютерного бачення за допомогою Python».

Виявлення меж OpenCV у Python за допомогою cv2.Canny() PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Ще один курс комп’ютерного зору?

Ми не будемо класифікувати цифри MNIST або моди MNIST. Вони свою роль давно відслужили. Занадто багато навчальних ресурсів зосереджені на базових наборах даних і базових архітектурах, перш ніж дозволити просунутим архітектурам чорної скриньки взяти на себе тягар продуктивності.

Ми хочемо зосередитися на демістифікація, практичність, розуміння, інтуїція та реальні проекти. Хочеться навчитися як ти можеш змінити ситуацію? Ми проведемо вас у подорожі від того, як наш мозок обробляє зображення, до написання дослідницького класифікатора глибокого навчання для раку молочної залози до мереж глибокого навчання, які «галюцинують», навчаючи вас принципам і теорії через практичну роботу, озброюючи вас ноу-хау та інструменти, щоб стати експертом у застосуванні глибокого навчання для вирішення проблем комп’ютерного зору.

Що всередині?

  • Перші принципи бачення та те, як комп’ютери можна навчити «бачити»
  • Різні задачі та застосування комп'ютерного зору
  • Інструменти, які полегшать вашу роботу
  • Пошук, створення та використання наборів даних для комп’ютерного зору
  • Теорія та застосування згорткових нейронних мереж
  • Обробка зсуву домену, спільного входження та інших упереджень у наборах даних
  • Передача навчання та використання часу навчання та обчислювальних ресурсів інших для вашої вигоди
  • Створення та навчання сучасного класифікатора раку молочної залози
  • Як застосувати здорову дозу скептицизму до основних ідей і зрозуміти наслідки широко поширених методів
  • Візуалізація «концептуального простору» ConvNet за допомогою t-SNE та PCA
  • Тематичні дослідження того, як компанії використовують методи комп’ютерного зору для досягнення кращих результатів
  • Правильна оцінка моделі, візуалізація прихованого простору та ідентифікація уваги моделі
  • Виконання досліджень предметної області, обробка власних наборів даних і створення тестів моделей
  • Передові архітектури, розвиток ідей, що робить їх унікальними та як їх реалізувати
  • KerasCV – бібліотека WIP для створення найсучасніших конвеєрів і моделей
  • Як аналізувати та читати документи та реалізувати їх самостійно
  • Вибір моделей в залежності від вашого застосування
  • Створення наскрізного конвеєра машинного навчання
  • Пейзаж та інтуїція під час виявлення об’єктів за допомогою Faster R-CNN, RetinaNets, SSD та YOLO
  • Екземплярна та семантична сегментація
  • Розпізнавання об'єктів у реальному часі за допомогою YOLOv5
  • Навчання детекторам об’єктів YOLOv5
  • Робота з Transformers за допомогою KerasNLP (потужна бібліотека WIP)
  • Інтеграція Transformers із ConvNets для створення підписів до зображень
  • DeepDream
  • Оптимізація моделі Deep Learning для комп’ютерного зору

Часова мітка:

Більше від Stackabuse