Bildbearbetning OpenCV

Bildbearbetning Opencv



Vi kommer att studera bildbehandlingsmetoderna i den här artikeln. Vi kommer att undersöka några grundläggande men kritiska ämnen inom datorseende och maskininlärning. Dessa grundläggande bildbehandlingstekniker kan lösa komplexa problem, såsom datauppsättningar. Som ett resultat finns det sex grundläggande steg i bildbehandling, som listas nedan:
  1. Bildöversättning
  2. Bildrotation
  3. Bild Aritmetik
  4. Bild Vänd
  5. Bildbeskärning
  6. Ändra storlek på bilden

Nu kommer vi att förklara alla ovan nämnda bildbehandlingsämnen i detalj.

1. Bildöversättning

Bildöversättning är en bildbehandlingsmetod som hjälper oss att flytta bilden längs x- och y-axlarna. Vi kan flytta bilden uppåt, nedåt, höger, vänster eller vilken kombination som helst.







Vi kan definiera översättningsmatrisen med symbolen M, och vi kan representera den i matematisk form, som visas nedan:





Vi kan förstå konceptet med översättningsbilden genom detta program.





Python-kod: Vi kommer att behålla följande programs namn som translate.py .

# importera nödvändiga paket

importera numpy som t.ex.

importera argparse

importera imutil

importera cv2

# vi implementerar argumentparsern

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--bild' , nödvändig = Sann ,

hjälp = 'plats för bildfilen' )

args = vars ( ap_obj. parse_args ( ) )

# ladda bilden och visa den på skärmen

bild = cv2. imread ( args [ 'bild' ] )

cv2. imshow ( 'Original_image' , bild )

# Översättningen av bilden är en NumPy-matris som ges nedan:

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

# Vi kommer att använda ovanstående NumPy-matris för att flytta bilderna längs med

# x-axel- och y-axelriktningar. För detta måste vi helt enkelt skicka pixelvärdena.

# I det här programmet kommer vi att flytta bilden 30 pixlar åt höger

# och 70 pixlar längst ner.

translation_mat = t.ex. flyta 32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

bildöversättning = cv2. warpAffine ( bild , translation_mat ,

( bild. form [ 1 ] , bild. form [ 0 ] ) )

cv2. imshow ( 'Bildöversättning Ner och höger' , bildöversättning )

# nu kommer vi att använda ovanstående NumPy-matris för att flytta bilderna längs med

# x-axel (vänster) och y-axel (upp) riktningar.

# Här kommer vi att flytta bilderna 50 pixlar till vänster

# och 90 pixlar uppåt.

translation_mat = t.ex. flyta 32 ( [ [ 1 , 0 , - femtio ] , [ 0 , 1 , - 90 ] ] )

bildöversättning = cv2. warpAffine ( bild , translation_mat ,

( bild. form [ 1 ] , bild. form [ 0 ] ) )

cv2. imshow ( 'Bildöversättning Upp och vänster' , bildöversättning )

cv2. waitKey ( 0 )

Rad 1 till 5: Vi importerar alla nödvändiga paket för detta program, som OpenCV, argparser och NumPy. Observera att det finns ett annat bibliotek som är imutils. Detta är inte ett paket med OpenCV. Detta är bara ett bibliotek som enkelt visar samma bildbehandling.



Bibliotekets imutils kommer inte att inkluderas automatiskt när vi installerar OpenCV. Så för att installera imutilerna måste vi använda följande metod:

pip installera imutils

Rad 8 till 15: Vi skapade vår agrparser och laddade vår bild.

Rad 24 till 25: Den här programdelen är där översättningen sker. Översättningsmatrisen talar om för oss hur många pixlar bilden kommer att flyttas upp eller ner eller åt vänster eller höger. Eftersom OpenCV kräver att matrisvärdet finns i en flyttalsmatris, tar översättningsmatrisen värden i flyttalsmatriser.

Översättningsmatrisens första rad ser ut så här:

Denna rad i matrisen är för x-axeln. Värdet av t x kommer att avgöra om bilden ska flyttas till vänster eller höger sida. Om vi ​​skickar ett negativt värde betyder det att bilden kommer att flyttas till vänster sida, och om värdet är positivt betyder det att bilden kommer att flyttas till höger sida.

Vi kommer nu att definiera den andra raden i matrisen enligt följande:

Denna rad i matrisen är för y-axeln. Värdet av t Y kommer att avgöra om bilden ska flyttas uppåt eller nedåt. Om vi ​​skickar ett negativt värde betyder det att bilden kommer att flyttas till uppsidan, och om värdet är positivt betyder det att bilden kommer att flyttas till nedsidan.

I det föregående programmet på rad 24 definierar vi t x = 30 och t Y = 70. Så vi flyttar bilden 30 pixlar mot höger sida och 70 pixlar nedåt.

Men den huvudsakliga bildöversättningsprocessen äger rum på rad 25, där vi definierar översättningsmatrisen cv2.warpAffine . I den här funktionen skickar vi tre parametrar: den första parametern är bilden, den andra parametern är översättningsmatrisen och den tredje parametern är bilddimensionen.

Rad 27: Rad 27 visar resultatet i utgången.

Nu kommer vi att implementera ytterligare en översättningsmatris för vänster och uppåt. För detta måste vi definiera värdena i negativa.

