Képfeldolgozás OpenCV

Kepfeldolgozas Opencv



Ebben a cikkben a képfeldolgozási módszereket fogjuk tanulmányozni. Megvizsgálunk néhány alapvető, de kritikus témát a számítógépes látás és a gépi tanulás területén. Ezek az alapvető képfeldolgozási technikák összetett problémákat, például adatkészleteket oldhatnak meg. Ennek eredményeként a képfeldolgozásnak hat alapvető lépése van, amelyeket az alábbiakban sorolunk fel:
  1. Kép fordítása
  2. Képforgatás
  3. Kép Aritmetika
  4. Képfordítás
  5. Kép kivágása
  6. Kép átméretezése

Most részletesen elmagyarázzuk az összes fent említett képfeldolgozási témát.

1. Képfordítás

A képfordítás egy képfeldolgozási módszer, amely segít a kép elmozdításában az x és y tengelyek mentén. Mozgathatjuk a képet fel, le, jobbra, balra, vagy bármilyen kombinációban.







A fordítási mátrixot az M szimbólummal definiálhatjuk, és matematikai formában is ábrázolhatjuk, az alábbiak szerint:





A fordítási kép fogalmát ezen a programon keresztül érthetjük meg.





Python kód: A következő program nevét megtartjuk translate.py .

# szükséges csomagok importálása

import zsibbadt mint például.

import argparse

import imutil

import cv2

# megvalósítjuk az argumentumelemzőt

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--kép' , kívánt = Igaz ,

Segítség = 'a képfájl helye' )

args = akinek ( ap_obj. parse_args ( ) )

# töltse be a képet és jelenítse meg a képernyőn

kép = cv2. olvasatlan ( args [ 'kép' ] )

cv2. imshow ( 'Eredeti_kép' , kép )

# A kép fordítása egy NumPy mátrix, amelyet alább adunk meg:

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

# A fenti NumPy mátrixot fogjuk használni a képek eltolásához

# x-tengely és y-tengely irányai. Ehhez egyszerűen át kell adnunk a pixelértékeket.

# Ebben a programban a képet 30 képponttal jobbra mozgatjuk

# és 70 pixel az alja felé.

translation_mat = például. úszó32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

image_translation = cv2. warpAffine ( kép , translation_mat ,

( kép. alak [ 1 ] , kép. alak [ 0 ] ) )

cv2. imshow ( 'Képfordítás lefelé és jobbra' , image_translation )

# most a fenti NumPy mátrixot fogjuk használni a képek eltolásához

# x-tengely (balra) és y-tengely (felfelé) iránya.

# Itt a képeket 50 képponttal balra mozgatjuk

# és 90 pixel felfelé.

translation_mat = például. úszó32 ( [ [ 1 , 0 , - ötven ] , [ 0 , 1 , - 90 ] ] )

image_translation = cv2. warpAffine ( kép , translation_mat ,

( kép. alak [ 1 ] , kép. alak [ 0 ] ) )

cv2. imshow ( 'Képfordítás felfelé és balra' , image_translation )

cv2. várj Key ( 0 )

1–5. sor: A programhoz szükséges összes csomagot importáljuk, például az OpenCV-t, az argparser-t és a NumPy-t. Kérjük, vegye figyelembe, hogy van egy másik könyvtár, amely az imutils. Ez nem az OpenCV csomagja. Ez csak egy könyvtár, amely könnyedén megmutatja ugyanazt a képfeldolgozást.



A könyvtári imutilok nem lesznek automatikusan beépítve az OpenCV telepítésekor. Tehát az imutilok telepítéséhez a következő módszert kell használnunk:

pip install imutils

8–15. sor: Elkészítettük az agrparserünket és betöltöttük a képünket.

24–25. sor: Ebben a programrészben történik a fordítás. A fordítási mátrix megmondja, hogy a kép hány pixellel kerül felfelé vagy lefelé, illetve balra vagy jobbra. Mivel az OpenCV megköveteli, hogy a mátrixérték lebegőpontos tömbben legyen, a fordítási mátrix lebegőpontos tömbökben vesz fel értékeket.

A fordítási mátrix első sora így néz ki:

A mátrixnak ez a sora az x tengelyre vonatkozik. A t értéke x eldönti, hogy a kép balra vagy jobbra tolódik-e el. Ha negatív értéket adunk át, az azt jelenti, hogy a kép balra, ha pedig pozitív, akkor azt jelenti, hogy a kép jobbra tolódik el.

Most a következőképpen határozzuk meg a mátrix második sorát:

A mátrixnak ez a sora az y tengelyre vonatkozik. A t értéke Y eldönti, hogy a kép felfelé vagy lefelé tolódik-e el. Ha negatív értéket adunk át, az azt jelenti, hogy a kép felfelé tolódik el, ha pedig pozitív, akkor azt jelenti, hogy a kép lefelé tolódik el.

Az előző programban a 24. sorban definiáljuk a t x = 30 és a t Y = 70. Tehát a képet 30 képponttal a jobb oldal felé, 70 képponttal lefelé mozgatjuk.

De a fő képfordítási folyamat a 25. sorban zajlik, ahol meghatározzuk a fordítási mátrixot cv2.warpAffine . Ebben a függvényben három paramétert adunk át: az első paraméter a kép, a második paraméter a fordítási mátrix, a harmadik paraméter pedig a kép mérete.

27. sor: A 27. sor megjeleníti az eredményt a kimenetben.

Most egy másik fordítási mátrixot fogunk megvalósítani a bal és a fejjel. Ehhez az értékeket negatívban kell meghatároznunk.

