Обработка на изображения OpenCV

Obrabotka Na Izobrazenia Opencv



В тази статия ще проучим методите за обработка на изображения. Ще разгледаме някои фундаментални, но критични теми в компютърното зрение и машинното обучение. Тези фундаментални техники за обработка на изображения могат да разрешават сложни проблеми, като набори от данни. В резултат на това има шест основни стъпки в обработката на изображения, които са изброени по-долу:
  1. Превод на изображения
  2. Завъртане на изображението
  3. Аритметика на изображението
  4. Обръщане на изображението
  5. Изрязване на изображението
  6. Преоразмеряване на изображението

Сега ще обясним подробно всички гореспоменати теми за обработка на изображения.

1. Превод на изображения

Преводът на изображения е метод за обработка на изображения, който ни помага да преместим изображението по осите x и y. Можем да местим изображението нагоре, надолу, надясно, наляво или произволна комбинация.







Можем да дефинираме транслационната матрица със символа M и можем да я представим в математическа форма, както е показано по-долу:





Чрез тази програма можем да разберем концепцията на изображението за превод.





Python код: Ще запазим името на следната програма като translate.py .

# импортирайте необходимите пакети

импортиране numpy като напр.

импортиране argparse

импортиране imutil

импортиране cv2

# прилагаме анализатора на аргументи

ap_obj = argparse. ArgumentParser ( )

ap_obj. добавяне на аргумент ( '-k' , '--образ' , изисква се = Вярно ,

помогне = 'местоположение на файла с изображение' )

аргументи = чийто ( ap_obj. parse_args ( ) )

# заредете изображението и го покажете на екрана

образ = cv2. imread ( аргументи [ 'образ' ] )

cv2. imshow ( 'Оригинално_изображение' , образ )

# Преводът на изображението е матрица NumPy, която е дадена по-долу:

# [[1, 0, shiftX], [0, 1, shiftY]]

# Ще използваме горната матрица NumPy, за да изместим изображенията по протежение на

# посоки на оста x и оста y. За целта трябва просто да предадем стойностите на пикселите.

# В тази програма ще преместим изображението с 30 пиксела надясно

# и 70 пиксела към дъното.

превод_мат = напр. float32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

изображение_превод = cv2. warpAffine ( образ , превод_мат ,

( образ. форма [ 1 ] , образ. форма [ 0 ] ) )

cv2. imshow ( „Превод на изображение надолу и надясно“ , изображение_превод )

# сега ще използваме горната матрица NumPy, за да изместим изображенията по протежение на

# посоки на оста x (вляво) и у (нагоре).

# Тук ще преместим изображенията 50 пиксела наляво

# и 90 пиксела нагоре.

превод_мат = напр. float32 ( [ [ 1 , 0 , - петдесет ] , [ 0 , 1 , - 90 ] ] )

изображение_превод = cv2. warpAffine ( образ , превод_мат ,

( образ. форма [ 1 ] , образ. форма [ 0 ] ) )

cv2. imshow ( „Превод на изображение нагоре и наляво“ , изображение_превод )

cv2. чакайКлюч ( 0 )

Редове от 1 до 5: Импортираме всички необходими пакети за тази програма, като OpenCV, argparser и NumPy. Моля, имайте предвид, че има друга библиотека, която е imutils. Това не е пакет на OpenCV. Това е просто библиотека, която лесно ще покаже същата обработка на изображения.



Библиотечните imutils няма да бъдат включени автоматично, когато инсталираме OpenCV. Така че, за да инсталираме imutils, трябва да използваме следния метод:

pip инсталирайте imutils

Редове от 8 до 15: Създадохме нашия agrparser и заредихме нашето изображение.

Редове 24 до 25: Този програмен раздел е мястото, където се извършва преводът. Матрицата за превод ни казва с колко пиксела изображението ще бъде преместено нагоре или надолу или наляво или надясно. Тъй като OpenCV изисква стойността на матрицата да е в масив с плаваща запетая, транслационната матрица приема стойности в масиви с плаваща запетая.

Първият ред на матрицата за превод изглежда така:

Този ред от матрицата е за оста x. Стойността на t х ще реши дали изображението ще бъде изместено наляво или надясно. Ако подадем отрицателна стойност, това означава, че изображението ще бъде изместено вляво, а ако стойността е положителна, това означава, че изображението ще бъде изместено в дясната страна.

Сега ще дефинираме втория ред на матрицата, както следва:

Този ред от матрицата е за оста y. Стойността на t Y ще реши дали изображението ще бъде изместено нагоре или надолу. Ако подадем отрицателна стойност, това означава, че изображението ще бъде изместено нагоре, а ако стойността е положителна, това означава, че изображението ще бъде изместено надолу.

В предишната програма на ред 24 ние дефинираме t х = 30 и t Y = 70. Така че преместваме изображението 30 пиксела надясно и 70 пиксела надолу.

Но основният процес на превод на изображение се извършва на ред 25, където дефинираме матрицата за превод cv2.warpAffine . В тази функция предаваме три параметъра: първият параметър е изображението, вторият параметър е транслационната матрица, а третият параметър е размерът на изображението.

Ред 27: Ред 27 ще покаже резултата в изхода.

Сега ще приложим друга транслационна матрица за лявата и горната страна. За целта трябва да дефинираме стойностите като отрицателни.