Rad 33 till 34: I det föregående programmet på rad 33 definierar vi t x = -50 och t Y = -90. Så vi flyttar bilden 50 pixlar mot vänster sida och 90 pixlar uppåt. Men den huvudsakliga bildöversättningsprocessen äger rum på rad 34, där vi definierar översättningsmatrisen cv2.warpAffine .

Linje 36 : Rad 36 kommer att visa resultatet som visas i utgången.

För att köra den föregående koden måste vi ange sökvägen till bilden enligt nedan.

Produktion: python translate.py –image squirrel.jpg

Nu kommer vi att implementera samma bildöversättningsprogram med hjälp av imutil bibliotek. Detta bibliotek är mycket lätt att använda för bildbehandling. I det här biblioteket behöver vi inte tänka på cv2.warpAffine eftersom det här biblioteket tar hand om detta. Så låt oss implementera detta bildöversättningsprogram med hjälp av imutils-biblioteket.

Python-kod: Vi kommer att behålla följande programs namn som translate_imutils.py .

# importera nödvändiga paket

importera numpy som t.ex.

importera argparse

importera imutil

importera cv2

# Den här funktionen implementerar bildöversättningen och

# returnerar den översatta bilden till den anropande funktionen.

def Översätt ( bild , x , Y ) :

translation_matrix = t.ex. flyta 32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

bildöversättning = cv2. warpAffine ( bild , translation_matrix ,

( bild. form [ 1 ] , bild. form [ 0 ] ) )

lämna tillbaka bildöversättning

# konstruera argumentparsern och analysera argumenten

ap = argparse. ArgumentParser ( )

ap. add_argument ( '-jag' , '--bild' , nödvändig = Sann , hjälp = 'Väg till bilden' )

args = vars ( ap. parse_args ( ) )

# ladda bilden och visa den på skärmen

bild = cv2. imread ( args [ 'bild' ] )

cv2. imshow ( 'Original_image' , bild )

bildöversättning = imutil. Översätt ( bild , 10 , 70 )

cv2. imshow ( 'Bildöversättning till höger och nedåt' ,

bildöversättning )

cv2. waitKey ( 0 )

Rad 9 till 13: Den här delen av programmet är där översättningen sker. Översättningsmatrisen informerar oss om hur många pixlar bilden kommer att flyttas upp eller ner eller till vänster eller höger.

Dessa rader har redan förklarats, men nu ska vi bygga en funktion som heter translate () och skicka tre distinkta parametrar till den. Själva bilden fungerar som den första parametern. Översättningsmatrisens x- och y-värden motsvarar de andra och tredje parametrarna.

Notera : Det finns inget behov av att definiera denna översättningsfunktion inuti programmet eftersom den redan ingår i imutils bibliotekspaket. Jag har använt det inom programmet för en enkel förklaring. Vi kan anropa denna funktion direkt med imutils, som visas på rad 24.

Rad 24: Det föregående programmet kommer att visa att på rad 24 definierar vi tx = 10 och ty = 70. Så vi flyttar bilden 10 pixlar mot höger sida och 70 pixlar nedåt.

I det här programmet bryr vi oss inte om några cv2.warpAffine-funktioner eftersom de redan finns inuti imutils bibliotekspaket.

För att köra den föregående koden måste vi ange sökvägen till bilden, enligt nedan:

Produktion:

python imutils. py --bild ekorre. jpg

2. Bildrotation

Vi gick igenom hur man översätter (d.v.s. flyttar) en bild uppåt, nedåt, åt vänster och höger i föregående lektion (eller valfri kombination). Därefter kommer vi att diskutera rotation när det gäller bildbehandling.

En bild roteras med en vinkel, theta, i en process som kallas rotation. Vinkeln med vilken vi roterar bilden kommer att representeras av theta. Dessutom kommer jag att tillhandahålla den roterande bekvämlighetsfunktionen för att göra roterande bilder enklare.

I likhet med translation, och kanske inte överraskande, rotation med en vinkel, bestäms theta genom att bygga en matris M i följande format:

Denna matris kan rotera en vektor theta-grader (moturs) runt det angivna origo (x, y)-kartesiska planet. Vanligtvis, i det här scenariot, skulle ursprunget vara bildens mitt, men i själva verket kan vi ange vilken slumpmässig (x, y) punkt som helst som vårt rotationscentrum.

Den roterade bilden R skapas sedan från den ursprungliga bilden I med användning av enkel matrismultiplikation: R = IM

OpenCV, å andra sidan, erbjuder dessutom kapaciteten att (1) skala (d.v.s. ändra storlek på) en bild och (2) erbjuda ett godtyckligt rotationscentrum för att utföra rotationen runt.

Vår modifierade rotationsmatris M visas nedan:

Låt oss börja med att öppna och skapa en ny fil som heter rotate.py :

# importerar de nödvändiga paketen

importera numpy som t.ex.

importera argparse

importera imutil

importera cv2

# skapa argumentparser-objektet och parsarargumentet

apobj = argparse. ArgumentParser ( )

apobj. add_argument ( '-k' , '--bild' , nödvändig = Sann , hjälp = 'bildväg' )

argument = vars ( apobj. parse_args ( ) )

bild = cv2. imread ( argument [ 'bild' ] )

cv2. imshow ( 'Original_image' , bild )