33-34. sor: Az előző programban a 33. sorban definiáljuk a t x = -50 és a t Y = -90. Így a képet 50 képponttal balra mozgatjuk, és 90 képponttal felfelé. De a fő képfordítási folyamat a 34. sorban zajlik, ahol meghatározzuk a fordítási mátrixot cv2.warpAffine .

36. sor : A 36. sor megjeleníti az eredményt a kimeneten látható módon.

Az előző kód futtatásához meg kell adnunk a kép elérési útját az alábbiak szerint.

Kimenet: python translate.py –image squirrel.jpg

Most ugyanazt a képfordító programot fogjuk megvalósítani a imutil könyvtár. Ez a könyvtár nagyon könnyen használható képfeldolgozáshoz. Ebben a könyvtárban nem kell arra gondolnunk cv2.warpAffine mert ez a könyvtár gondoskodni fog erről. Tehát valósítsuk meg ezt a képfordító programot az imutils könyvtár használatával.

Python kód: A következő program nevét megtartjuk translate_imutils.py .

# importálja a szükséges csomagokat

import zsibbadt mint például.

import argparse

import imutil

import cv2

# Ez a funkció valósítja meg a képfordítást és

# visszaadja a lefordított képet a hívó függvénynek.

def fordít ( kép , x , Y ) :

fordítási_mátrix = például. úszó32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

image_translation = cv2. warpAffine ( kép , fordítási_mátrix ,

( kép. alak [ 1 ] , kép. alak [ 0 ] ) )

Visszatérés image_translation

# megszerkeszti az argumentumelemzőt és elemzi az argumentumokat

ap = argparse. ArgumentParser ( )

ap. add_argument ( '-én' , '--kép' , kívánt = Igaz , Segítség = 'Út a képhez' )

args = akinek ( ap. parse_args ( ) )

# betölti a képet és megjeleníti a képernyőn

kép = cv2. olvasatlan ( args [ 'kép' ] )

cv2. imshow ( 'Eredeti_kép' , kép )

image_translation = imutil. fordít ( kép , 10 , 70 )

cv2. imshow ( 'Képfordítás jobbra és lefelé' ,

image_translation )

cv2. várj Key ( 0 )

9–13. sor: A program ezen szakaszában történik a fordítás. A fordítási mátrix arról tájékoztat bennünket, hogy a kép hány pixellel kerül felfelé vagy lefelé, illetve balra vagy jobbra.

Ezeket a sorokat már elmagyaráztuk, de most felépítjük a translate () nevű függvényt, és három különböző paramétert küldünk bele. Maga a kép szolgál az első paraméterként. A transzlációs mátrix x és y értékei megfelelnek a második és harmadik paraméternek.

jegyzet : Ezt a fordítási függvényt nem kell definiálni a programon belül, mert az már benne van az imutils könyvtárcsomagban. A programon belül az egyértelmű magyarázat kedvéért használtam. Ezt a függvényt közvetlenül az imutilokkal hívhatjuk meg, ahogy az a 24. sorban látható.

24. sor: Az előző program megmutatja, hogy a 24. sorban definiáljuk a tx = 10-et és a ty = 70-et. Tehát a képet 10 pixellel a jobb oldal felé mozgatjuk, és 70 képponttal lefelé.

Ebben a programban nem törődünk a cv2.warpAffine függvényekkel, mert azok már benne vannak az imutils könyvtárcsomagban.

Az előző kód futtatásához meg kell adnunk a kép elérési útját, az alábbiak szerint:

Kimenet:

python imutils. py --kép mókus. jpg

2. Képelforgatás

Az előző leckében (vagy bármilyen kombinációban) végignéztük, hogyan kell lefordítani (vagyis eltolni) egy képet fel, le, balra és jobbra. Ezután a forgatásról fogunk beszélni, mivel az a képfeldolgozáshoz kapcsolódik.

A képet egy szöggel, thétával elforgatják az elforgatásnak nevezett folyamat során. Azt a szöget, amellyel a képet elforgatjuk, théta jelzi. Ezenkívül a későbbiekben biztosítom a kényelmi elforgatás funkciót, hogy egyszerűbbé tegyem a képek elforgatását.

Hasonlóan a fordításhoz, és talán nem meglepő módon a szöggel történő elforgatáshoz, a thétát egy M mátrix felépítésével határozzuk meg a következő formátumban:

Ez a mátrix elforgathat egy vektort théta fokkal (az óramutató járásával ellentétes irányban) a megadott (x, y)-derékszögű origó körül. Általában ebben a forgatókönyvben az origó lenne a kép közepe, de valójában bármilyen véletlenszerű (x, y) pontot kijelölhetünk forgási középpontunknak.

Az elforgatott R kép ezután az eredeti I képből jön létre egyszerű mátrixszorzással: R = IM

Másrészt az OpenCV emellett lehetőséget kínál (1) egy kép méretezésére (vagyis átméretezésére), és (2) egy tetszőleges elforgatási középpontra a körbeforgatáshoz.

Az alábbiakban látható az M módosított forgatási mátrixunk:

Kezdjük egy új fájl megnyitásával és generálásával rotate.py :

# a szükséges csomagok importálása

import zsibbadt mint például.

import argparse

import imutil

import cv2

# az argumentumparser objektum létrehozása és az elemzési argumentum

apobj = argparse. ArgumentParser ( )

apobj. add_argument ( '-k' , '--kép' , kívánt = Igaz , Segítség = 'kép útja' )

érvek = akinek ( apobj. parse_args ( ) )

kép = cv2. olvasatlan ( érvek [ 'kép' ] )

cv2. imshow ( 'Eredeti_kép' , kép )

# Számítsa ki a kép közepét a kép méretei alapján.

( magasság , szélesség ) = kép. alak [ : 2 ]

( centerX , centerY ) = ( szélesség / 2 , magasság / 2 )