Ред 33 до 34: В предишната програма на ред 33 ние дефинираме t х = -50 и t Y = -90. Така че преместваме изображението 50 пиксела към лявата страна и 90 пиксела нагоре. Но основният процес на превод на изображение се извършва на ред 34, където дефинираме матрицата за превод cv2.warpAffine .

Ред 36 : Ред 36 ще покаже резултата, както е показано в изхода.

За да изпълним предишния код, трябва да дадем пътя на изображението, както е дадено по-долу.

Изход: python translate.py – изображение squirrel.jpg

Сега ще приложим същата програма за превод на изображения, използвайки imutil библиотека. Тази библиотека е много лесна за използване за обработка на изображения. В тази библиотека не е нужно да мислим за cv2.warpAffine защото тази библиотека ще се погрижи за това. Така че нека внедрим тази програма за превод на изображения с помощта на библиотеката imutils.

Python код: Ще запазим името на следната програма като translate_imutils.py .

# импортирайте необходимите пакети

импортиране numpy като напр.

импортиране argparse

импортиране imutil

импортиране cv2

# Тази функция изпълнява превода на изображение и

# връща преведеното изображение на извикващата функция.

деф превеждам ( образ , х , Y ) :

преводна_матрица = напр. float32 ( [ [ 1 , 0 , х ] , [ 0 , 1 , Y ] ] )

изображение_превод = cv2. warpAffine ( образ , преводна_матрица ,

( образ. форма [ 1 ] , образ. форма [ 0 ] ) )

връщане изображение_превод

# конструиране на анализатора на аргументи и анализиране на аргументите

ап = argparse. ArgumentParser ( )

ап. добавяне на аргумент ( '-и' , '--образ' , изисква се = Вярно , помогне = 'Път към образа' )

аргументи = чийто ( ап. parse_args ( ) )

# заредете изображението и го покажете на екрана

образ = cv2. imread ( аргументи [ 'образ' ] )

cv2. imshow ( 'Оригинално_изображение' , образ )

изображение_превод = imutil. превеждам ( образ , 10 , 70 )

cv2. imshow ( „Превод на изображение надясно и надолу“ ,

изображение_превод )

cv2. чакайКлюч ( 0 )

Редове от 9 до 13: Този раздел на програмата е мястото, където се извършва преводът. Матрицата за превод ни информира с колко пиксела изображението ще бъде преместено нагоре или надолу или наляво или надясно.

Тези редове вече бяха обяснени, но сега ще изградим функция, наречена translate () и ще изпратим три различни параметъра в нея. Самото изображение служи като първи параметър. Стойностите x и y на транслационната матрица съответстват на втория и третия параметър.

Забележка : Няма нужда да дефинирате тази функция за превод вътре в програмата, защото тя вече е включена в пакета на библиотеката imutils. Използвал съм го в рамките на програмата за по-лесно обяснение. Можем да извикаме тази функция директно с imutils, както е показано в ред 24.

Ред 24: Предишната програма ще покаже, че в ред 24 ние дефинираме tx = 10 и ty = 70. Така че преместваме изображението с 10 пиксела надясно и 70 пиксела надолу.

В тази програма не се интересуваме от никакви функции cv2.warpAffine, защото те вече са в пакета на библиотеката imutils.

За да изпълним предишния код, трябва да дадем пътя на изображението, както е дадено по-долу:

Изход:

python imutils. py --изображение катерица. jpg

2. Завъртане на изображението

Разгледахме как да преведем (т.е. да преместим) изображение нагоре, надолу, наляво и надясно в предишния урок (или произволна комбинация). След това ще обсъдим ротацията, тъй като е свързана с обработката на изображения.

Една картина се завърта на ъгъл, тита, в процес, известен като ротация. Ъгълът, под който завъртаме изображението, ще бъде представен от тита. Освен това впоследствие ще осигуря удобната функция за завъртане, за да направя завъртането на изображения по-лесно.

Подобно на транслацията и може би не е изненадващо завъртането под ъгъл, тита се определя чрез изграждане на матрица M в следния формат:

Тази матрица може да завърти вектор тита градуса (обратно на часовниковата стрелка) около началото на дадената (x, y)-декартова равнина. Обикновено в този сценарий началото ще бъде центърът на картината, но в действителност можем да обозначим всяка произволна (x, y) точка като наш център на въртене.

След това завъртената картина R се създава от оригиналното изображение I, като се използва директно матрично умножение: R = IM

OpenCV, от друга страна, допълнително предлага капацитет за (1) мащабиране (т.е. преоразмеряване) на изображение и (2) предлагане на произволен център на въртене, който да извършва въртенето наоколо.

Нашата модифицирана ротационна матрица M е показана по-долу:

Нека започнем с отваряне и генериране на нов файл, наречен rotate.py :

# импортиране на необходимите пакети

импортиране numpy като напр.

импортиране argparse

импортиране imutil

импортиране cv2

# създаване на обект argumentparser и аргумент за анализиране

apobj = argparse. ArgumentParser ( )

apobj. добавяне на аргумент ( '-k' , '--образ' , изисква се = Вярно , помогне = 'път на изображение' )

аргументи = чийто ( apobj. parse_args ( ) )

образ = cv2. imread ( аргументи [ 'образ' ] )

cv2. imshow ( 'Оригинално_изображение' , образ )

# Изчислете центъра на изображението, като използвате размерите на изображението.

