- 1. Побітові операції та маскування
- 2. Виток та розмиття
- 3. Загострення - зворотне розмиття зображення
- 4. Тренування (бінаризація)
- 5. Розширення, ерозія, відкриття / закриття
- 6. Виявлення країв та градієнти зображення
- 14. Перспектива та афінна трансформація
- 8. Live Sketch Application
У попередніх навчальних посібниках ми дізналися про OpenCV і виконали деякі базові обробки зображень, а потім у наступному підручнику ми виконали деякі маніпуляції із зображеннями в OpenCV, такі як обрізання, обертання, перетворення зображень тощо. ще деякі методи обробки зображень, такі як і в кінці підручника ми побудуємо програму python-opencv, щоб робити ескіз у реальному часі з веб-камери в реальному часі. Ця програма використовуватиме багато функцій обробки зображень, які ми вивчали до цього часу або вивчатимемо в цьому посібнику, тому це буде хорошим практичним прикладом для охоплення всіх функцій.
Як було сказано в попередньому навчальному посібнику, OpenCV - це бібліотека з відкритим кодом Commuter Vision, яка має інтерфейси C ++, Python та Java та підтримує Windows, Linux, Mac OS, iOS та Android. Тож його можна легко встановити в Raspberry Pi за допомогою середовища Python та Linux. А Raspberry Pi з OpenCV та підключеною камерою можна використовувати для створення багатьох програм обробки зображень у режимі реального часу, таких як виявлення обличчя, блокування обличчя, відстеження об’єктів, виявлення номерного знака автомобіля, система домашньої безпеки тощо.
У цьому підручнику ми побачимо ще кілька маніпуляцій із зображеннями за допомогою Python OpenCV. Тут ми навчимося застосовувати таку функцію до зображення за допомогою Python OpenCV:
- Побітові операції та маскування
- Виток та розмиття
- Заточка - Змінення зображення в зворотному напрямку
- Порогове обмеження (бінаризація)
- Розширення, ерозія, відкриття / закриття
- Виявлення країв та градієнти зображення
- Перспективна та афінна трансформація
- Застосування ескізу в прямому ефірі
1. Побітові операції та маскування
Побітові операції допомагають вам у маскуванні зображень та створюють кілька простих зображень.
Виготовлення квадрата
import cv2 import numpy as np # ми використовуємо лише два виміри, оскільки це зображення у відтінках сірого, якщо ми використовували # кольорове зображення, тоді використовували прямокутник = np.zeros ((300,300,3), np.uint8) # Створення квадратного квадрата = np.zeros ((300300), np.uint8) cv2.rectangle (квадрат, (50,50), (250,250), 255, -1) cv2.imshow ("квадрат", квадрат) cv2. waitKey (0)
Виготовлення еліпса
еліпс = np.zeros ((300300), np.uint8) cv2.ellipse (еліпс, (150150), (150150), 30,080,255, -1) cv2.imshow ("еліпс", еліпс) cv2.waitKey (0)
Експерименти з побітовими операціями
#AND_показує лише там, де вони перетинаються
BitwiseAND = cv2.bitwise_and (квадрат, еліпс) cv2.imshow ("І", BitwiseAND) cv2.waitKey (0)
#OR_показує лише там, де є квадрат або еліпс
Побітове OR = cv2.bitwise_or (квадрат, еліпс) cv2.imshow ("АБО", Побітове OR) cv2.waitKey (0)
#XOR_показує лише там, де один із них існує сам по собі
BitwiseXOR = cv2.bitwise_xor (квадрат, еліпс) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_показує все, що не є частиною еліпса і операція НЕ може застосовуватися лише до однієї фігури
BitwiseNOT_elp = cv2.bitwise_not (еліпс) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Виток та розмиття
Згортки є математичною операцією, виконуваної на двох функцій, які виробляють третю функцію, яка зазвичай становить собою модифікований варіант вихідної функції.
Вихідне зображення = зображення Функція Розмір ядра
У комп'ютерному зорі ми використовуємо ядра, щоб вказати розмір, над яким ми запускаємо нашу маніпуляційну функцію над своїм зображенням.
Розмиття - це операція, коли ми усереднюємо пікселі в межах регіону (ядро)
OpenCV розмиває зображення, застосовуючи ядра, ядро розповідає, як змінити значення будь-якого даного пікселя, комбінуючи його з різною кількістю сусідніх пікселів, ядро застосовується до кожного пікселя на зображенні по одному для отримання кінцевого зображення.
Простіше кажучи, згортка зображення - це просто елементарне множення двох матриць, за яким йде сума.
Ми можемо просто зрозуміти це на наступному прикладі.
Вище є ядро 3X3.
Ми множимо на 1/25, щоб нормалізувати, тобто підсумовуючи до 1, ми збільшували інтенсивність або зменшували інтенсивність, як у випадку освітлення або затемнення зображень.
Давайте протестуємо метод розмиття opencv filter2D, заданий функцією cv2.filter2D (зображення, -1, ядро)
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#створення матриці ядра 3x3
ядро_3x3 = np.ones ((3,3), np.float32) / 9
# ми використовуємо cv2.filter2D для конвертування ядра із зображенням
розмито = cv2.filter2D (зображення, -1, ядро_3x3) cv2.imshow ('3x3_ blurring', розмито) cv2.waitKey (0)
#створення матриці ядра 7x7
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# ми використовуємо cv2.filter2D для конвертування ядра із зображенням
розмито = cv2.filter2D (зображення, -1, ядро_7x7) cv2.imshow ('7x7_ blurring', розмито) cv2.waitKey (0) cv2.destroyAllWindows ()
Існують також інші типи методів розмиття:
cv2.blur - усереднює значення за вказаним вікном.
cv2.GaussianBlur - подібний, але використовує гауссове вікно (більше уваги на точки навколо центру).
cv2.medianBlur - використовує медіану всіх елементів у вікні.
cv2.bilateralFilter - Розмиття, зберігаючи чіткість країв, зберігає краї та деталі лінії.
Внизу ми побачимо по одному, спочатку відобразимо оригінальне зображення, використовуючи код нижче:
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
У цьому методі усереднення здійснюється шляхом перетворення зображення за допомогою нормалізованого фільтра коробки, це займає місце під полем і замінює центральний елемент. Тут розмір коробки повинен бути непарним і позитивним .
# cv2.blur blur = cv2.blur (image, (3,3)) cv2.imshow ('Усереднення', розмиття) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # замість полевого фільтра спробуємо ядро Гауса Gaussian = cv2.GaussianBlur (зображення, (7,7), 0) cv2.imshow ('Гаусова розмиття, Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Він приймає медіану всіх пікселів в області ядра, а центральний елемент замінюється цією медіаною.
# cv2.medianBlur # приймає медіану всіх пікселів в області ядра та центральний елемент # замінюється цим медіанним значенням. Медіана = cv2.medianBlur (зображення, 5) cv2.imshow ('медіанний розмивання', медіана) cv2.waitKey (0)
cv2.bilateralFilter:
Двосторонній дуже ефективний при видаленні шуму, зберігаючи при цьому гострі краї
# cv2.bilateralFilter # Білатерал дуже ефективний у видаленні шуму, зберігаючи при цьому чіткі краї двостороннім = cv2.bilateralFilter (зображення, 9,75,75) cv2.imshow ('двостороннє розмиття', двостороннє) cv2.waitKey (0) cv2. знищитиAllWindows ()
Зниження шуму зображення-не місцеве означає шум
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# параметр після None - це потужність фільтру 'h' (5-10 - хороший діапазон) #next - h для кольорових компонентів, знову встановлене таке ж значення, як h
dst = cv2.fastNlMeansDenoisingColored (зображення, None, 6,6,7,21) cv2.imshow ('Швидко означає denois', dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Існує 4 варіації нелокальних засобів проти шуму
cv2.fastNlMeansDenoising () - для одинарного зображення у сірій шкалі
cv2.fastNlMeansDenoisingColored () - одноколірне зображення
cv2.fastNlmeansDenoisingMulti () - для шкали відтінків сірого
cv2.fastNlmeansDenoisingcoloredMulti () - для кольорової послідовності зображень
3. Загострення - зворотне розмиття зображення
Заточка - це протилежність розмитості, вона посилює або підкреслює краї по зображенню.
Ядро =,,
Наша матриця ядра підсумовує до одиниці, тому немає необхідності нормалізувати (тобто помножити на коефіцієнт до тієї самої яскравості, що і оригінал), якщо ядро не нормується до 1, зображення буде яскравішим або темнішим.
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
kernel_sharpening = np.array (,
]))
#applying sharpening kernel to input image
sharpened = cv2.filter2D (image, -1, kernel_sharpening) cv2.imshow ('загострене зображення', загострене) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Тренування (бінаризація)
Порогове обмеження - це акт перетворення зображення в двійкову форму. У opencv є окрема функція для порогового значення, визначена як
Cv2.threshold (зображення, значення порога, максимальне значення, тип порогу)
Існують такі типи порогових значень:
- cv2.THRESH_BINARY - найпоширеніший
- cv2. THRESH_BINARY_INV - найпоширеніші
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
ПРИМІТКА: зображення потрібно перетворити у відтінки сірого перед пороговим значенням
import cv2 import numpy as np #load image as grayscale image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)
# значення нижче 127 переходить до 0 (чорний), а вище 127 переходить до 255 (білий)
_, thresh1 = cv2.threshold (зображення, 127,255, cv2.THRESH_BINARY) cv2.imshow ('1 поріг', thresh1) cv2.waitKey (0)
#value нижче 127 переходить до 255, а значення вище 127 переходить до 0 (зворотне значення вище)
_, thresh2 = cv2.threshold (зображення, 127255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 поріг', thresh2) cv2.waitKey (0)
#value вище 127 усікається (утримується) на 127, аргумент 255 не використовується.
_, thresh3 = cv2.threshold (зображення, 127,255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc', thresh3) cv2.waitKey (0)
# значення нижче 127 переходить до 0, вище 127 не змінюється
_, thresh4 = cv2.threshold (зображення, 127255, cv2.THRESH_TOZERO) cv2.imshow ('4 поріг', thresh4) cv2.waitKey (0)
#Revesrse вище, нижче 127 не змінюється, вище 127 переходить до нуля
_, thresh5 = cv2.threshold (зображення, 127255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 поріг', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Розширення, ерозія, відкриття / закриття
Це операції у галузі математичної морфології
Розширення - додає пікселі до меж об’єкта на зображенні.
Ерозія - видаляє пікселі на межі об’єкта на зображенні.
Відкриття - ерозія з подальшим розширенням.
Закриття - розширення з наступною ерозією.
Відкриття дуже корисно для знешкодження зображень, оскільки воно спочатку розріджує зображення шляхом ерозії (усуває шум), а потім розширює його.
Плутанина з розширенням та ерозією
Іноді виникає плутанина між розширенням та ерозією, як правило, на знімках з білим фоном, оскільки opencv розглядає білий фон як зображення, що розширюється або стирається, а не оригінальне зображення, тому в цьому випадку ерозія працює як розширення і навпаки, як показано на зразку зображення показано нижче.
Пам’ятайте, Розширення додає пікселі до меж об’єктів на зображенні, тоді як Ерозія видаляє пікселі на межі об’єктів на зображенні
import cv2 import numpy as np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
# Ерозія
# давайте визначимо наш розмір ядра
ядро = np.ones ((5,5), np.uint8)
# зараз ми стираємо зображення, тут ітерація не раз вимагає стирання зображення
ерозія = cv2.erode (зображення, ядро, ітерації = 1) cv2.imshow ('Ерозія', ерозія) cv2.waitKey (0)
# розширення
dilation = cv2.dilate (зображення, ядро, ітерації = 1) cv2.imshow ('розширення', dilation) cv2.waitKey (0)
#opening, Добре для усунення шуму
opening = cv2.morphologyEx (зображення, cv2.MORPH_OPEN, ядро) cv2.imshow ('відкриття', відкриття) cv2.waitKey (0)
#closing, добре для усунення шуму
closed = cv2.morphologyEx (зображення, cv2.MORPH_CLOSE, ядро) cv2.imshow ('закриття', закриття) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Виявлення країв та градієнти зображення
Виявлення країв є дуже важливою областю в комп'ютерному зорі, особливо коли йдеться про контури.
Краю можна визначити як межі зображення, насправді це краї, які визначають об'єкт на зображеннях, вони зберігають багато інформації про зображення.
Формально краї можна визначити як раптові зміни (розриви) зображення, і вони можуть кодувати стільки інформації, скільки пікселів.
Наведене зображення показує, як комп'ютерний зір ідентифікує та розпізнає зображення.
Алгоритми виявлення країв: - Існує три основних типи алгоритмів виявлення країв
- Собель - для акцентування на вертикальних або горизонтальних зображеннях.
- Лапласіан - оптимальний завдяки низькій частоті помилок, чітко визначеним краям і точному виявленню.
- Алгоритм виявлення краю Canny (розроблений Джоном Ф. Кенні в 1986 році)
1. Застосовує розмиття Гауса
2. Знаходить градієнт інтенсивності зображення
3. застосовує не максимальне придушення (тобто видаляє пікселі, що не є краями).
4. Гістерезис застосовує поріг (тобто якщо піксель знаходиться в межах верхнього та нижнього порогу, він вважається краєм)
import cv2 import numpy як np image = cv2.imread ('input.jpg', 0) висота, ширина = image.shape
#sobel
# вилучення країв собеля
sobel_x = cv2.Sobel (зображення, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (зображення, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('оригінал', зображення) cv2.waitKey (0) cv2.imshow ('sobelx', sobel_x) cv2.waitKey (0)
# Собелі
cv2.imshow ('sobely', sobel_y) cv2.waitKey (0)
sobel_OR = cv2.bitwise_or (sobel_x, sobel_y) cv2.imshow ('sobelOR', sobel_OR) cv2.waitKey (0)
# лаплайська
laplacian = cv2.Laplacian (зображення, cv2.CV_64F) cv2.imshow ('лаплаційна', лаплаційна) cv2.waitKey (0)
# canny алгоритм виявлення краю використовує значення градієнта як порогові значення
#inny нам потрібно надати два значення: порог1 і поріг2.
# будь-який градієнт, більший за поріг 2, вважається ребром.
# будь-який градієнт, більший за поріг 1, вважається не ребром.
#values проміжний поріг 1 і 2 порога або, як край або некраевой
#on, як їх інтенсивності пов'язані, в цьому випадку будь-яке значення нижче 60 будуть розглянуті
#non країв wheareas будь-яке значення вище 120 розглядаються як краями.
canny = cv2.Canny (зображення, 60 120) cv2.imshow ('canny', canny) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Перспектива та афінна трансформація
Давайте зробимо крок назад і подивимося на афінні та неаффінні перетворення. Оригінальне зображення, представлене нижче, явно є неаффінним зображенням, оскільки краї збираються в якийсь момент зіткнутися, однак ми можемо виправити його, викрививши та взявши перспективу перетворювати.
Для цього перспективного перетворення нам потрібні чотири координати вихідного зображення, а потім чотири точки вихідного зображення, вони позначаються точками_А та точками_В. Спочатку за допомогою цих точок ми обчислюємо матрицю перетворень, M за допомогою функції getPerspectiveTransform.
А потім ця матриця передається функції warpPerspective для формування кінцевого результату.
Тепер спершу спробуємо перетворення Перспективи.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# координата 4 кутів оригінального зображення
points_A = np.float32 (,,,])
# координати 4 кутів бажаного виводу
# ми використовуємо співвідношення паперу формату А4 1: 1,41
points_B = np.float32 (,,,])
# використовуйте два набори з двох точок для обчислення матриці перспективного перетворення, M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (image, M, (420,594)) cv2.imshow ('warpprespective', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
Аффінне перетворення легше, ніж неафінне, оскільки нам потрібні лише три точки для отримання перетворення. Весь процес йде однаково, але замість перегляду перспективи ми тепер маємо афінне перетворення, а також визначаємо col і рядки у warpAffine з функції shape, замість того, щоб вводити його вручну.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('box.jpg') рядки, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
# координата 3 кутів оригінального зображення
points_A = np.float32 (,,])
# координати 3 кутів бажаного виводу
# ми використовуємо співвідношення паперу формату А4 1: 1,41
points_B = np.float32 (,,])
# використовуйте два набори з двох точок для обчислення матриці Affine
#transformation, M
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (image, M, (cols, rows)) cv2.imshow ('warpaffine', warped) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Live Sketch Application
Перш за все, привітайте себе з тим, що ви зробили успіх у цьому міні-проекті, прочитавши всі функції обробки зображень вище. Отже, у цьому міні-проекті Python OpenCV ми будемо вивчати деякі нові концепції циклів та функцій. Якщо ви знайомі з програмуванням, ви повинні мати більш широке уявлення про те, що таке функція та цикли. Однак у python основне поняття циклів та функцій залишається незмінним, але спосіб їх визначення трохи змінюється.
Отже, на початку цієї програми ми можемо побачити певну групу висловлювань під заголовком “ def sketch (image): ” це офіційне визначення функції, яка є групою висловлювань, що працюють разом для певного результату.
Отже, цей ескіз - це функція, у python функція визначається “def” і закінчується знаком “:”. Крім того, оператори, які повинні бути всередині функції, або ви можете сказати, які потрібні для належної роботи функції, автоматично вирівнюються по стороні. Отже, щоб вийти з функцій, твердження потрібно було повністю вирівняти за лівим краєм. Для подальших посилань ви можете звернутися до google про те, як функції визначені в python.
Отже, у цій функції ескізу ми ввели кілька шарів обробки зображень, які поєднуються разом, щоб отримати результат. По-перше, зображення перетворюється у відтінки сірого, щоб opencv міг легко його обробити, а потім до зображення сірого масштабу застосовується розмиття Гауса, щоб зменшити шум. Потім ребра витягуються за допомогою алгоритму виявлення ребер банку, потім на зображення, визначене ребром, застосовується двійковий зворотний, тут двійковий зворотний також може бути зроблений bitwise_NOT, але ми навмисно вибрали цей пороговий двійковий зворотний, оскільки це дає свободу встановлює його параметри, поки не отримаємо чітке зображення.
Також зауважимо, що функція бере зображення аргументів і повертає два аргументи ret та mask. Поки ret - це логічне значення, яке говорить про те, що функція запущена успішно чи ні, а маска є кінцевим результатом функції, тобто обробленим зображенням.
Тоді друга концепція полягає у роботі веб-камери у opencv, що виконується функцією cv2.VideoCapture (0) , яка зберігає зображення в шапці об’єкта, яку можна прочитати за допомогою функції cap.read () , також тут, щоб зазначити цю кришку. read () знаходиться всередині нескінченного циклу while, оскільки йому постійно доводилося захоплювати зображення, щоб надати йому відчуття живого відео, де частота кадрів відео буде частотою кадрів вашої веб-камери, яка в основному становить від 24 до 60 кадрів в секунду
cap.read () повертає ret та frame, де ret є логічним значенням, що вказує на те, що функція успішно запущена чи ні, а кадр містить зображення, зроблене веб-камерою.
Нижче наведено повний код Python OpenCV для запуску Live Sketch
import cv2 import numpy as np #sketch generating function def sketch (image): #convert image to grayscale img_gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) # очищення зображення за допомогою розмиття за Гаусом img_gray_blur = cv2.GaussianBlur (img__grass 5,5), 0) # витягнути краї canny_edges = cv2.Canny (img_gray_blur, 10,70) # зробити інвертний бінарізацію зображення ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) маска повернення # ініціалізувати веб-камеру, cap - це об’єкт, що надається при захопленні відео # він містить логічну форму, яка вказує, чи був він успішним (ret) #it також містить зображення, зібрані з веб-камери (frame) cap = cv2.VideoCapture (0) while True: ret, frame = cap.read () cv2.imshow ('livesketcher', sketch (frame)) if cv2.waitKey (1) == 13: # 13 - перерва Enterkey #release camera and close window, не забудьте звільнити веб-камеру за допомогою cap.release () cap.release () cv2.destroyAllWindows ()
Отже, це кінець Частини 2 Маніпуляцій із зображеннями в Python-OpenCV. Щоб отримати заниження рівня комп'ютерного зору та OpenCV, перегляньте попередні статті (Початок роботи з Python OpenCV та Маніпуляції зображеннями в Python OpenCV (Частина 1), і ви зможете зробити щось круте за допомогою Computer Vision.