# Most a cv2 használatával 55 fokkal elforgatjuk a képet

# határozza meg a forgatási mátrixot a getRotationMatrix2D() segítségével

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , 55 , 1.0 )

elforgatottKép = cv2. warpAffine ( kép , rotationMatrix , ( szélesség , magasság ) )

cv2. imshow ( '55 fokkal elforgatta a képet' , elforgatottKép )

cv2. várj Key ( 0 )

# A kép most -85 fokkal el lesz forgatva.

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , - 85 , 1.0 )

elforgatottKép = cv2. warpAffine ( kép , rotationMatrix , ( szélesség , magasság ) )

cv2. imshow ( 'Elforgatta a képet -85 fokkal' , elforgatottKép )

cv2. várj Key ( 0 )

1–5. sor: A programhoz szükséges összes csomagot importáljuk, például az OpenCV-t, az argparser-t és a NumPy-t. Kérjük, vegye figyelembe, hogy van egy másik könyvtár, amely az imutils. Ez nem az OpenCV csomagja. Ez csak egy könyvtár, amely ugyanazon képfeldolgozás egyszerű megjelenítésére szolgál.

A könyvtári imutilok nem lesznek automatikusan beépítve az OpenCV telepítésekor. Az OpenCV telepíti az imutilokat. A következő módszert kell használnunk:

pip install imutils

8–14. sor: Elkészítettük az agrparserünket és betöltöttük a képünket. Ebben az argparserben csak egy kép argumentumot használunk, amely megmondja annak a képnek az útvonalát, amelyet ebben a programban a forgatás bemutatására fogunk használni.

A kép elforgatásakor meg kell határoznunk az elforgatás forgáspontját. Legtöbbször el kell forgatni egy képet a középpontja körül, de az OpenCV lehetővé teszi, hogy tetszőleges véletlenszerű pontot válasszon helyette. Egyszerűen forgassuk el a képet a közepe körül.

17-18. sor vegye ki a kép szélességét és magasságát, majd osszon el minden méretet kettővel a kép közepének megállapításához.

A kép elforgatására szolgáló mátrixot ugyanúgy definiáltunk, mint egy kép fordítására szolgáló mátrixot. csak hívjuk a cv2.getRotationMatrix2D funkciót a 22. sorban, ahelyett, hogy manuálisan hozná létre a mátrixot a NumPy használatával (ami kissé nehézkes lehet).

Az cv2.getRotationMatrix2D funkció három paramétert igényel. Az első bemenet a kívánt elforgatási szög (jelen esetben a kép közepe). A théta ezután annak megadására szolgál, hogy hány fokkal (az óramutató járásával ellentétes irányba) forgatjuk el a képet. Itt 45 fokkal elforgatjuk a képet. Az utolsó lehetőség a kép méretéhez kapcsolódik.

Függetlenül attól, hogy még nem beszéltünk a kép méretezéséről, itt megadhat egy lebegőpontos számot 1,0-val, amely azt jelzi, hogy a képet eredeti arányában kell használni. Ha azonban 2,0 értéket ír be, a kép megkétszereződik. A 0,5-ös szám így csökkenti a kép méretét.

22-23. sor: Miután megkaptuk az M forgatási mátrixunkat a cv2.getRotationMatrix2D függvény segítségével elforgatjuk képünket a cv2.warpAffine technika a 23. sorban. A függvény első bemenete az a kép, amelyet el akarunk forgatni. Ezután meghatározzuk a kimeneti képünk szélességét és magasságát az M elforgatási mátrixunkkal együtt. A 23. sorban a képet ezután 55 fokkal elforgatjuk.

Észreveheti, hogy a képünk el lett forgatva.

28-30. sor alkotják a második forgatást. A kód 22-23 sorai azonosak, kivéve, hogy ezúttal -85 fokkal forgatjuk el az 55-tel szemben.

Egészen idáig egyszerűen elforgattunk egy képet a közepe körül. Mi lenne, ha a képet egy véletlenszerű pont körül akarnánk elforgatni?

Kezdjük egy új fájl megnyitásával és generálásával rotate.py:

# a szükséges csomagok importálása

import zsibbadt mint például.

import argparse

import imutil

import cv2

# az argumentumparser objektum létrehozása és az elemzési argumentum

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--kép' , kívánt = Igaz , Segítség = 'kép útja' )

érv = akinek ( ap_obj. parse_args ( ) )

# betölti a képet és megjeleníti a képernyőn

kép = cv2. olvasatlan ( érv [ 'kép' ] )

cv2. imshow ( 'Eredeti_kép' , kép )

# Számítsa ki a kép közepét a kép méretei alapján.

( magasság , szélesség ) = kép. alak [ : 2 ]

( centerX , centerY ) = ( szélesség / 2 , magasság / 2 )

# Most a cv2 használatával 55 fokkal elforgatjuk a képet

# határozza meg a forgatási mátrixot a getRotationMatrix2D() segítségével

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , 55 , 1.0 )

elforgatottKép = cv2. warpAffine ( kép , rotationMatrix , ( szélesség , magasság ) )

cv2. imshow ( '55 fokkal elforgatta a képet' , elforgatottKép )

cv2. várj Key ( 0 )

# A kép most -85 fokkal el lesz forgatva.

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX , centerY ) , - 85 , 1.0 )

elforgatottKép = cv2. warpAffine ( kép , rotationMatrix , ( szélesség , magasság ) )

cv2. imshow ( 'Elforgatta a képet -85 fokkal' , elforgatottKép )

cv2. várj Key ( 0 )

# kép elforgatása valamilyen tetszőleges pontból, nem a középpontból

rotationMatrix = cv2. getRotationMatrix2D ( ( centerX - 40 , centerY - 40 ) , 55 , 1.0 )