( височина , ширина ) = образ. форма [ : 2 ]

( centerX , център Y ) = ( ширина / 2 , височина / 2 )

# Сега, използвайки cv2, ще завъртим изображението с 55 градуса до

# определяне на ротационната матрица с помощта на getRotationMatrix2D()

ротационна матрица = cv2. getRotationMatrix2D ( ( centerX , център Y ) , 55 , 1.0 )

завъртяно изображение = cv2. warpAffine ( образ , ротационна матрица , ( ширина , височина ) )

cv2. imshow ( „Изображението се завъртя на 55 градуса“ , завъртяно изображение )

cv2. чакайКлюч ( 0 )

# Изображението сега ще бъде завъртяно на -85 градуса.

ротационна матрица = cv2. getRotationMatrix2D ( ( centerX , център Y ) , - 85 , 1.0 )

завъртяно изображение = cv2. warpAffine ( образ , ротационна матрица , ( ширина , височина ) )

cv2. imshow ( „Изображението се завъртя с -85 градуса“ , завъртяно изображение )

cv2. чакайКлюч ( 0 )

Редове от 1 до 5: Импортираме всички необходими пакети за тази програма, като OpenCV, argparser и NumPy. Моля, имайте предвид, че има друга библиотека, която е imutils. Това не е пакет на OpenCV. Това е просто библиотека, която ще се използва за лесно показване на същата обработка на изображения.

Библиотечните imutils няма да бъдат включени автоматично, когато инсталираме OpenCV. OpenCV инсталира imutils. Трябва да използваме следния метод:

pip инсталирайте imutils

Редове от 8 до 14: Създадохме нашия agrparser и заредихме нашето изображение. В този argparser използваме само един аргумент за изображение, който ще ни каже пътя на изображението, което ще използваме в тази програма, за да демонстрираме ротацията.

Когато завъртаме изображение, трябва да дефинираме опорната точка на завъртането. През повечето време ще искате да завъртите изображение около центъра му, но OpenCV ви позволява да изберете произволна точка вместо това. Нека просто завъртим изображението около центъра му.

Редове от 17 до 18 вземете съответно ширината и височината на изображението и след това разделете всяко измерение на две, за да установите центъра на изображението.

Конструираме матрица за завъртане на изображение по същия начин, по който дефинирахме матрица за превод на изображение. Просто ще се обадим на cv2.getRotationMatrix2D функция на ред 22, а не ръчно създаване на матрицата с помощта на NumPy (което може да е малко тромаво).

The cv2.getRotationMatrix2D функцията изисква три параметъра. Първият вход е желаният ъгъл на завъртане (в този случай центърът на изображението). След това тита се използва за определяне на колко градуса (обратно на часовниковата стрелка) ще завъртим изображението. Тук ще завъртим изображението на 45 градуса. Последната опция е свързана с размера на изображението.

Независимо от факта, че все още не сме обсъждали мащабиране на изображение, можете да предоставите число с плаваща запетая тук с 1,0, което означава, че изображението трябва да се използва в оригиналните си пропорции. Ако обаче въведете стойност 2.0, изображението ще се удвои по размер. Число 0,5 намалява размера на изображението по този начин.

Ред 22 до 23: След получаване на нашата ротационна матрица M от cv2.getRotationMatrix2D функция, завъртаме нашето изображение с помощта на cv2.warpAffine техника на ред 23. Първият вход на функцията е изображението, което искаме да завъртим. След това се определят ширината и височината на нашето изходно изображение, заедно с нашата ротационна матрица M. На ред 23 изображението се завърта на 55 градуса.

Можете да забележите, че нашето изображение е завъртяно.

Редове 28 до 30 представляват втората ротация. Редове 22–23 от кода са идентични, с изключение на това, че този път се въртим с -85 градуса за разлика от 55.

Ние просто завъртяхме изображение около центъра му до този момент. Ами ако искаме да завъртим изображението около произволна точка?

Нека започнем с отваряне и генериране на нов файл, наречен rotate.py:

# импортиране на необходимите пакети

импортиране numpy като напр.

импортиране argparse

импортиране imutil

импортиране cv2

# създаване на обект argumentparser и аргумент за анализиране

ap_obj = argparse. ArgumentParser ( )

ap_obj. добавяне на аргумент ( '-k' , '--образ' , изисква се = Вярно , помогне = 'път на изображение' )

аргумент = чийто ( ap_obj. parse_args ( ) )

# заредете изображението и го покажете на екрана

образ = cv2. imread ( аргумент [ 'образ' ] )

cv2. imshow ( 'Оригинално_изображение' , образ )

# Изчислете центъра на изображението, като използвате размерите на изображението.

( височина , ширина ) = образ. форма [ : 2 ]

( centerX , център Y ) = ( ширина / 2 , височина / 2 )

# Сега, използвайки cv2, ще завъртим изображението с 55 градуса до

# определяне на ротационната матрица с помощта на getRotationMatrix2D()

ротационна матрица = cv2. getRotationMatrix2D ( ( centerX , център Y ) , 55 , 1.0 )

завъртяно изображение = cv2. warpAffine ( образ , ротационна матрица , ( ширина , височина ) )

cv2. imshow ( „Изображението се завъртя на 55 градуса“ , завъртяно изображение )

cv2. чакайКлюч ( 0 )

# Изображението сега ще бъде завъртяно на -85 градуса.