# Beräkna bildens mitt med hjälp av bildens mått.

( höjd , bredd ) = bild. form [ : 2 ]

( centerX , centerY ) = ( bredd / 2 , höjd / 2 )

# Nu, med hjälp av cv2, kommer vi att rotera bilden 55 grader till

# bestäm rotationsmatrisen med getRotationMatrix2D()

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

roterad bild = cv2. warpAffine ( bild , rotationsmatris , ( bredd , höjd ) )

cv2. imshow ( 'Roterade bilden med 55 grader' , roterad bild )

cv2. waitKey ( 0 )

# Bilden kommer nu att roteras med -85 grader.

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

roterad bild = cv2. warpAffine ( bild , rotationsmatris , ( bredd , höjd ) )

cv2. imshow ( 'Roterade bilden med -85 grader' , roterad bild )

cv2. waitKey ( 0 )

Rad 1 till 5: Vi importerar alla nödvändiga paket för detta program, som OpenCV, argparser och NumPy. Observera att det finns ett annat bibliotek som är imutils. Detta är inte ett paket med OpenCV. Detta är bara ett bibliotek som kommer att användas för att enkelt visa samma bildbehandling.

Bibliotekets imutils kommer inte att inkluderas automatiskt när vi installerar OpenCV. OpenCV installerar imutils. Vi måste använda följande metod:

pip installera imutils

Rad 8 till 14: Vi skapade vår agrparser och laddade vår bild. I denna argparser använder vi bara ett bildargument, vilket kommer att berätta för oss sökvägen till bilden som vi kommer att använda i det här programmet för att demonstrera rotationen.

När vi roterar en bild måste vi definiera rotationens pivotpunkt. För det mesta vill du rotera en bild kring dess mitt, men OpenCV låter dig välja valfri slumpmässig punkt istället. Låt oss helt enkelt rotera bilden runt dess mitt.

Rad 17 till 18 ta bildens bredd respektive höjd och dela sedan varje dimension med två för att fastställa bildens mitt.

Vi konstruerar en matris för att rotera en bild på samma sätt som vi definierade en matris för att översätta en bild. Vi ringer bara cv2.getRotationMatrix2D funktion på linje 22 istället för att manuellt skapa matrisen med hjälp av NumPy (vilket kan vara lite krångligt).

De cv2.getRotationMatrix2D funktionen kräver tre parametrar. Den första ingången är den önskade rotationsvinkeln (i detta fall bildens mitt). Theta används sedan för att ange hur många (motsols) grader vi ska rotera bilden. Här kommer vi att rotera bilden 45 grader. Det sista alternativet är relaterat till bildens storlek.

Oavsett det faktum att vi ännu inte har diskuterat skalning av en bild, kan du ange ett flyttal här med 1,0 som anger att bilden ska användas i sina ursprungliga proportioner. Men om du skrev ett värde på 2,0 skulle bilden fördubblas i storlek. Ett tal på 0,5 minskar bildens storlek så.

Rad 22 till 23: Efter att ha mottagit vår rotationsmatris M från cv2.getRotationMatrix2D funktionen roterar vi vår bild med hjälp av cv2.warpAffine teknik på rad 23. Funktionens första ingång är bilden som vi vill rotera. Bredden och höjden på vår utgående bild definieras sedan tillsammans med vår rotationsmatris M. På rad 23 roteras bilden sedan 55 grader.

Du kan märka att vår bild har roterats.

Rad 28 till 30 utgör den andra rotationen. Raderna 22–23 i koden är identiska, förutom att vi denna gång roterar med -85 grader i motsats till 55.

Vi har helt enkelt roterat en bild runt dess mitt fram till denna punkt. Tänk om vi ville rotera bilden runt en slumpmässig punkt?

Låt oss börja med att öppna och skapa en ny fil som heter rotate.py:

# importerar de nödvändiga paketen

importera numpy som t.ex.

importera argparse

importera imutil

importera cv2

# skapa argumentparser-objektet och analysargumentet

ap_obj = argparse. ArgumentParser ( )

ap_obj. add_argument ( '-k' , '--bild' , nödvändig = Sann , hjälp = 'bildväg' )

argument = vars ( ap_obj. parse_args ( ) )

# ladda bilden och visa den på skärmen

bild = cv2. imread ( argument [ 'bild' ] )

cv2. imshow ( 'Original_image' , bild )

# Beräkna bildens mitt med hjälp av bildens mått.

( höjd , bredd ) = bild. form [ : 2 ]

( centerX , centerY ) = ( bredd / 2 , höjd / 2 )

# Nu, med hjälp av cv2, kommer vi att rotera bilden 55 grader till

# bestäm rotationsmatrisen med getRotationMatrix2D()

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

roterad bild = cv2. warpAffine ( bild , rotationsmatris , ( bredd , höjd ) )

cv2. imshow ( 'Roterade bilden med 55 grader' , roterad bild )

cv2. waitKey ( 0 )

# Bilden kommer nu att roteras med -85 grader.

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

roterad bild = cv2. warpAffine ( bild , rotationsmatris , ( bredd , höjd ) )

cv2. imshow ( 'Roterade bilden med -85 grader' , roterad bild )

cv2. waitKey ( 0 )

# bildrotation från någon godtycklig punkt, inte från mitten

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

roterad bild = cv2. warpAffine ( bild , rotationsmatris , ( bredd , höjd ) )