elforgatottKép = cv2. warpAffine ( kép , rotationMatrix , ( szélesség , magasság ) )

cv2. imshow ( 'Kép elforgatása tetszőleges pontokból' , elforgatottKép )

cv2. várj Key ( 0 )

34-35. sor: Nos, ennek a kódnak elég gyakorinak kell tűnnie egy objektum elforgatásakor. A kép 40 képponttal balra és 40 képponttal a középpontja feletti pont körüli elforgatásához utasítjuk a cv2.getRotationMatrix2D funkciót, hogy figyeljen az első paraméterére.

Az alábbi kép látható, amikor ezt az elforgatást alkalmazzuk:

Jól láthatjuk, hogy az elforgatás középpontja most az (x, y) koordináta, amely 40 pixel balra és 40 pixel felett van a kép számított középpontjától.

3. Képaritmetika

Valójában a képaritmetika csak mátrixösszeadás, néhány további adattípus-korlátozással, amelyekkel később foglalkozunk.

Szánjunk egy percet a lineáris algebra néhány igen alapos áttekintésére.

Fontolja meg a következő két mátrix kombinálását:

Milyen eredményt adna a mátrixösszeadás? Az egyszerű válasz a mátrix bejegyzések összege elemenként:

Elég egyszerű, igaz?

Jelenleg mindannyian értjük az összeadás és kivonás alapvető műveleteit. A képekkel végzett munka során azonban szem előtt kell tartanunk a színterünk és az adattípusunk által támasztott korlátozásokat.

Az RGB képek képpontjai például [0, 255] közé esnek. Mi történik, ha 10-et próbálunk hozzáadni egy 250-es intenzitású pixelhez, miközben nézzük?

260-as értékhez jutnánk, ha standard aritmetikai elveket alkalmaznánk. A 260 nem érvényes érték, mivel az RGB képek 8 bites előjel nélküli egész számokként jelennek meg.

Tehát minek kellene történnie? Futtassunk egy ellenőrzést, hogy megbizonyosodjunk arról, hogy egyetlen pixel sem esik túl a [0, 255] tartományon, és minden képpontot levágunk úgy, hogy az értéke 0 és 255 között legyen?

Vagy „körbetekerjük” és végrehajtunk egy modulus műveletet? A modulusszabályoknak megfelelően, ha 10-et adunk 255-höz, az csak 9-et eredményez.

Hogyan kell kezelni a [0, 255] tartományon túli képek összeadását és kivonását?

Az igazság az, hogy nincs jó vagy rossz technika; minden attól függ, hogyan dolgozik a képpontjaival, és mit szeretne elérni.

De ne feledje, hogy vannak különbségek az OpenCV és a NumPy összeadás között. A modulus aritmetikát és a „körbetekerést” a NumPy végzi. Ezzel szemben az OpenCV kivágást hajt végre, és gondoskodik arról, hogy a pixelértékek soha ne hagyják el a [0, 255] tartományt.

Kezdjük egy új fájl létrehozásával aritmetika.py és kinyitod:

# python arithmetic.py --image squirrel.jpg

# a szükséges csomagok importálása

import zsibbadt mint például.

import argparse

import imutil

import cv2

# az argumentumparser objektum létrehozása és az elemzési argumentum

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--kép' , kívánt = Igaz , Segítség = 'kép útja' )

érvek = akinek ( apObj. parse_args ( ) )

kép = cv2. olvasatlan ( érvek [ 'kép' ] )

cv2. imshow ( 'Eredeti_kép' , kép )

'''

A pixeleink értéke a [0, 255] tartományba esik

mivel a képek NumPy tömbök, amelyek előjel nélküli 8 bites egész számokként vannak tárolva.

Ha olyan függvényeket használ, mint a cv2.add és a cv2.subtract, az értékek levágásra kerülnek

ebbe a tartományba még akkor is, ha hozzáadjuk vagy kivonjuk a tartományon kívülről

[0, 255] tartomány. Íme egy illusztráció:

'''


nyomtatás ( 'maximum 255: {}' . formátum ( str ( cv2. add hozzá ( például. uint8 ( [ 201 ] ) ,

például. uint8 ( [ 100 ] ) ) ) ) )

nyomtatás ( 'minimum 0: {}' . formátum ( str ( cv2. kivonni ( például. uint8 ( [ 60 ] ) ,

például. uint8 ( [ 100 ] ) ) ) ) )

'''

Amikor ezekkel a tömbökkel aritmetikai műveleteket végez a NumPy használatával,

az érték körbe fog fordulni, nem pedig a

[0, 255]tartomány. A képek használatakor ezt feltétlenül meg kell őrizni

gondolatban.

'''


nyomtatás ( 'körbeteker: {}' . formátum ( str ( például. uint8 ( [ 201 ] ) + pl. uint8 ( [ 100 ] ) ) ) )

nyomtatás ( 'körbeteker: {}' . formátum ( str ( például. uint8 ( [ 60 ] ) - például. uint8 ( [ 100 ] ) ) ) )

'''

Szorozzuk meg képünk minden képpontjának fényerejét 101-gyel.

Ehhez a mátrixunkkal megegyező méretű NumPy tömböt állítunk elő,

tele van egyekkel, és szorozd meg 101-gyel, hogy egy kitöltött tömböt kapj

101-esekkel. Végül a két képet egyesítjük.

Észreveheti, hogy a kép most 'világosabb'.

'''


Mátrix = például. azok ( kép. alak , dtype = 'uint8' ) * 101

image_added = cv2. add hozzá ( kép , Mátrix )

cv2. imshow ( 'Hozzáadott kép eredménye' , image_added )

#Hasonló módon a felvétellel sötétebbé tehetjük képünket