ротационна матрица = cv2. getRotationMatrix2D ( ( centerX , център Y ) , - 85 , 1.0 )

завъртяно изображение = cv2. warpAffine ( образ , ротационна матрица , ( ширина , височина ) )

cv2. imshow ( „Изображението се завъртя с -85 градуса“ , завъртяно изображение )

cv2. чакайКлюч ( 0 )

# завъртане на изображението от произволна точка, а не от центъра

ротационна матрица = cv2. getRotationMatrix2D ( ( centerX - 40 , centerY - 40 ) , 55 , 1.0 )

завъртяно изображение = cv2. warpAffine ( образ , ротационна матрица , ( ширина , височина ) )

cv2. imshow ( „Въртене на изображение от произволни точки“ , завъртяно изображение )

cv2. чакайКлюч ( 0 )

Ред 34 до 35: Сега този код трябва да изглежда доста често срещан за завъртане на обект. За да завъртите изображението около точка 40 пиксела наляво и 40 пиксела над центъра, ние инструктираме cv2.getRotationMatrix2D функция, за да обърне внимание на първия си параметър.

Изображението, получено, когато приложим това завъртане, е показано по-долу:

Можем ясно да видим, че центърът на въртенето сега е (x, y)-координатата, която е 40 пиксела вляво и 40 пиксела над изчисления център на картината.

3. Аритметика на изображенията

Всъщност аритметиката на изображението е просто събиране на матрици с няколко допълнителни ограничения върху типовете данни, които ще разгледаме по-късно.

Нека отделим малко време, за да разгледаме някои хубави основи на линейната алгебра.

Помислете за комбиниране на следващите две матрици:

Какъв резултат би довело събирането на матрицата? Простият отговор е сумата от записите в матрицата, елемент по елемент:

Достатъчно просто, нали?

В момента всички разбираме основните операции събиране и изваждане. Трябва обаче да имаме предвид ограниченията, наложени от нашето цветово пространство и тип данни, докато работим с изображения.

Пикселите в RGB изображения, например, попадат между [0, 255]. Какво се случва, ако се опитаме да добавим 10 към пиксел с интензитет 250, докато го гледаме?

Ще стигнем до стойност 260, ако приложим стандартни аритметични принципи. 260 не е валидна стойност, тъй като RGB изображенията се представят като 8-битови цели числа без знак.

И така, какво трябва да се случи? Трябва ли да извършим проверка, за да се уверим, че нито един пиксел не е извън обхвата [0, 255], като изрязваме всеки пиксел, за да има стойност между 0 и 255?

Или „обгръщаме“ и извършваме модулна операция? В съответствие с правилата за модул, добавянето на 10 към 255 ще доведе до стойност 9.

Как трябва да се обработват добавянията и изважданията към изображения извън диапазона от [0, 255]?

Истината е, че няма правилна или грешна техника; всичко зависи от това как работите с вашите пиксели и какво се надявате да постигнете.

Но не забравяйте, че има разлики между добавянето в OpenCV и добавянето в NumPy. Модулната аритметика и „обвиването“ ще се извършват от NumPy. Обратно, OpenCV ще изпълни изрязване и ще се увери, че стойностите на пикселите никога не напускат диапазона [0, 255].

Нека започнем със създаването на нов файл, наречен arithmetic.py и го отварям:

# python arithmetic.py --image squirrel.jpg

# импортиране на необходимите пакети

импортиране numpy като напр.

импортиране argparse

импортиране imutil

импортиране cv2

# създаване на обект argumentparser и аргумент за анализиране

apObj = argparse. ArgumentParser ( )

apObj. добавяне на аргумент ( '-k' , '--образ' , изисква се = Вярно , помогне = 'път на изображение' )

аргументи = чийто ( apObj. parse_args ( ) )

образ = cv2. imread ( аргументи [ 'образ' ] )

cv2. imshow ( 'Оригинално_изображение' , образ )

'''

Стойностите на нашите пиксели ще бъдат в диапазона [0, 255]

тъй като изображенията са масиви NumPy, които се съхраняват като 8-битови цели числа без знак.

Когато използвате функции като cv2.add и cv2.subtract, стойностите ще бъдат изрязани

към този диапазон, дори ако се добавят или изваждат извън

[0, 255] диапазон. Ето една илюстрация:

'''


печат ( 'максимум 255: {}' . формат ( ул ( cv2. добавете ( напр. uint8 ( [ 201 ] ) ,

напр. uint8 ( [ 100 ] ) ) ) ) )

печат ( 'минимум от 0: {}' . формат ( ул ( cv2. изваждам ( напр. uint8 ( [ 60 ] ) ,

напр. uint8 ( [ 100 ] ) ) ) ) )

'''

Когато правите аритметични операции с тези масиви с помощта на NumPy,

стойността ще се обвие, вместо да бъде подрязана към

[0, 255] диапазон. Когато използвате изображения, важно е да запазите това

се има предвид.

'''


печат ( 'обгърне: {}' . формат ( ул ( напр. uint8 ( [ 201 ] ) + напр. uint8 ( [ 100 ] ) ) ) )

печат ( 'обгърне: {}' . формат ( ул ( напр. uint8 ( [ 60 ] ) - напр. uint8 ( [ 100 ] ) ) ) )

