- 1. Побитови операции и маскиране
- 2. Сгъване и замъгляване
- 3. Заточване - Обратното изображение се размазва
- 4. Трениране (бинаризация)
- 5. Разширение, ерозия, отваряне / затваряне
- 6. Откриване на ръбове и градиенти на изображението
- 14. Перспектива и афинна трансформация
- 8. Приложение за скица на живо
В предишните уроци научихме за 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 като np # използваме само две измерения, защото това е изображение в сива скала, ако използвахме # цветно изображение, тогава използвахме правоъгълник = np.zeros ((300,300,3), np.uint8) # Осъществяване на квадрат квадрат = np.zeros ((300,300), np.uint8) cv2.rectangle (квадрат, (50,50), (250,250), 255, -1) cv2.imshow ("квадрат", квадрат) cv2. waitKey (0)
Правене на елипса
елипса = np.zeros ((300,300), np.uint8) cv2.ellipse (елипса, (150,150), (150,150), 30,0,180,255, -1) cv2.imshow ("елипса", елипса) cv2.waitKey (0)
Експериментиране с битови операции
#AND_показва само там, където двете се пресичат
BitwiseAND = cv2.bitwise_and (квадрат, елипса) cv2.imshow ("И", BitwiseAND) cv2.waitKey (0)
# ИЛИ_показва само там, където е квадрат или елипса
BitwiseOR = cv2.bitwise_or (квадрат, елипса) cv2.imshow ("ИЛИ", BitwiseOR) 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)
#creating 3x3 ядро матрица
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# използваме cv2.filter2D, за да превърнем ядрото с изображение
замъглено = cv2.filter2D (изображение, -1, ядро_3x3) cv2.imshow ('3x3_ blurring', размазано) cv2.waitKey (0)
#creating 7x7 kernel matrix
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# използваме cv2.filter2D, за да превърнем ядрото с изображение
замъглено = cv2.filter2D (изображение, -1, kernel_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 ('Averaging', blur) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # вместо кутия филтър, нека опитаме Gaussian ядро Gaussian = cv2.GaussianBlur (изображение, (7,7), 0) cv2.imshow ('Gaussian blurring', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Отнема медиана на всички пиксели под зоната на ядрото и централният елемент се заменя с тази средна стойност.
# cv2.medianBlur # взема медиана на всички пиксели под зоната на ядрото и централният елемент # се заменя с тази средна стойност. медиана = cv2.medianBlur (изображение, 5) cv2.imshow ("средната замъгляване", медиана) cv2.waitKey (0)
cv2.bilateralFilter:
Двустранният е много ефективен при премахване на шума, като същевременно поддържа краищата остри
# cv2.bilateralFilter #Bilateral е много ефективен за премахване на шума, като същевременно запазва остри ръбове bilateral = cv2.bilateralFilter (изображение, 9,75,75) cv2.imshow ('двустранно размазване', двустранно) cv2.waitKey (0) cv2. Унищожи всичкиWindows ()
Image De-noising-non Local означава Denoising
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
#parameter след None е силата на филтъра 'h' (5-10 е добър диапазон) #next е h за цветни компоненти, задайте отново същата стойност като h
dst = cv2.fastNlMeansDenoisingColored (изображение, Няма, 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 изостряне на ядрото за входно изображение
заострено = cv2.filter2D (изображение, -1, заточване на ядрото) 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)
#value под 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 (изображение, 127,255, 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)
#values под 127 отива до 0, над 127 са непроменени
_, thresh4 = cv2.threshold (изображение, 127,255, cv2.THRESH_TOZERO) cv2.imshow ('4 праг', thresh4) cv2.waitKey (0)
#Revesrse на по-горе, под 127 е непроменено, над 127 отива на нула
_, thresh5 = cv2.threshold (изображение, 127,255, 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)
#now ние ерозираме изображението, тук итерацията не е случаят, в който искате да ерозирате изображението
ерозия = cv2.erode (изображение, ядро, итерации = 1) cv2.imshow ('Ерозия', ерозия) cv2.waitKey (0)
# дилатация
dilation = cv2.dilate (изображение, ядро, итерации = 1) cv2.imshow ('разширение', разширение) cv2.waitKey (0)
#opening, Добър за премахване на шума
opening = cv2.morphologyEx (изображение, cv2.MORPH_OPEN, ядро) cv2.imshow ('отваряне', отваряне) cv2.waitKey (0)
#closing, Добър за премахване на шума
затваряне = cv2.morphologyEx (изображение, cv2.MORPH_CLOSE, ядро) cv2.imshow ('затваряне', затваряне) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Откриване на ръбове и градиенти на изображението
Откриването на ръбове е много важна област в компютърното зрение, особено когато се работи с контури.
Ръбовете могат да бъдат определени като граници на изображението, всъщност те са ръбове, които дефинират обект в изображенията, те запазват много информация за изображението.
Формално Edges могат да бъдат определени като внезапни промени (прекъсвания) в изображението и те могат да кодират толкова информация, колкото пикселите.
Горното изображение показва как компютърното зрение идентифицира и разпознава изображението.
Алгоритми за откриване на ръбове: - Има три основни типа алгоритми за откриване на ръбове
- Sobel - за акцент върху вертикални или хоризонтални изображения.
- Лаплациан - оптимален поради ниска честота на грешки, добре дефинирани ръбове и точно откриване.
- Алгоритъм за откриване на Canny Edge (деволпиран от John F. Canny през 1986 г.)
1. Прилага размиване по Гаус
2. Намира градиент на интензивността на изображението
3. прилага не максимално потискане (т.е. премахва пиксели, които не са ръбове).
4. Хистерезис прилага праг (т.е. ако пикселът е в горния и долния праг, той се счита за ръб)
импортиране на cv2 импортиране на 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)
#laplaian
laplacian = cv2.Laplacian (изображение, cv2.CV_64F) cv2.imshow ('лаплациански', laplacian) cv2.waitKey (0)
#canny алгоритъм за откриване на ръба използва градиентни стойности като прагове
# в canny трябва да предоставим две стойности: праг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. Перспектива и афинна трансформация
Нека да направим крачка назад и да разгледаме афинни и неафинни трансформации, показаното по-долу оригинално изображение е явно неафинно изображение, тъй като краищата ще се срещнат в даден момент, обаче, можем да го изправим, като се изкривим и вземем перспективата трансформирам.
За тази перспективна трансформация са ни необходими четирите координати на оригиналното изображение и след това четирите точки на изходното изображение, те се означават с points_A и points_B. Първо с помощта на тези точки изчисляваме матрица за преобразуване, 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 ъгъла на оригиналното изображение
точки_А = np.float32 (,,,])
# координати на 4 ъгъла на желания изход
# използваме съотношение на хартия А4 1: 1,41
точки_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 ()
Аффинната трансформация е по-лесна от неафинната трансформация, тъй като се нуждаем само от три точки, за да получим трансформацията. Целият процес върви по същия начин, но вместо перспективна трансформация вече имаме affine transform и също така дефинираме cols и редове в 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 ъгъла на оригиналното изображение
точки_А = np.float32 (,,])
# координати на 3 ъгъла на желания изход
# използваме съотношение на хартия А4 1: 1,41
точки_B = np.float32 (,,])
# използвайте двата набора от две точки, за да изчислите матрицата Affine
#transformation, M
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (изображение, M, (cols, редове)) cv2.imshow ('warpaffine', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Приложение за скица на живо
На първо място, поздравете се, че сте се справили с този мини проект, след като сте прочели всички функции за манипулиране на изображения по-горе. Така че в този мини проект на Python OpenCV ще научим някои нови концепции за цикли и функции. Ако сте запознати с програмирането, трябва да имате по-широка представа за това каква е функцията и контурите. Въпреки това, в python основната концепция за цикли и функции остава същата, но методът за тяхното дефиниране се променя малко.
Така че в началото на тази програма можем да видим заглавие на определена група изявления под „ скица (изображение): ” това е официално определение на функция група от изявления, работещи заедно за даден изход.
Така че тази скица е функция, в python функцията се дефинира от “def” и завършва с знак “:”. Също така изявленията, които трябва да бъдат във функцията или можете да кажете кои са необходими, за да може функцията да работи правилно, са автоматично подравнени отстрани от функцията. Така че, за да излязат от функциите, изявленията трябва да бъдат напълно подравнени вляво. За допълнителни препратки можете да се обърнете към google за това как са дефинирани функциите в python.
Така че в тази функция за скициране въведохме няколко слоя обработка на изображения, които се комбинират заедно, за да дадат резултат. Първо, изображението се преобразува в скала на сивото, за да може opencv да го обработи лесно и след това върху изображението на сивата скала се прилага размиване на Гаус, за да се намали шума. След това ръбовете се извличат с помощта на алгоритъма за откриване на ръбовете на кутията, след което върху изображението, дефинирано от ръба, се прилага двоична инверсия, тук бинарната инверсия също може да бъде направена чрез bitwise_NOT, но умишлено сме избрали този двоичен обратен праг, тъй като дава свобода да задава параметрите му, докато получим ясен образ.
Също така да се отбележи, че функцията взема изображението на аргументите и връща двата аргумента ret и mask. Докато ret е булева стойност, която казва, че функцията се изпълнява успешно или не, а маската е крайният изход на функцията, т.е. обработеното изображение.
Тогава втората концепция е за работа с уеб камера в opencv, което се извършва от функцията cv2.VideoCapture (0) , която съхранява изображението в капачка на обект, която капачката може да се прочете с функцията cap.read () , също тук, за да се отбележи тази капачка. read () е вътре в безкрайния цикъл while, тъй като непрекъснато е трябвало да заснема изображенията, за да му даде усещане за видео на живо, където честотата на кадрите на видеото ще бъде честотата на кадрите на вашата уеб камера, която е най-вече между 24 и 60 fps.
cap.read () връща ret и frame, където ret е Boolean, което показва, че функцията е изпълнена успешно или не и рамката съдържа изображението, направено от уеб камера.
По-долу е даден пълният код на 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) # почистване на изображението с помощта на Gaussian blur img_gray_blur = cv2.GaussianBlur (img_grag 5,5), 0) # извличане на ръбове canny_edges = cv2.Canny (img_gray_blur, 10,70) #do invert binarize the image ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) return mask #initialize webcam, капачка е обектът, предоставена от видео заснемане #it съдържа Булева показва, ако тя е била успешна (задържане) #it също съдържа изображенията, събрани от уеб камерата (кадър) cap = cv2.VideoCapture (0), докато True: ret, frame = cap.read () cv2.imshow ('livesketcher', скица (кадър)) ако cv2.waitKey (1) == 13: # 13 е enterkey break #release camera и close window, не забравяйте да освободите уеб камерата с помощта на cap.release () cap.release () cv2.destroyAllWindows ()
Така че това е краят на Част 2 от Манипулации с изображения в Python-OpenCV. За да получите добро подценяване на компютърното зрение и OpenCV, преминете през предишни статии (Първи стъпки с Python OpenCV и Манипулации на изображения в Python OpenCV (Част 1) и ще можете да направите нещо страхотно с Computer Vision.