# 60 távolságra az összes képponttól.

Mátrix = például. azok ( kép. alak , dtype = 'uint8' ) * 60

image_subtracted = cv2. kivonni ( kép , Mátrix )

cv2. imshow ( 'Kivont kép eredménye' , image_subtracted )

cv2. várj Key ( 0 )

1-16. sorok lesz használva a normál folyamatunk végrehajtására, amely magában foglalja a csomagjaink importálását, az argumentumelemző konfigurálását és a kép betöltését.

Emlékszel, hogyan beszéltem korábban az OpenCV és a NumPy összeadás közötti különbségtételről? Most, hogy alaposan megvizsgáltuk, nézzünk meg egy konkrét esetet, hogy biztosan megértsük.

Két 8 bites előjel nélküli egész NumPy tömb van definiálva 26. sor . A 201-es érték az egyetlen elem az első tömbben. Bár csak egy tag van a második tömbben, annak értéke 100. Az értékeket ezután az OpenCV cv2.add függvényével adjuk össze.

Milyen eredményre számít?

A hagyományos aritmetikai elveknek megfelelően a válasznak 301-nek kell lennie. De ne feledjük, hogy 8 bites előjel nélküli egész számokkal van dolgunk, amelyek csak a [0, 255] tartományban lehetnek. Mivel a cv2.add metódust használjuk, az OpenCV kezeli a kivágást, és biztosítja, hogy az összeadás csak 255-ös maximális eredményt adjon vissza.

Az alábbi lista első sora mutatja a kód futtatásának eredményét:

számtan. py

maximum az 255 : [ [ 255 ] ]

Az összeg valóban 255-öt eredményezett.

Ezt követően, 26. sor a cv2.subtract függvényt használja a kivonás végrehajtásához. Még egyszer definiálunk két 8 bites előjel nélküli egész NumPy tömböt, mindegyikben egy elemmel. Az első tömb értéke 60, míg a második tömb értéke 100.

A számtan azt diktálja, hogy a kivonás -40-es értéket eredményezzen, de az OpenCV még egyszer kezeli helyettünk a kivágást. Azt tapasztaljuk, hogy az értéket 0-ra vágtuk. Az alábbi eredményünk ezt mutatja:

számtan. py

minimum az 0 : [ [ 0 ] ]

A cv2 használatával vonjon ki 100-at a 60 kivonásból, így 0 értéket kap.

De mi történik, ha az OpenCV helyett a NumPy-t használjuk a számítások elvégzéséhez?

38. és 39. sor foglalkozzon ezzel a kérdéssel.

Először két 8 bites előjel nélküli egész NumPy tömb van meghatározva egy-egy elemmel. Az első tömb értéke 201, míg a második tömb értéke 100. A cv2.add függvény használata esetén a hozzáadást levágjuk, és 255 értéket adunk vissza.

A NumPy viszont „körbeteker” és modulo aritmetikát végez, nem pedig vágást. A NumPy a 255-ös érték elérésekor nullára teker, majd folytatja a számolást, amíg el nem éri a 100 lépést. Ezt megerősíti a kimenet első sora, amely alább látható:

számtan. py
körbeteker: [ Négy öt ]

Ezután két további NumPy tömb kerül meghatározásra, az egyik 50-es, a másik 100-as értékkel. Ezt a kivonást a cv2.subtract metódus levágja, hogy 0-t adjon vissza. De tisztában vagyunk vele, hogy a kivágás helyett a NumPy végrehajtja modulo aritmetika. Ehelyett a modulo eljárások körbefutnak, és 255-től kezdenek visszafelé számolni, ha a kivonás során elérik a 0-t. Ezt láthatjuk a következő kimenetből:

számtan. py

körbeteker: [ 207 ]

Terminál kimenetünk még egyszer bemutatja a különbséget a levágás és a körbetekerés között:

Kulcsfontosságú, hogy a kívánt eredményt tartsa szem előtt, amikor egész számokat számol. Szeretné, hogy a [0, 255] tartományon kívüli értékek levágásra kerüljenek? Ezt követően használja az OpenCV beépített képszámítási technikáit.

Szeretné, hogy az értékek körbefussanak, ha kívül esnek a [0, 255] és a modulusaritmetikai műveletek tartományán? A NumPy tömböket ezután egyszerűen hozzáadja és kivonja a szokásos módon.

48. sor egy egydimenziós NumPy tömböt határoz meg, amelynek méretei megegyeznek a képünkkel. Még egyszer gondoskodunk arról, hogy az adattípusunk 8 bites előjel nélküli egész szám legyen. Az egyjegyű értékekből álló mátrixunkat csak megszorozzuk 101-gyel, hogy 1 helyett 101-gyel töltsük fel. Végül a cv2.add függvényt használva hozzáadjuk a 100-as mátrixunkat az eredeti képhez. Ez 101-gyel növeli az egyes pixelek intenzitását, miközben biztosítja, hogy minden olyan érték, amely megkísérli meghaladni a 255-öt, a [0, 255] tartományba kerül.

Figyelje meg, hogy a kép észrevehetően világosabb és „kimosottabbnak” tűnik, mint az eredeti. Ennek az az oka, hogy a pixeleket a világosabb színek felé tereljük azáltal, hogy 101-gyel növeljük a képpontok intenzitását.

Annak érdekében, hogy a kép minden pixelintenzitásából levonjunk 60-at, először létrehozunk egy második NumPy-tömböt az 54-es sorban, amely tele van a 60-asokkal.

Ennek a kivonásnak az eredménye a következő képen látható:

A körülöttünk lévő tárgyak sokkal sötétebbnek tűnnek, mint korábban. Ennek az az oka, hogy ha minden képpontból levonunk 60-at, az RGB színtér képpontjait a sötétebb tartományokba helyezzük át.