'''

Нека умножим яркостта на всеки пиксел в нашето изображение по 101.

За да направим това, ние генерираме масив NumPy със същия размер като нашата матрица,

запълнен с единици и го умножете по 101, за да получите попълнен масив

със 101s. Накрая сливаме двете изображения.

Ще забележите, че изображението вече е „по-ярко“.

'''


Матрица = напр. нечий ( образ. форма , dtype = 'uint8' ) * 101

изображение_добавено = cv2. добавете ( образ , Матрица )

cv2. imshow ( „Резултат с добавено изображение“ , изображение_добавено )

#По подобен начин можем да направим изображението си по-тъмно, като вземем

# 60 разстояние от всички пиксели.

Матрица = напр. нечий ( образ. форма , dtype = 'uint8' ) * 60

изображение_извадено = cv2. изваждам ( образ , Матрица )

cv2. imshow ( „Резултат от извадено изображение“ , изображение_извадено )

cv2. чакайКлюч ( 0 )

Редове от 1 до 16 ще се използва за извършване на нашия нормален процес, който включва импортиране на нашите пакети, конфигуриране на нашия анализатор на аргументи и зареждане на нашето изображение.

Спомняте ли си как по-рано обсъждах разликата между добавянето на OpenCV и NumPy? Сега, след като го разгледахме обстойно, нека разгледаме конкретен случай, за да сме сигурни, че го разбираме.

Два 8-битови целочислени NumPy масива без знак са дефинирани на ред 26 . Стойност 201 е единственият елемент в първия масив. Въпреки че само един член е във втория масив, той има стойност 100. След това стойностите се добавят с помощта на функцията cv2.add на OpenCV.

Какъв очаквате да бъде резултатът?

В съответствие с конвенционалните аритметични принципи, отговорът трябва да бъде 301. Но не забравяйте, че имаме работа с 8-битови цели числа без знак, които могат да бъдат само в диапазона [0, 255]. Тъй като използваме метода cv2.add, OpenCV обработва изрязването и гарантира, че добавянето връща само максимален резултат от 255.

Първият ред от списъка по-долу показва резултата от изпълнението на този код:

аритметика. py

максимум от 255 : [ [ 255 ] ]

Сумата наистина произведе числото 255.

След това, ред 26 използва cv2.subtract за извършване на изваждане. Още веднъж дефинираме два 8-битови масива NumPy с цели числа без знак с един елемент във всеки. Стойността на първия масив е 60, докато стойността на втория масив е 100.

Нашата аритметика диктува, че изваждането трябва да доведе до стойност от -40, но OpenCV обработва изрязването отново вместо нас. Откриваме, че стойността е намалена до 0. Нашият резултат по-долу демонстрира това:

аритметика. py

минимум от 0 : [ [ 0 ] ]

Използвайки cv2, извадете 100 от 60 извадете, произвеждайки стойност 0.

Но какво се случва, ако използваме NumPy вместо OpenCV, за да извършим изчисленията?

Редове 38 и 39 адресирайте този проблем.

Първо се дефинират два 8-битови целочислени NumPy масива без знак с един елемент всеки. Стойността на първия масив е 201, докато стойността на втория масив е 100. Нашата добавка ще бъде изрязана и ще бъде върната стойност 255, ако използваме функцията cv2.add.

NumPy, от друга страна, „обвива“ и прави аритметика по модул, а не изрязване. NumPy се завърта до нула, след като се достигне стойност от 255 и след това подновява броенето до достигане на 100 стъпки. Това се потвърждава от първия ред на изхода, който е показан по-долу:

аритметика. py
обгърне: [ Четири пет ]

След това се дефинират още два масива NumPy, единият със стойност 50, а другият със 100. Това изваждане ще бъде подрязано от метода cv2.subtract, за да върне резултат 0. Но ние сме наясно, че вместо изрязване, NumPy изпълнява аритметика по модул. Вместо това модулните процедури се преобръщат и започват да броят назад от 255, след като по време на изваждането се достигне 0. Можем да видим това от следния изход:

аритметика. py

обгърне: [ 207 ]

Още веднъж, нашият терминален изход демонстрира разликата между изрязване и обвиване около:

От решаващо значение е да имате предвид желания резултат, когато извършвате целочислена аритметика. Искате ли стойности извън диапазона [0, 255] да бъдат изрязани? След това използвайте вградените техники за аритметика на изображения на OpenCV.

Искате ли стойностите да се обгръщат, ако са извън обхвата на [0, 255] и модулни аритметични операции? След това масивите NumPy просто се добавят и изваждат както обикновено.

Ред 48 дефинира едномерен масив NumPy със същите размери като нашето изображение. Още веднъж гарантираме, че нашият тип данни е 8-битови цели числа без знак. Ние просто умножаваме нашата матрица от едноцифрени стойности по 101, за да я запълним със стойности от 101 вместо 1. Накрая използваме функцията cv2.add, за да добавим нашата матрица от 100s към оригиналното изображение. Това увеличава интензитета на всеки пиксел със 101, като същевременно гарантира, че всички стойности, които се опитват да надвишат 255, се отрязват в диапазона [0, 255].

Наблюдавайте как изображението е забележимо по-ярко и изглежда по-„измито“ от оригинала. Това е така, защото насочваме пикселите към по-ярки цветове, като повишаваме интензитета им със 101.

За да извадим 60 от интензитета на всеки пиксел на изображението, първо създаваме втори масив NumPy на ред 54, който е запълнен с 60-те.