cv2. imshow ( 'Bildrotation från godtyckliga punkter' , roterad bild )

cv2. waitKey ( 0 )

Rad 34 till 35: Nu borde den här koden verka ganska vanlig för att rotera ett objekt. För att rotera bilden runt en punkt 40 pixlar till vänster och 40 pixlar ovanför dess mitt, instruerar vi cv2.getRotationMatrix2D funktion för att uppmärksamma dess första parameter.

Bilden som skapas när vi tillämpar denna rotation visas nedan:

Vi kan tydligt se rotationens centrum är nu (x, y)-koordinaten, som är 40 pixlar till vänster och 40 pixlar ovanför den beräknade mitten av bilden.

3. Bildräkning

Faktum är att bildaritmetik bara är matristillägg med några ytterligare begränsningar för datatyper som vi kommer att täcka senare.

Låt oss ta en stund för att gå igenom några ganska grundläggande principer för linjär algebra.

Överväg att kombinera de följande två matriserna:

Vilket resultat skulle matristillägget ge? Det enkla svaret är summan av matrisposterna, element för element:

Enkelt nog, eller hur?

Vi förstår alla de grundläggande funktionerna för addition och subtraktion vid denna tidpunkt. Vi måste dock vara uppmärksamma på de begränsningar som vår färgrymd och datatyp ställer när vi arbetar med bilder.

Pixlar i RGB-bilder ligger till exempel mellan [0, 255]. Vad händer om vi försöker lägga till 10 till en pixel med en intensitet på 250 medan vi tittar på den?

Vi skulle komma fram till ett värde på 260 om vi tillämpade vanliga aritmetiska principer. 260 är inte ett giltigt värde, eftersom RGB-bilder representeras som 8-bitars heltal utan tecken.

Så vad borde hända? Ska vi köra en kontroll för att säkerställa att ingen pixel ligger utanför intervallet [0, 255] och klippa varje pixel till ett värde mellan 0 och 255?

Eller 'lindar vi runt' och utför en moduloperation? I enlighet med modulreglerna skulle en addering av 10 till 255 bara resultera i ett värde på 9.

Hur ska tillägg och subtraktioner till bilder utanför intervallet [0, 255] hanteras?

Sanningen är att det inte finns någon rätt eller fel teknik; allt beror på hur du arbetar med dina pixlar och vad du hoppas uppnå.

Men kom ihåg att det finns skillnader mellan addition i OpenCV och addition i NumPy. Modularitmetik och 'wrap around' kommer att göras av NumPy. Däremot kommer OpenCV att utföra klippning och se till att pixelvärden aldrig lämnar intervallet [0, 255].

Låt oss börja med att skapa en ny fil som heter aritmetic.py och öppnar den:

# python arithmetic.py --image squirrel.jpg

# importerar de nödvändiga paketen

importera numpy som t.ex.

importera argparse

importera imutil

importera cv2

# skapa argumentparser-objektet och parsarargumentet

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--bild' , nödvändig = Sann , hjälp = 'bildväg' )

argument = vars ( apObj. parse_args ( ) )

bild = cv2. imread ( argument [ 'bild' ] )

cv2. imshow ( 'Original_image' , bild )

'''

Värdena på våra pixlar kommer att ligga inom intervallet [0, 255]

eftersom bilder är NumPy-matriser, som lagras som osignerade 8-bitars heltal.

När du använder funktioner som cv2.add och cv2.subtract kommer värden att klippas

till detta intervall även om de läggs till eller subtraheras från utanför

[0, 255] intervall. Här är en illustration:

'''


skriva ut ( 'max 255: {}' . formatera ( str ( cv2. Lägg till ( t.ex. uint8 ( [ 201 ] ) ,

t.ex. uint8 ( [ 100 ] ) ) ) ) )

skriva ut ( 'minst 0: {}' . formatera ( str ( cv2. subtrahera ( t.ex. uint8 ( [ 60 ] ) ,

t.ex. uint8 ( [ 100 ] ) ) ) ) )

'''

När du gör aritmetiska operationer med dessa matriser med NumPy,

värdet kommer att omslutas i stället för att klippas till

[0, 255]intervall. När du använder bilder är det viktigt att behålla detta

i åtanke.

'''


skriva ut ( 'vira runt: {}' . formatera ( str ( t.ex. uint8 ( [ 201 ] ) + t.ex. uint8 ( [ 100 ] ) ) ) )

skriva ut ( 'vira runt: {}' . formatera ( str ( t.ex. uint8 ( [ 60 ] ) - t.ex. uint8 ( [ 100 ] ) ) ) )

'''

Låt oss multiplicera ljusstyrkan för varje pixel i vår bild med 101.

För att göra detta genererar vi en NumPy-array av samma storlek som vår matris,

fylld med ettor och multiplicera den med 101 för att skapa en array fylld

med 101:or. Slutligen slår vi samman de två bilderna.

Du kommer att notera att bilden nu är 'ljusare'.

'''


Matris = t.ex. ettor ( bild. form , dtype = 'uint8' ) * 101

image_added = cv2. Lägg till ( bild , Matris )

cv2. imshow ( 'Tillagt bildresultat' , image_added )

#På ett liknande sätt kan vi göra vår bild mörkare genom att ta

# 60 bort från alla pixlar.