4. Képfordítás

A forgatáshoz hasonlóan az OpenCV egy másik lehetőség a kép átfordítása az x vagy y tengelyen. Még ha nem is használják olyan gyakran az átfordítási műveleteket, ezek ismerete hihetetlenül előnyös olyan okok miatt, amelyeket nem biztos, hogy azonnal észrevesz.

Gépi tanulási osztályozót fejlesztünk egy kis startup cég számára, amely az arcokat képeken szeretné azonosítani. Ahhoz, hogy a rendszerünk „megtanulja”, mi az arc, szükségünk lenne valamilyen mintaarcokat tartalmazó adatkészletre. Sajnos a cég csak egy kis, 40 arcból álló adatkészletet adott nekünk, és nem tudunk több információt gyűjteni.

Akkor mit tegyünk?

Mivel egy arc arc marad, függetlenül attól, hogy tükröződik-e, akár nem, az arc minden képét vízszintesen megfordíthatjuk, és a tükrözött változatokat extra edzésadatként használhatjuk.

Ez a példa hülyének és mesterségesnek tűnhet, de nem az. Az átfordítás egy tudatos stratégia, amelyet erős mélytanulási algoritmusok használnak, hogy több adatot állítsanak elő a betanítási szakaszban.

Az előzőekből kitűnik, hogy az ebben a modulban elsajátított képfeldolgozási módszerek nagyobb számítógépes látórendszerek alapjául szolgálnak.

Célok:

Használni a cv2.flip funkció segítségével ezen a foglalkozáson megtanulhatja, hogyan lehet egy képet vízszintesen és függőlegesen is megfordítani.

Az átfordítás a következő képmanipuláció, amelyet tanulmányozni fogunk. Egy kép x és y tengelye megfordítható, vagy akár mindkettő. Mielőtt belemerülnénk a kódolásba, a legjobb, ha először megnézzük a képfordítás eredményeit. Tekintse meg a vízszintesen elfordított képet a következő képen:


Jegyezze meg, hogy az eredeti képünk hogyan van a bal oldalon, és hogyan tükröződött a kép vízszintesen a jobb oldalon.

Kezdjük egy új fájl létrehozásával flipping.py .

Látott már példát egy képfordításra, ezért vizsgáljuk meg a kódot:

# python flipping.py --image quirrel.jpg

# a szükséges csomagok importálása

import argparse

import cv2

# az argumentum elemző objektumának létrehozása és az argumentum elemzése

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-én' , '--kép' , kívánt = Igaz , Segítség = 'kép útja' )

érv = akinek ( apObj. parse_args ( ) )

kép = cv2. olvasatlan ( érv [ 'kép' ] )

cv2. imshow ( 'Eredeti' , kép )

# vízszintesen fordítsa meg a képet

képlapozva = cv2. flip ( kép , 1 )

cv2. imshow ( 'Kép vízszintesen megfordítva' , képlapozva )

# függőlegesen fordítsa meg a képet

képlapozva = cv2. flip ( kép , 0 )

cv2. imshow ( 'Kép függőlegesen megfordítva' , képlapozva )

# képfordítás mindkét tengely mentén

képlapozva = cv2. flip ( kép , - 1 )

cv2. imshow ( 'Vízszintesen és függőlegesen megfordítva' , képlapozva )

cv2. várj Key ( 0 )

A csomagok importálásához, a bemeneteink elemzéséhez és a kép lemezről történő betöltéséhez szükséges lépéseket a l kezeli. ines 1-12 .

A cv2.flip függvény bekapcsolásával 15. sor , egyszerű a kép vízszintes megfordítása. A cv2.flip metódushoz szükséges két argumentum a kép, amelyet meg akarunk fordítani, és egy konkrét kód vagy zászló, amely meghatározza a kép megfordításának módját.

Az 1-es flip kód azt jelenti, hogy elforgatjuk a képet az y tengely körül, hogy vízszintesen megfordítsuk ( 15. sor ). Ha 0-s flip kódot adunk meg, akkor el akarjuk forgatni a képet az x tengely körül ( 19. sor ). Negatív flip kód ( 23. sor ) mindkét tengelyen elforgatja a képet.

Az egyik legegyszerűbb példa ebben a témában a kép megfordítása, ami alapvető.

Ezután megvitatjuk a képek kivágását, és NumPy tömbszeleteket használunk adott képrészletek kinyerésére.

5. Képkivágás

A vágás, ahogy a név is sugallja, az érdeklődési terület (vagy egyszerűen ROI) kiválasztásának és eltávolításának folyamata, amely a kép minket érdeklő területe.

Az arcot le kell vágni egy képről az arcfelismerő alkalmazáshoz. Ezen túlmenően, ha Python-szkriptet hozunk létre, hogy megkeressük a kutyákat a képeken, érdemes lehet kivágni a kutyát a képből, amikor megtaláljuk.

Célok: Fő célunk, hogy megismerjük a NumPy tömbszeletelést, és könnyebben használjuk a területek kivágásához a képről.

Vágás : Amikor kivágunk egy képet, az a célunk, hogy kiküszöböljük azokat a külső elemeket, amelyek nem érdekelnek minket. A ROI kiválasztásának folyamatát gyakran érdeklődési körünk kiválasztásának nevezik.

Hozzon létre egy új fájlt crop.py , nyissa meg, és adja hozzá a következő kódot:

# python crop.py

# a szükséges csomagok importálása

import cv2

# kép betöltése és megjelenítése a képernyőn

kép = cv2. olvasatlan ( 'mókus.jpg' )

nyomtatás ( kép. alak )

cv2. imshow ( 'Eredeti' , kép )

# A NumPy tömbszeleteket a kép gyors vágására használják