Резултатите от това изваждане са изобразени на следното изображение:

Предметите около нас изглеждат значително по-тъмни, отколкото преди. Това е така, защото изваждайки 60 от всеки пиксел, преместваме пикселите в цветовото пространство RGB в по-тъмните области.

4. Обръщане на изображението

Подобно на въртенето, обръщането на изображение по неговата ос x или y е друга опция, предлагана от OpenCV. Дори операциите за обръщане да не се използват толкова често, познаването им е невероятно полезно поради различни причини, които може да не видите веднага.

Ние разработваме класификатор за машинно обучение за малка стартираща компания, която се стреми да идентифицира лица в изображения. За да може нашата система да „научи“ какво е лице, ще ни трябва някакъв набор от данни с примерни лица. За съжаление, компанията ни е предоставила само малък набор от данни от 40 лица и не можем да съберем повече информация.

Тогава какво правим?

Тъй като лицето си остава лице, независимо дали е огледално или не, можем да обърнем хоризонтално всяко изображение на лице и да използваме огледалните версии като допълнителни данни за обучение.

Този пример може да изглежда глупав и изкуствен, но не е. Обръщането е целенасочена стратегия, използвана от силни алгоритми за дълбоко обучение, за да произвеждат повече данни по време на фазата на обучение.

От предишното става ясно, че методите за обработка на изображения, които научавате в този модул, служат като основа за по-големи системи за компютърно зрение.

Цели:

Използвайки cv2.flip ще научите как да обръщате изображение както хоризонтално, така и вертикално в тази сесия.

Обръщането е следващата манипулация на изображението, която ще изучаваме. Осите x и y на изображението могат да бъдат обърнати или дори и двете. Преди да се потопим в кодирането, най-добре е първо да разгледаме резултатите от обръщане на изображението. Вижте изображение, което е хоризонтално обърнато в следното изображение:


Обърнете внимание как нашето оригинално изображение е отляво и как изображението е хоризонтално огледално отдясно.

Нека започнем със създаването на нов файл, наречен обръщане.py .

Видяхте пример за обръщане на изображение, така че нека разгледаме кода:

# python flipping.py --image quirrel.jpg

# импортиране на необходимите пакети

импортиране argparse

импортиране cv2

# създаване на обект на анализатор на аргументи и анализиране на аргумента

apObj = argparse. ArgumentParser ( )

apObj. добавяне на аргумент ( '-и' , '--образ' , изисква се = Вярно , помогне = 'път на изображение' )

аргумент = чийто ( apObj. parse_args ( ) )

образ = cv2. imread ( аргумент [ 'образ' ] )

cv2. imshow ( 'Оригинал' , образ )

# хоризонтално обръщане на изображението

imageflipped = cv2. флип ( образ , 1 )

cv2. imshow ( „Хоризонтално обърнато изображение“ , imageflipped )

# вертикално обръщане на изображението

imageflipped = cv2. флип ( образ , 0 )

cv2. imshow ( „Вертикално обърнато изображение“ , imageflipped )

# Обръщане на изображението по двете оси

imageflipped = cv2. флип ( образ , - 1 )

cv2. imshow ( „Обърнато хоризонтално и вертикално“ , imageflipped )

cv2. чакайКлюч ( 0 )

Стъпките, които предприемаме, за да импортираме нашите пакети, да анализираме нашите входове и да заредим нашето изображение от диска, се обработват в l от 1 до 12 .

Чрез извикване на функцията cv2.flip на Ред 15 , лесно е да обърнете изображение хоризонтално. Изображението, което търсим да обърнем, и специфичен код или флаг, който указва как да обърнем изображението, са двата аргумента, необходими за метода cv2.flip.

Стойност на кода за обръщане 1 означава, че ще завъртим изображението около оста y, за да го обърнем хоризонтално ( Ред 15 ). Ако посочим код за обръщане 0, искаме да завъртим изображението около оста x ( Ред 19 ). Отрицателен флип код ( Ред 23 ) завърта изображението по двете оси.

Един от най-лесните примери в тази тема е обръщането на изображение, което е основно.

След това ще обсъдим изрязването на изображения и използването на резени от масив NumPy за извличане на конкретни части от изображението.

5. Изрязване на изображението

Изрязването, както подсказва името, е процесът на избиране и премахване на региона на интерес (или просто ROI), който е областта на изображението, която ни интересува.

Лицето трябва да бъде изрязано от изображение за приложение за разпознаване на лица. Освен това, ако създавахме скрипт на Python за намиране на кучета в изображения, може да искаме да изрежем кучето от изображението, когато го намерим.

Цели: Нашата основна цел е да се запознаем и лесно да използваме нарязването на масив NumPy за изрязване на области от изображение.

Изрязване : Когато изрязваме изображение, нашата цел е да елиминираме външните елементи, които не ни интересуват. Процесът на избор на нашата ROI често се нарича избор на нашия регион на интерес.

Създайте нов файл, наречен crop.py , отворете го и добавете следния код:

# python crop.py

# импортиране на необходимите пакети

импортиране cv2

# изображението се зарежда и показва на екрана

образ = cv2. imread ( 'катерица.jpg' )

печат ( образ. форма )

cv2. imshow ( 'Оригинал' , образ )

# Срезове от масив NumPy се използват за бързо изрязване на изображение

# ще изрежем лицето на катеричката от изображението