Matris = t.ex. ettor ( bild. form , dtype = 'uint8' ) * 60

bild_subtraherad = cv2. subtrahera ( bild , Matris )

cv2. imshow ( 'Subtraherat bildresultat' , bild_subtraherad )

cv2. waitKey ( 0 )

Rad 1 till 16 kommer att användas för att utföra vår normala process, vilket innebär att importera våra paket, konfigurera vår argumentparser och ladda vår bild.

Kom ihåg hur jag tidigare diskuterade skillnaden mellan OpenCV och NumPy-tillägg? Nu när vi har täckt det noggrant, låt oss titta på ett specifikt fall för att säkerställa att vi förstår det.

Två 8-bitars osignerade heltals NumPy-matriser definieras på rad 26 . Ett värde på 201 är det enda elementet i den första matrisen. Även om endast en medlem finns i den andra arrayen har den ett värde på 100. Värdena läggs sedan till med hjälp av OpenCV:s cv2.add-funktion.

Vad tror du resultatet blir?

I enlighet med konventionella aritmetiska principer bör svaret vara 301. Men kom ihåg att vi har att göra med 8-bitars heltal utan tecken, som bara kan vara i intervallet [0, 255]. Eftersom vi använder metoden cv2.add, hanterar OpenCV klippning och säkerställer att tillägget endast ger ett maximalt resultat på 255.

Den första raden i listan nedan visar resultatet av att köra den här koden:

aritmetisk. py

max 255 : [ [ 255 ] ]

Summan gav verkligen ett antal av 255.

Efter det, rad 26 använder cv2.subtract för att utföra en subtraktion. Än en gång definierar vi två 8-bitars heltals-NumPy-arrayer utan tecken med ett enda element i varje. Värdet på den första matrisen är 60, medan värdet på den andra matrisen är 100.

Vår aritmetik säger att subtraktionen ska resultera i ett värde på -40, men OpenCV hanterar klippningen åt oss en gång till. Vi upptäcker att värdet har trimmats till 0. Vårt resultat nedan visar detta:

aritmetisk. py

minimum av 0 : [ [ 0 ] ]

Använd cv2, subtrahera 100 från 60 subtrahera, vilket ger värdet 0.

Men vad händer om vi använder NumPy i stället för OpenCV för att utföra beräkningarna?

Rad 38 och 39 ta itu med denna fråga.

Först definieras två 8-bitars heltals-NumPy-arrayer utan tecken med ett enda element vardera. Värdet på den första matrisen är 201, medan värdet på den andra matrisen är 100. Vår addition skulle trimmas och ett värde på 255 skulle returneras om vi använde cv2.add-funktionen.

NumPy, å andra sidan, 'lindar runt' och gör modulo aritmetik snarare än klippning. NumPy går runt till noll när ett värde på 255 har nåtts och fortsätter sedan att räkna upp tills 100 steg har uppnåtts. Detta bekräftas av den första utdataraden, som visas nedan:

aritmetisk. py
vira runt: [ Fyra fem ]

Sedan definieras ytterligare två NumPy-matriser, en med värdet 50 och den andra med 100. Denna subtraktion skulle trimmas med metoden cv2.subtract för att returnera resultatet 0. Men vi är medvetna om att istället för att klippa, kör NumPy modulo aritmetik. Istället lindas moduloprocedurerna runt och börjar räkna bakåt från 255 när 0 nås under subtraktionen. Vi kan se detta från följande utdata:

aritmetisk. py

vira runt: [ 207 ]

Än en gång visar vår terminalutgång skillnaden mellan klippning och lindning:

Det är viktigt att ha ditt önskade resultat i åtanke när du utför heltalsräkning. Vill du att några värden utanför intervallet [0, 255] ska klippas? Använd OpenCV:s inbyggda bildarithmetiktekniker efter det.

Vill du att värden ska omslutas om de ligger utanför intervallet för [0, 255] och aritmetiska moduloperationer? NumPy-matriserna läggs sedan helt enkelt till och subtraheras som vanligt.

Linje 48 definierar en endimensionell NumPy-array med samma dimensioner som vår bild. Återigen säkerställer vi att vår datatyp är 8-bitars heltal utan tecken. Vi multiplicerar bara vår matris med ensiffriga värden med 101 för att fylla den med värden på 101 istället för 1. Slutligen använder vi funktionen cv2.add för att lägga till vår matris på 100s till originalbilden. Detta ökar varje pixels intensitet med 101 samtidigt som det säkerställer att alla värden som försöker överskrida 255 klipps till intervallet [0, 255].

Observera hur bilden är märkbart ljusare och verkar mer 'uttvättad' än originalet. Detta beror på att vi driver pixlar mot ljusare färger genom att höja deras pixelintensitet med 101.

För att subtrahera 60 från varje pixelintensitet i bilden, etablerar vi först en andra NumPy-array på linje 54 som är fylld med 60-talet.

Resultaten av denna subtraktion visas i följande bild:

Föremålen runt omkring oss ser betydligt mörkare ut än de gjorde tidigare. Detta beror på att genom att subtrahera 60 från varje pixel flyttar vi pixlarna i RGB-färgrymden till de mörkare områdena.

4. Bildvändning