# a képről levágjuk a mókusarcot

mókusarcú = kép [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'mókusarc' , mókusarcú )

cv2. várj Key ( 0 )

# És most itt fogjuk levágni az egész testet

# a mókus

mókustest = kép [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Mókus test' , mókustest )

cv2. várj Key ( 0 )

Megjelenítjük a vágást Pythonban és OpenCV-ben egy lemezről letöltött kép segítségével 5. és 6. sor .

Eredeti kép, amelyet levágunk

Kizárólag alapvető vágási technikákat alkalmazva arra törekszünk, hogy a mókus arcát és testét elkülönítsük a környező területtől.

Használjuk a képpel kapcsolatos előzetes tudásunkat, és manuálisan adjuk meg a NumPy tömbszeleteket, ahol a test és az arc található. Normál körülmények között általában gépi tanulási és számítógépes látási algoritmusokat alkalmazunk az arc és a test felismerésére a képen. De egyelőre legyünk egyértelműek, és kerüljük az észlelési modellek alkalmazását.

A képen látható arcot egyetlen kódsorból tudjuk azonosítani. 13. sor , A kép egy téglalap alakú részének (35, 35) kibontásához a NumPy tömbszeleteket (90, 100) biztosítjuk. Zavarba ejtőnek tűnhet, hogy a kivágást magasság-első és szélesség-második sorrendben adjuk meg az indexekkel, de ne feledje, hogy az OpenCV a képeket NumPy-tömbökként tárolja. Ennek eredményeként az y tengely értékeit az x tengely előtt kell megadnunk.

A NumPy a következő négy indexet igényli a kivágás végrehajtásához:

Kezdés y: Az y-koordináta az elején. Ebben az esetben y=35-tel kezdjük.

vége y: Az y koordináta a végén. A termés leáll, ha y = 90.

Kezdés x: A szelet kezdő x koordinátája. A vágás x=35-nél kezdődik.

End x: A szelet végének x tengely koordinátája. x=100-nál a szeletünk kész.

Hasonlóképpen levágjuk a (23, 35) és (143, 148) régiókat az eredeti képről, hogy kivonjuk a teljes testet a képből 19. sor .

Megfigyelheti, hogy a kép le van vágva, hogy csak a testet és az arcot mutassa be.

6. Kép ​​átméretezése

A kép szélességének és magasságának növelésének vagy csökkentésének folyamatát méretezésnek vagy egyszerűen átméretezésnek nevezik. A kép átméretezésekor figyelembe kell venni a képarányt, amely a kép szélességének és magasságának aránya. A képarány figyelmen kívül hagyása a méretezett képeket tömörítettnek és torzultnak tűnhet:

Kezdő képünk a bal oldalon. A jobb oldalon két olyan képet láthat, amelyeket a képarány megtartása nélkül méreteztek, így torzítva a kép szélességének és magasságának arányát. A képek átméretezésekor általában figyelembe kell vennie a képarányt.

Az átméretező algoritmusunk által használt interpolációs technikának figyelembe kell vennie az interpolációs függvény célját is, hogy a pixelek ezen környezetét használja a kép méretének növelésére vagy csökkentésére.

Általában a kép méretének csökkentése sokkal hatékonyabb. Ennek az az oka, hogy az interpolációs funkciónak csak a képpontok eltávolítására van szüksége a képről. Másrészt, ha a képméretet növelni akarjuk, az interpolációs módszernek ki kell töltenie a pixelek közötti hézagokat, amelyek korábban nem léteztek.

Az eredeti képünk a bal oldalon látható. A képet középen az eredeti méretének felére csökkentették, de ezt leszámítva a kép „minősége” nem romlott. Ennek ellenére a kép mérete jelentősen megnőtt a jobb oldalon. Most „felrobbantottnak” és „pixelesnek” tűnik.

Amint azt korábban említettem, általában csökkenteni kell a kép méretét, nem pedig növelni. A képméret csökkentésével kevesebb pixelt elemezünk, és kevesebb „zajjal” kell számolnunk, ami gyorsabbá és pontosabbá teszi a képfeldolgozó algoritmusokat.

A fordítás és az elforgatás az a két képátalakítás, amellyel eddig foglalkoztunk. Most megvizsgáljuk, hogyan lehet átméretezni egy képet.

Nem meglepő módon a képeinket a cv2.resize módszerrel fogjuk átméretezni. Ahogy korábban jeleztem, ennek a módszernek a használatakor figyelembe kell vennünk a kép oldalarányát. Mielőtt azonban túlságosan belemennénk a részletekbe, engedje meg, hogy egy szemléltetést adjon:

# python resize.py --image squirrel.jpg

# a szükséges csomagok importálása

import argparse

import cv2

# az argumentum elemző objektumának létrehozása és az argumentum elemzése

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--kép' , kívánt = Igaz , Segítség = 'kép útja' )

érvek = akinek ( apObj. parse_args ( ) )

# betölti a képet és megjeleníti a képernyőn

kép = cv2. olvasatlan ( érvek [ 'kép' ] )

cv2. imshow ( 'Eredeti' , kép )

# Annak érdekében, hogy a kép ne jelenjen meg ferdén, a képarányt

# figyelembe kell venni vagy deformálódni kell; ezért kitaláljuk, mit

# az új kép és az aktuális kép aránya.

# Tegyük 160 képpontra az új képünk szélességét.

vonatkozás = 160,0 / kép. alak [ 1 ]

dimenzió = ( 160 , int ( kép. alak [ 0 ] * szempont ) )

# ez a sor a tényleges átméretezési műveleteket mutatja

átméretezett kép = cv2. átméretezni ( kép , dimenzió , interpoláció = cv2. INTER_AREA )

cv2. imshow ( 'Átméretezett képszélesség' , átméretezett kép )

# Mi van, ha meg akarjuk változtatni a kép magasságát? - használni a

# ugyanazon az elven, tudjuk kiszámítani a képarány alapján

# inkább a magasságra, mint a szélességre. Készítsük el a mérleget

# kép magassága 70 pixel.

vonatkozás = 70,0 / kép. alak [ 0 ]

dimenzió = ( int ( kép. alak [ 1 ] * szempont ) , 70 )

# hajtsa végre az átméretezést

átméretezett kép = cv2. átméretezni ( kép , dimenzió , interpoláció = cv2. INTER_AREA )

cv2. imshow ( 'Átméretezett kép magassága' , átméretezett kép )

cv2. várj Key ( 0 )

sorok 1-14 , A csomagjaink importálása és az argumentumelemző konfigurálása után betöltjük és megjelenítjük a képünket.

20. és 21. sor: A vonatkozó kódolás ezekben a sorokban kezdődik . A kép átméretezésénél figyelembe kell venni a kép méretarányát. A kép szélessége és magassága közötti arányt képaránynak nevezzük.

Magasság szélesség a képarány.

Ha nem vesszük figyelembe a képarányt, akkor az átméretezés eredménye torz lesz.

Tovább 20. sor , az átméretezett arány számítása megtörténik. Ebben a kódsorban 160 pixelben adjuk meg az új képünk szélességét. Egyszerűen definiáljuk az arányunkat (aspectratio) úgy, hogy az új szélesség (160 pixel) osztva a régi szélességgel, amelyet kép segítségével érünk el, hogy kiszámítsuk az új magasság és a régi magasság arányát. alakzat[1].

A kép új méretei bekapcsolva 21. sor kiszámítható most, hogy ismerjük az arányunkat. Az új kép szélessége ismét 160 pixel lesz. Miután megszoroztuk a régi magasságot az arányunkkal, és az eredményt egész számra konvertáltuk, kiszámítjuk a magasságot. Ezzel a művelettel megőrizhetjük a kép eredeti képarányát.

24. sor ahol a kép valóban át van méretezve. Az átméretezni kívánt kép az első argumentum, a második pedig az új képhez kiszámított méretek. Interpolációs módszerünk, amely az aktuális kép átméretezésének algoritmusa, az utolsó paraméter.

Végül be 25. sor , megjelenítjük a méretezett képünket.

Újradefiniáljuk az arányunkat (aspectratio) on 31. sor . Az új képünk magassága 70 pixel lesz. 70-et elosztunk az eredeti magassággal, hogy megkapjuk az új magasság-eredeti magasság arányt.

Ezután meghatározzuk az új kép méreteit. Az új kép 70 pixel magasságú lesz, ami már ismert. Ismét megtarthatjuk a kép eredeti képarányát, ha a régi szélességet megszorozzuk az aránnyal, így az új szélességet kapjuk.

A kép ekkor ténylegesen átméreteződik 35. sor , és megjelenik 36. sor.

Itt láthatjuk, hogy csökkentettük az eredeti kép szélességét és magasságát, miközben megtartottuk a képarányt. A képünk torzulna, ha nem tartják be a képarányt.

Következtetés

Ebben a blogban az alapvető különböző képfeldolgozási fogalmakat tanulmányoztuk. Láttunk képfordítást az OpenCV csomag segítségével. Láttuk a kép felfelé, lefelé, jobbra és balra mozgatásának módszereit. Ezek a módszerek nagyon hasznosak, ha hasonló képekből készítünk egy adatkészletet, amelyet képzési adatkészletként adunk, így a gép különböző képeket fog látni, még akkor is, ha azok azonosak. Ez a cikk azt is megtanította, hogyan forgathat el egy képet a derékszögű tér bármely pontja körül elforgatási mátrix segítségével. Aztán felfedezted, hogy az OpenCV hogyan forgatja el a képeket ezzel a mátrixszal, és láttad néhány pörgő kép illusztrációját.

Ebben a részben a két alapvető (de jelentős) képaritmetikai műveletet, az összeadást és a kivonást vizsgáltuk. Amint látja, az alapvető mátrixok összeadása és kivonása az összes képaritmetikai műveletből áll.

Emellett OpenCV és NumPy segítségével vizsgáltuk a képaritmetika sajátosságait. Ezeket a korlátozásokat szem előtt kell tartani, különben váratlan eredményeket kaphat, amikor aritmetikai műveleteket hajt végre a képeken.

Fontos megjegyezni, hogy bár a NumPy modulus-műveletet hajt végre, és „körbejár”, az OpenCV összeadás és kivonás csökkenti a [0, 255] tartományon túli értékeket, hogy beleférjen a tartományba. Amikor saját számítógépes látásalkalmazásait fejleszti, ennek emlékezése segít elkerülni a trükkös hibák felkutatását.

A képfordítás kétségtelenül az egyik egyszerűbb ötlet, amelyet ezen a tanfolyamon megvizsgálunk. Az átfordítást gyakran alkalmazzák a gépi tanulásban, hogy több tanítási adatmintát állítsanak elő, ami hatékonyabb és megbízhatóbb képosztályozókat eredményez.

Azt is megtanultuk, hogyan lehet az OpenCV-vel átméretezni egy képet. Alapvető fontosságú, hogy az alkalmazott interpolációs módszert és az eredeti kép képarányát is figyelembe vegye az átméretezés során, hogy az eredmény ne tűnjön torznak.

Végezetül fontos megjegyezni, hogy ha a képminőség probléma, mindig a legjobb, ha nagyobb képről kisebbre vált. A legtöbb esetben a kép nagyítása műtermékeket hoz létre, és rontja a minőségét.