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

Порогове значення OpenCV у Python за допомогою cv2.threshold()

Вступ

Порогове значення – це проста та ефективна техніка для виконання базової сегментації зображення та його двійкової перетворення (перетворення на двійкове зображення), де пікселі або 0 or 1 (Або 255 якщо ви використовуєте цілі числа для їх представлення).

Як правило, ви можете використовувати порогове значення для виконання простої сегментації фону та переднього плану в зображенні, і це зводиться до варіантів простої техніки для кожного пікселя:

if pixel_value > threshold:
    pixel_value = MAX
else:
    pixel_value = 0

Цей важливий процес відомий як Двійкове порогове визначення. Тепер – є різні способи, якими ви можете налаштувати цю загальну ідею, включаючи інвертування операцій (перемикання > підписати з < знак), встановлення в pixel_value до threshold замість максимального значення/0 (відомого як усікання), зберігаючи pixel_value сам, якщо він вище threshold або якщо він нижче threshold.

Усе це було зручно реалізовано в OpenCV як:

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

… відповідно. Це відносно «наївні» методи, оскільки вони досить прості, не враховують контекст у зображеннях, мають відомості про загальні форми тощо. Для цих властивостей нам доведеться використовувати набагато дорожчі та потужніші обчислювальні засоби техніки.

Тепер навіть «наївними» методами – деякі Для пошуку хороших порогів можна застосувати евристичні методи, зокрема метод Оцу та метод трикутника:

  • cv2.THRESH_OTSU
  • cv2.THRESH_TRIANGLE

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

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

Просте визначення порогів за допомогою OpenCV

Порогове значення в API Python OpenCV здійснюється за допомогою cv2.threshold() метод – який приймає зображення (масив NumPy, представлений цілими числами), порогове значення, максимальне значення та метод порогового значення (як threshold та maximum_value використовуються):

img = cv2.imread('objects.jpg')

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)


blurred = cv2.GaussianBlur(img, (7, 7), 0)

ret, img_masked = cv2.threshold(blurred, 220, 255, cv2.THRESH_BINARY)

Код повернення – це лише застосоване порогове значення:

print(f"Threshold: {ret}") 

Ось, оскільки поріг є 220 і ми використали THRESH_BINARY метод – кожне піксельне значення вище 220 буде збільшено до 255, тоді як значення кожного пікселя нижче 220 буде знижено до 0, створюючи чорно-біле зображення з «маскою», що закриває об’єкти переднього плану.

Чому 220? Знаючи, як виглядає зображення, ви можете зробити деякі приблизні припущення про те, який поріг ви можете вибрати. На практиці ви рідко захочете встановити порогове значення вручну, тому ми зараз розглянемо автоматичний вибір порогового значення.

Давайте накреслимо результат! Вікна OpenCV можуть бути дещо вибагливими, тому ми створимо вихідне зображення, розмите зображення та результати за допомогою Matplotlib:

fig, ax = plt.subplots(1, 3, figsize=(12, 8))
ax[0].imshow(img)
ax[1].imshow(blurred)
ax[2].imshow(img_masked)

Порогові методи

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

methods = [cv2.THRESH_BINARY, cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC, cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV]
names = ['Binary Threshold', 'Inverse Binary Threshold', 'Truncated Threshold', 'To-Zero Threshold', 'Inverse To-Zero Threshold']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    blurred = cv2.GaussianBlur(img, (7, 7), 0)
    ret, img_masked = cv2.threshold(blurred, 220, 255, method)

    fig, ax = plt.subplots(1, 3, figsize=(12, 4))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(img)
    ax[1].imshow(blurred)
    ax[2].imshow(img_masked)
    plt.tight_layout()

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

THRESH_BINARY та THRESH_BINARY_INV є оберненими один до одного, а між ними двійковий образ 0 та 255, призначаючи їх фону та передньому плану відповідно, і навпаки.

THRESH_TRUNC бінаризує зображення між threshold та 255.

THRESH_TOZERO та THRESH_TOZERO_INV бінаризувати між 0 і поточне значення пікселя (src(x, y)). Давайте подивимося на отримані зображення:

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

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

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

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

Ми можемо певною мірою боротися з цим, знайшовши кращий глобальний поріг.

Автоматичне/оптимізоване порогове значення з OpenCV

OpenCV використовує два ефективні глобальні порогові методи пошуку – метод Оцу та метод трикутника.

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

Порогове визначення OpenCV у Python за допомогою cv2.threshold() PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.
Зображення кредиту: https://scipy-lectures.org/

Ви можете зробити деякі зображення більш бімодальними за допомогою розмиття за Гаусом, але не всі.

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

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

Обидва вони передбачають зображення в градаціях сірого, тому нам потрібно буде перетворити вхідне зображення на сіре за допомогою cv2.cvtColor():

img = cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

ret, mask1 = cv2.threshold(blurred, 0, 255, cv2.THRESH_OTSU)
ret, mask2 = cv2.threshold(blurred, 0, 255, cv2.THRESH_TRIANGLE)

masked = cv2.bitwise_and(img, img, mask=mask1)

Давайте проглянемо зображення обома методами та візуалізуємо результати:

methods = [cv2.THRESH_OTSU, cv2.THRESH_TRIANGLE]
names = ['Otsu Method', 'Triangle Method']

def thresh(img_path, method, index):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (7, 7), 0)

    ret, img_masked = cv2.threshold(blurred, 0, 255, method)
    print(f"Threshold: {ret}")

    fig, ax = plt.subplots(1, 3, figsize=(12, 5))
    fig.suptitle(names[index], fontsize=18)
    ax[0].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    ax[1].imshow(cv2.cvtColor(gray, cv2.COLOR_BGR2RGB))
    ax[2].imshow(cv2.cvtColor(img_masked, cv2.COLOR_BGR2RGB))

for index, method in enumerate(methods):
    thresh('coins.jpeg', method, index)

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

Тут метод трикутника перевершує метод Оцу, оскільки зображення не є бімодальним:

import numpy as np

img = cv2.imread('coins.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)

histogram_gray, bin_edges_gray = np.histogram(gray, bins=256, range=(0, 255))
histogram_blurred, bin_edges_blurred = np.histogram(blurred, bins=256, range=(0, 255))

fig, ax = plt.subplots(1, 2, figsize=(12, 4))

ax[0].plot(bin_edges_gray[0:-1], histogram_gray)
ax[1].plot(bin_edges_blurred[0:-1], histogram_blurred)

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

Однак зрозуміло, як метод трикутника міг працювати із зображенням і давати більш задовільний результат.

Обмеження порогового значення OpenCV

Порогове значення за допомогою OpenCV є простим, легким і ефективним. Проте він досить обмежений. Як тільки ви вводите кольорові елементи, неоднорідний фон і мінливі умови освітлення – глобальне порогове значення як концепція стає занадто жорстким.

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

Висновок

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

Для простого встановлення порогів на льоту можна використовувати OpenCV. Для точної сегментації на виробничому рівні ви захочете використовувати нейронні мережі.

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

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

Порогове визначення OpenCV у Python за допомогою cv2.threshold() 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