I likhet med rotation är att vända en bild över dess x- eller y-axel ett annat alternativ som erbjuds av OpenCV. Även om vändningsoperationer inte används så ofta, är det oerhört fördelaktigt att känna till dem av olika anledningar som du kanske inte direkt ser.

Vi utvecklar en maskininlärningsklassificerare för ett litet nystartat företag som försöker identifiera ansikten i bilder. För att vårt system ska 'lära sig' vad ett ansikte är, skulle vi behöva någon form av datauppsättning med exempelansikten. Tyvärr har företaget bara gett oss en liten datauppsättning med 40 ansikten, och vi kan inte samla in mer information.

Vad gör vi då?

Eftersom ett ansikte förblir ett ansikte oavsett om det är spegelvänt eller inte, kan vi vända varje bild av ett ansikte horisontellt och använda de spegelvända versionerna som extra träningsdata.

Det här exemplet kan verka dumt och konstlat, men det är det inte. Flipping är en medveten strategi som används av starka djupinlärningsalgoritmer för att producera mer data under träningsfasen.

Det är tydligt från föregående att de bildbehandlingsmetoder du lär dig i denna modul fungerar som grunden för större datorseendesystem.

Mål:

Använda cv2.flip funktionen kommer du att lära dig hur du vänder en bild både horisontellt och vertikalt i denna session.

Vändning är nästa bildmanipulation vi kommer att studera. En bilds x- och y-axlar kan vändas eller till och med båda. Innan vi dyker in i kodningen är det bäst att först titta på resultatet av en bildvändning. Se en bild som har vänts horisontellt i följande bild:


Notera hur vår originalbild är till vänster och hur bilden har spegelvänts horisontellt till höger.

Låt oss börja med att skapa en ny fil som heter flipping.py .

Du har sett ett exempel på en bildvändning, så låt oss undersöka koden:

# python flipping.py --image quirrel.jpg

# importerar de nödvändiga paketen

importera argparse

importera cv2

# skapa objektet för argument parser och analysera argumentet

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-jag' , '--bild' , nödvändig = Sann , hjälp = 'bildväg' )

argument = vars ( apObj. parse_args ( ) )

bild = cv2. imread ( argument [ 'bild' ] )

cv2. imshow ( 'Original' , bild )

# Vänd bilden horisontellt

bildvänd = cv2. flip ( bild , 1 )

cv2. imshow ( 'Vänd bild horisontellt' , bildvänd )

# Vänd bilden vertikalt

bildvänd = cv2. flip ( bild , 0 )

cv2. imshow ( 'Vänd bild vertikalt' , bildvänd )

# bild vänd längs båda axlarna

bildvänd = cv2. flip ( bild , - 1 )

cv2. imshow ( 'Vänd horisontellt och vertikalt' , bildvänd )

cv2. waitKey ( 0 )

Stegen vi tar för att importera våra paket, analysera våra indata och ladda vår bild från disken hanteras i l ines 1 till 12 .

Genom att aktivera cv2.flip-funktionen Rad 15 , är det enkelt att vända en bild horisontellt. Bilden vi försöker vända och en specifik kod eller flagga som anger hur bilden ska vändas är de två argument som behövs för metoden cv2.flip.

Ett flipkodvärde på 1 betyder att vi kommer att rotera bilden runt y-axeln för att vända den horisontellt ( Rad 15 ). Om vi ​​anger en flip-kod på 0, vill vi rotera bilden runt x-axeln ( Linje 19 ). En negativ flipkod ( Linje 23 ) roterar bilden på båda axlarna.

Ett av de enklaste exemplen i detta ämne är att vända en bild, vilket är grundläggande.

Därefter kommer vi att diskutera beskärning av bilder och använda NumPy-arrayskivor för att extrahera specifika bilddelar.

5. Bildbeskärning

Beskärning, som namnet antyder, är processen att välja och ta bort intresseregionen (eller helt enkelt ROI), som är det område av bilden som intresserar oss.

Ansiktet måste beskäras från en bild för ett ansiktsavkänningsprogram. Dessutom, om vi skapade ett Python-skript för att hitta hundar i bilder, kanske vi vill beskära hunden ur bilden när vi hittar den.

Mål: Vårt huvudsakliga mål är att bli bekanta med och lätt att använda NumPy-arrayslicing för att beskära områden från en bild.

Beskärning : När vi beskär en bild är vårt mål att eliminera de yttre elementen som inte intresserar oss. Processen att välja vår ROI kallas ofta för att välja vår region av intresse.

Skapa en ny fil som heter crop.py , öppna den och lägg till följande kod:

# python crop.py

# importerar de nödvändiga paketen

importera cv2

# bild laddas och visas på skärmen

bild = cv2. imread ( 'squirrel.jpg' )

skriva ut ( bild. form )

cv2. imshow ( 'Original' , bild )

# NumPy-arrayskivor används för att snabbt trimma en bild

# vi ska beskära ekorrens ansikte från bilden

ekorreansikte = bild [ 35 : 90 , 35 : 100 ]

cv2. imshow ( 'ekorre ansikte' , ekorreansikte )

cv2. waitKey ( 0 )

# Och nu, här ska vi beskära hela kroppen

# av ekorren

ekorrkropp = bild [ 35 : 148 , 23 : 143 ]

cv2. imshow ( 'Ekorrkropp' , ekorrkropp )

cv2. waitKey ( 0 )