катерица = образ [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'лице на катерица' , катерица )

cv2. чакайКлюч ( 0 )

# И сега, тук ще изрежем цялото тяло

# на катерицата

squirrelbody = образ [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Тяло на катерица' , squirrelbody )

cv2. чакайКлюч ( 0 )

Ще покажем изрязване в Python и OpenCV, като използваме изображение, което зареждаме от диска Редове 5 и 6 .

Оригинално изображение, което ще изрежем

Използвайки само основни техники за изрязване, ние се стремим да отделим лицето и тялото на катерицата от околната среда.

Ще използваме предварителните си познания за изображението и ще предоставим ръчно срезовете на масива NumPy, където съществуват тялото и лицето. При нормални условия обикновено използваме машинно обучение и алгоритми за компютърно зрение, за да разпознаем лицето и тялото в изображението. Но нека засега да запазим нещата ясни и да избягваме използването на модели за откриване.

Можем да идентифицираме лицето в изображението само с един ред код. Ред 13 , За да извлечете правоъгълна част от изображението, започвайки от (35, 35), ние предоставяме срезове от масив NumPy (90, 100). Може да изглежда объркващо, че захранваме изрязването с индексите в реда на първо височина и втори на ширина, но имайте предвид, че OpenCV съхранява изображения като масиви NumPy. В резултат на това трябва да предоставим стойностите за оста y преди оста x.

NumPy изисква следните четири индекса, за да извърши нашето изрязване:

Начало y: Y-координатата в началото. За този пример започваме от y=35.

Край y: Координатата y в края. Нашата реколта ще спре, когато y = 90.

Начало x: Координата x на началото на среза. Реколтата започва при x=35.

Край x: Крайната координата на оста x на среза. При x=100 нашият срез е завършен.

По същия начин изрязваме регионите (23, 35) и (143, 148) от оригиналното изображение, за да извлечем цялото тяло от изображението на Ред 19 .

Можете да забележите, че изображението е изрязано, за да покаже само тялото и лицето.

6. Преоразмеряване на изображението

Процесът на увеличаване или намаляване на ширината и височината на изображението е известен като мащабиране или просто преоразмеряване. Съотношението на страните, което е съотношението на ширината на изображението към неговата височина, трябва да се има предвид при преоразмеряване на изображение. Пренебрегването на съотношението може да доведе до изображения, които са били мащабирани, които изглеждат компресирани и изкривени:

Първоначалното ни изображение е отляво. Вдясно ще видите две изображения, които са мащабирани, без да се поддържа съотношението на страните, изкривявайки пропорцията на ширината на изображението към неговата височина. Когато преоразмерявате вашите изображения, обикновено трябва да имате предвид съотношението на страните.

Техниката на интерполация, използвана от нашия алгоритъм за преоразмеряване, трябва също да вземе предвид целта на функцията за интерполация да използва тези квартали на пиксели за увеличаване или намаляване на размера на изображението.

Като цяло намаляването на размера на изображението е много по-ефективно. Това е така, защото премахването на пиксели от изображение е всичко, което функцията за интерполация трябва да направи. От друга страна, методът на интерполация ще трябва да „запълни празнините“ между пикселите, които не са съществували преди, ако размерът на изображението трябва да бъде увеличен.

Имаме нашето оригинално изображение вляво. Изображението е намалено до половината от първоначалния си размер в центъра, но освен това, няма загуба на „качеството“ на изображението. Въпреки това размерът на изображението е значително увеличен вдясно. Сега изглежда „раздуто“ и „пикселизирано“.

Както казах по-рано, обикновено ще искате да намалите размера на изображението, вместо да го увеличите. Чрез намаляване на размера на изображението анализираме по-малко пиксели и трябва да се справяме с по-малко „шум“, което прави алгоритмите за обработка на изображения по-бързи и по-прецизни.

Транслацията и ротацията са двете трансформации на изображението, разгледани досега. Сега ще разгледаме как да промените размера на изображение.

Не е изненадващо, че ще преоразмеряваме изображенията си с помощта на метода cv2.resize. Както посочих по-рано, трябва да вземем предвид съотношението на изображението, когато използваме този метод. Но преди да навлезем твърде дълбоко в спецификата, позволете ми да ви дам една илюстрация:

# python resize.py --image squirrel.jpg

# импортиране на необходимите пакети

импортиране argparse

импортиране cv2

# създаване на обект на анализатор на аргументи и анализиране на аргумента

apObj = argparse. ArgumentParser ( )

apObj. добавяне на аргумент ( '-k' , '--образ' , изисква се = Вярно , помогне = 'път на изображение' )

аргументи = чийто ( apObj. parse_args ( ) )

# заредете изображението и го покажете на екрана

образ = cv2. imread ( аргументи [ 'образ' ] )

cv2. imshow ( 'Оригинал' , образ )

# За да предотвратите изкривяването на изображението, съотношението на страните

# трябва да се вземе предвид или да се деформира; следователно, ние разбираме какво

# съотношението на новото изображение към текущото изображение.

# Нека направим ширината на нашето ново изображение 160 пиксела.

аспект = 160,0 / образ. форма [ 1 ]

измерение = ( 160 , вътр ( образ. форма [ 0 ] * аспект ) )

# този ред ще покаже действителните операции за преоразмеряване

преоразмерено изображение = cv2. преоразмеряване ( образ , измерение , интерполация = cv2. INTER_AREA )

cv2. imshow ( „Преоразмерена ширина на изображението“ , преоразмерено изображение )

# Ами ако искаме да променим височината на изображението? - използвайки

# същия принцип, можем да изчислим съотношението въз основа

# на височина, а не на ширина. Да направим мащаба

Височина на # изображение 70 пиксела.

аспект = 70,0 / образ. форма [ 0 ]

измерение = ( вътр ( образ. форма [ 1 ] * аспект ) , 70 )

# извършете преоразмеряването

преоразмерено изображение = cv2. преоразмеряване ( образ , измерение , интерполация = cv2. INTER_AREA )

cv2. imshow ( „Преоразмерена височина на изображението“ , преоразмерено изображение )

cv2. чакайКлюч ( 0 )

Редове 1-14 , След като импортираме нашите пакети и конфигурираме нашия анализатор на аргументи, ще заредим и покажем нашето изображение.

Редове 20 и 21: В тези редове започва съответното кодиране . Съотношението на страните на изображението трябва да се вземе предвид при преоразмеряването му. Пропорцията между ширината и височината на изображението е известна като съотношение на страните.

Височина ширина е съотношението на страните.

Ако не вземем предвид съотношението на страните, резултатите от нашето преоразмеряване ще бъдат изкривени.

На Ред 20 , изчислението на преоразмереното съотношение е направено. Предоставяме ширината на нашето ново изображение като 160 пиксела в този ред код. Ние просто определяме нашето съотношение (aspectratio) като новата ширина (160 пиксела), разделена на старата ширина, до която имаме достъп с помощта на изображение, за да изчислим съотношението на новата височина към старата височина. форма [1].

Новите измерения на изображението на Ред 21 може да се изчисли сега, когато знаем нашето съотношение. Още веднъж новото изображение ще има ширина от 160 пиксела. След умножаване на старата височина по нашето съотношение и преобразуване на резултата в цяло число, се изчислява височината. Можем да запазим оригиналното съотношение на изображението, като извършим тази операция.

Ред 24 е мястото, където изображението наистина се преоразмерява. Изображението, което искаме да преоразмерим, е първият аргумент, а вторият е размерите, които сме изчислили за новото изображение. Нашият метод на интерполация, който е алгоритъмът за преоразмеряване на действителното изображение, е последният параметър.

Накрая, на Ред 25 , показваме нашето мащабирано изображение.

Ние предефинираме нашето съотношение (aspectratio) на Ред 31 . Височината на нашето ново изображение ще бъде 70 пиксела. Разделяме 70 на първоначалната височина, за да получим съотношението на новата височина към първоначалната височина.

След това установяваме размерите на новото изображение. Новото изображение ще е с височина от 70 пиксела, което вече е известно. Можем отново да запазим оригиналното съотношение на изображението, като умножим старата ширина по съотношението, за да получим новата ширина.

След това изображението действително се преоразмерява Ред 35 , и се показва на Ред 36.

Тук можем да видим, че сме намалили ширината и височината на нашето оригинално изображение, като запазихме съотношението на страните. Нашето изображение ще изглежда изкривено, ако съотношението не се поддържа.

Заключение

В този блог проучихме основните различни концепции за обработка на изображения. Видяхме превод на изображения с помощта на пакета OpenCV. Видяхме методите за преместване на изображението нагоре, надолу, надясно и наляво. Тези методи са много полезни, когато създаваме набор от данни от подобни изображения, които да дадем като набор от данни за обучение, така че машината ще вижда различни изображения, дори ако са еднакви. Тази статия също така ви научи как да завъртите изображение около всяка точка в декартово пространство с помощта на ротационна матрица. След това открихте как OpenCV завърта изображения с помощта на тази матрица и видяхте няколко илюстрации на въртящи се изображения.

Двете фундаментални (но значими) аритметични операции на изображения събиране и изваждане бяха разгледани в този раздел. Както можете да видите, добавянето и изваждането на фундаментални матрици е всичко, което включват аритметични операции с изображения.

Освен това използвахме OpenCV и NumPy, за да проучим особеностите на аритметиката на изображенията. Тези ограничения трябва да се имат предвид, в противен случай рискувате да получите неочаквани резултати, когато изпълнявате аритметични операции върху вашите изображения.

Важно е да запомните, че въпреки че NumPy извършва модулна операция и „обгръща“, OpenCV добавяне и изваждане изрязва стойностите извън диапазона [0, 255], за да се поберат в диапазона. Когато разработвате свои собствени приложения за компютърно зрение, запомнянето на това ще ви помогне да избегнете откриването на трудни грешки.

Обръщането на изображение несъмнено е една от по-простите идеи, които ще разгледаме в този курс. Обръщането често се използва в машинното обучение за генериране на повече проби от данни за обучение, което води до по-мощни и надеждни класификатори на изображения.

Научихме също как да използваме OpenCV за преоразмеряване на изображение. От решаващо значение е да вземете предвид както метода на интерполация, който използвате, така и съотношението на оригиналното ви изображение, когато го преоразмерявате, така че резултатът да не изглежда изкривен.

И накрая, изключително важно е да запомните, че ако качеството на изображението е проблем, винаги е най-добре да преминете от по-голямо към по-малко изображение. В повечето случаи уголемяването на изображение създава артефакти и влошава качеството му.