Vi visar beskärning i Python och OpenCV med hjälp av en bild som vi laddar från disken på Rad 5 och 6 .

Originalbild som vi ska beskära

Med enbart grundläggande beskärningstekniker strävar vi efter att separera ekorrens ansikte och ekorrkropp från det omgivande området.

Vi kommer att använda våra förkunskaper om bilden och manuellt tillhandahålla NumPy-arrayskivorna där kroppen och ansiktet finns. Under normala förhållanden skulle vi i allmänhet använda maskininlärning och datorseendealgoritmer för att känna igen ansiktet och kroppen i bilden. Men låt oss hålla saker raka tills vidare och undvika att använda några upptäcktsmodeller.

Vi kan identifiera ansiktet på bilden med bara en rad kod. Linje 13 , För att extrahera en rektangeldel av bilden, med början på (35, 35), tillhandahåller vi NumPy-arrayskivor (90, 100). Det kan verka förvirrande att vi matar grödan med indexen i höjd-första och bredd-sekund-ordning som vi gör, men kom ihåg att OpenCV lagrar bilder som NumPy-matriser. Som ett resultat måste vi ange värdena för y-axeln före x-axeln.

NumPy kräver följande fyra index för att utföra vår beskärning:

Starta y: Y-koordinaten i början. I det här fallet börjar vi vid y=35.

Slut y: Y-koordinaten i slutet. Vår skörd kommer att sluta när y = 90.

Start x: Skivans början x-koordinat. Skörden påbörjas vid x=35.

Slut x: Skivans x-axelkoordinat i slutet. Vid x=100 är vår skiva klar.

På liknande sätt beskär vi regionerna (23, 35) och (143, 148) från originalbilden för att extrahera hela kroppen från bilden på Linje 19 .

Du kan se att bilden har beskurits för att bara visa upp kroppen och ansiktet.

6. Ändra storlek på bild

Processen att öka eller minska en bilds bredd och höjd kallas skalning eller helt enkelt ändra storlek. Bildförhållandet, som är proportionen mellan en bilds bredd och dess höjd, bör beaktas när du ändrar storlek på en bild. Att försumma bildförhållandet kan resultera i att bilder som har skalats som verkar komprimerade och förvrängda:

Vår första bild är till vänster. Till höger ser du två bilder som har skalats utan att bibehålla bildförhållandet, vilket förvränger proportionen mellan bildens bredd och dess höjd. När du ändrar storlek på dina bilder bör du generellt överväga bildförhållandet.

Interpolationstekniken som används av vår storleksändringsalgoritm måste också beakta syftet med interpolationsfunktionen att använda dessa pixlar för att antingen öka eller minska bildens storlek.

I allmänhet är det mycket effektivare att krympa bildens storlek. Detta beror på att ta bort pixlar från en bild är allt som interpolationsfunktionen behöver göra. Å andra sidan skulle interpolationsmetoden behöva 'fylla i luckorna' mellan pixlar som tidigare inte fanns om bildstorleken skulle ökas.

Vi har vår originalbild till vänster. Bilden har reducerats till hälften av sin ursprungliga storlek i mitten, men förutom det har det inte skett någon förlust av bildens 'kvalitet'. Ändå har bildens storlek förbättrats avsevärt till höger. Det ser nu ut som 'sprängt' och 'pixlat'.

Som jag tidigare sa, vill du vanligtvis minska en bilds storlek snarare än att öka den. Genom att minska bildstorleken analyserar vi färre pixlar och måste hantera mindre 'brus', vilket gör bildbehandlingsalgoritmerna snabbare och mer exakta.

Translation och rotation är de två bildtransformationer som hittills behandlats. Vi ska nu undersöka hur man ändrar storlek på en bild.

Föga överraskande kommer vi att ändra storlek på våra bilder med metoden cv2.resize. Som jag indikerade tidigare måste vi ta hänsyn till bildens bildförhållande när vi använder den här metoden. Men innan vi går in för djupt i detaljerna, låt mig ge dig en illustration:

# python resize.py --image squirrel.jpg

# importerar de nödvändiga paketen

importera argparse

importera cv2

# skapa objektet för argument parser och analysera argumentet

apObj = argparse. ArgumentParser ( )

apObj. add_argument ( '-k' , '--bild' , nödvändig = Sann , hjälp = 'bildväg' )

argument = vars ( apObj. parse_args ( ) )

# ladda bilden och visa den på skärmen

bild = cv2. imread ( argument [ 'bild' ] )

cv2. imshow ( 'Original' , bild )

# För att förhindra att bilden ser skev ut, bildförhållande

# måste beaktas eller deformeras; därför tar vi reda på vad

# den nya bildens förhållande till den aktuella bilden.

# Låt oss göra bredden på vår nya bild 160 pixlar.

aspekt = 160,0 / bild. form [ 1 ]

dimensionera = ( 160 , int ( bild. form [ 0 ] * aspekt ) )

# den här raden visar faktiska storleksändringsoperationer

ändra storlek på bilden = cv2. ändra storlek ( bild , dimensionera , interpolation = cv2. INTER_AREA )

cv2. imshow ( 'Ändra storlek på bildbredd' , ändra storlek på bilden )

# Tänk om vi ville ändra bildens höjd? - använda

# samma princip, vi kan beräkna bildförhållandet baserat

# på höjd snarare än bredd. Låt oss göra skalan

# bilds höjd 70 pixlar.

aspekt = 70,0 / bild. form [ 0 ]

dimensionera = ( int ( bild. form [ 1 ] * aspekt ) , 70 )

# utför storleksändringen

ändra storlek på bilden = cv2. ändra storlek ( bild , dimensionera , interpolation = cv2. INTER_AREA )

cv2. imshow ( 'Ändra storlek på bildhöjd' , ändra storlek på bilden )

cv2. waitKey ( 0 )

Rad 1-14 , Efter att ha importerat våra paket och konfigurerat vår argumentparser kommer vi att ladda och visa vår bild.

Rad 20 och 21: Den relevanta kodningen börjar på dessa rader . Bildförhållandet måste beaktas när du ändrar storleken på den. Proportionen mellan bildens bredd och höjd kallas bildförhållandet.

Höjd bredd är bildförhållandet.

Om vi ​​inte tar hänsyn till bildförhållandet kommer resultaten av vår storleksändring att bli förvrängda.

Linje 20 , görs beräkningen av den ändrade storleken. Vi tillhandahåller bredden på vår nya bild som 160 pixlar i denna kodrad. Vi definierar helt enkelt vårt förhållande (aspectratio) som den nya bredden (160 pixlar) dividerat med den gamla bredden, som vi kommer åt med hjälp av bild, för att beräkna förhållandet mellan den nya höjden och den gamla höjden. form[1].

De nya dimensionerna av bilden på Linje 21 kan beräknas nu när vi vet vårt förhållande. Återigen kommer den nya bilden att ha en bredd på 160 pixlar. Efter att ha multiplicerat den gamla höjden med vårt förhållande och omvandlat resultatet till ett heltal, beräknas höjden. Vi kan behålla bildens ursprungliga bildförhållande genom att utföra denna operation.

Linje 24 det är där bilden verkligen ändras. Bilden vi vill ändra storlek på är det första argumentet, och det andra är dimensionerna vi beräknade för den nya bilden. Vår interpolationsmetod, som är algoritmen för att ändra storlek på den faktiska bilden, är den sista parametern.

Äntligen på Linje 25 , visar vi vår skalade bild.

Vi omdefinierar vårt förhållande (aspektratio) på Linje 31 . Höjden på vår nya bild kommer att vara 70 pixlar. Vi delar 70 med den ursprungliga höjden för att få det nya förhållandet mellan höjd och ursprunglig höjd.

Därefter fastställer vi den nya bildens dimensioner. Den nya bilden kommer att ha en höjd på 70 pixlar, vilket redan är känt. Vi kan återigen behålla bildens ursprungliga bildförhållande genom att multiplicera den gamla bredden med förhållandet för att producera den nya bredden.

Bilden ändras sedan i verkligheten Linje 35 , och den visas på Linje 36.

Här kan vi se att vi har minskat bredden och höjden på vår ursprungliga bild samtidigt som vi behåller bildförhållandet. Vår bild skulle verka förvrängd om bildförhållandet inte bibehölls.

Slutsats

I den här bloggen har vi studerat de grundläggande olika bildbehandlingskoncepten. Vi har sett bildöversättning med hjälp av OpenCV-paketet. Vi har sett metoderna för att flytta bilden upp, ner, höger och vänster. Dessa metoder är mycket användbara när vi skapar en datauppsättning med liknande bilder för att ge som en träningsdatauppsättning, så att maskinen kommer att se olika bilder även om de är samma. Den här artikeln lärde dig också hur du roterar en bild runt vilken punkt som helst i det kartesiska rymden med hjälp av en rotationsmatris. Sedan upptäckte du hur OpenCV roterar bilder med hjälp av denna matris och såg ett par illustrationer av snurrande bilder.

De två grundläggande (men signifikanta) bildaritmetiska operationerna addition och subtraktion undersöktes i detta avsnitt. Som du kan se är att addera och subtrahera grundläggande matriser alla bildarithmetiska operationer innebär.

Dessutom använde vi OpenCV och NumPy för att undersöka särdragen med bildaritmetik. Dessa begränsningar måste hållas i åtanke, annars riskerar du att få oväntade utfall när du utför aritmetiska operationer på dina bilder.

Det är viktigt att komma ihåg att även om NumPy utför en moduloperation och 'omsluter', skär OpenCV addition och subtraktion värden bortom intervallet [0, 255] för att passa inom intervallet. När du utvecklar dina egna datorvisionsapplikationer kommer du att komma ihåg detta hjälpa dig att undvika att jaga knepiga buggar.

Bildvändning är utan tvekan en av de enklare idéerna vi kommer att utforska i den här kursen. Flipping används ofta i maskininlärning för att generera fler träningsdataprover, vilket resulterar i mer potenta och tillförlitliga bildklassificerare.

Vi lärde oss också hur man använder OpenCV för att ändra storlek på en bild. Det är viktigt att ta hänsyn till både interpolationsmetoden du använder och bildförhållandet på din ursprungliga bild när du ändrar storlek på en så att resultatet inte ser förvrängt ut.

Slutligen är det viktigt att komma ihåg att om bildkvaliteten är ett problem är det alltid bäst att byta från en större till en mindre bild. I de flesta fall skapar förstoring av en bild artefakter och försämrar dess kvalitet.