- 1. Bitové operace a maskování
- 2. Konvoluce a rozmazání
- 3. Ostření - Obrácení rozostření obrazu
- 4. Threshoding (binarizace)
- 5. Dilatace, eroze, otevírání / zavírání
- 6. Detekce hran a přechody obrazu
- 14. Perspektivní a afinní transformace
- 8. Aplikace Live Sketch
V předchozích výukových programech jsme se dozvěděli o OpenCV a provedli jsme základní zpracování obrazu a v dalším tutoriálu jsme provedli nějakou manipulaci s obrázky v OpenCV, jako je oříznutí, rotace, transformace obrazu atd. Takže v pokračování předchozího tutoriálu Manipulace s obrázky se zde učíme některé další techniky manipulace s obrázky a na konci tutoriálu vytvoříme program python-opencv pro vytvoření živého náčrtu z živého přenosu webové kamery. Tato aplikace bude používat mnoho funkcí zpracování obrazu, které jsme se dosud naučili nebo se naučíme v tomto tutoriálu, takže to bude dobrý praktický příklad k pokrytí všech funkcí.
Jak bylo řečeno v předchozím tutoriálu, OpenCV je Open Source Commuter Vision Library, která má rozhraní C ++, Python a Java a podporuje Windows, Linux, Mac OS, iOS a Android. Lze jej tedy snadno nainstalovat na Raspberry Pi s prostředím Python a Linux. A Raspberry Pi s OpenCV a připojenou kamerou lze použít k vytvoření mnoha aplikací pro zpracování obrazu v reálném čase, jako je detekce obličeje, zámek obličeje, sledování objektu, detekce poznávací značky automobilu, domácí bezpečnostní systém atd.
V tomto tutoriálu uvidíme některé další manipulace s obrázky pomocí Python OpenCV. Zde se naučíme aplikovat následující funkci na obrázek pomocí Python OpenCV:
- Bitové operace a maskování
- Konvoluce a rozmazání
- Zaostření - obrácení rozostření obrazu
- Prahové hodnoty (binarizace)
- Dilatace, eroze, otevírání / zavírání
- Detekce hran a přechody obrazu
- Perspektivní a afinní transformace
- Živá skica aplikace
1. Bitové operace a maskování
Bitové operace vám pomohou při maskování obrázků a pomohou vám vytvořit několik jednoduchých obrázků.
Vytvoření čtverce
import cv2 import numpy jako np # používáme pouze dvě dimenze, protože se jedná o obrázek ve stupních šedi, pokud bychom použili # barevný obrázek, použili jsme pak obdélník = np.zeros ((300,300,3), np.uint8) # Vytvoření čtvercového čtverce = np.zeros ((300 300), np.uint8) cv2.rectangle (čtverec, (50,50), (250 250), 255, -1) cv2.imshow ("čtverec", čtverec) cv2. waitKey (0)
Vytváření elipsy
elipsa = np.zeros ((300 300), np.uint8) cv2.ellipse (elipsa, (150,150), (150,150), 30,0 180,255, -1) cv2.imshow ("elipsa", elipsa) cv2.waitKey (0)
Experimentování s bitovými operacemi
#AND_zobrazí se pouze tam, kde se tyto dva protínají
BitwiseAND = cv2.bitwise_and (čtverec, elipsa) cv2.imshow ("AND", BitwiseAND) cv2.waitKey (0)
#OR_shows pouze tam, kde je buď čtverec, nebo elipsa
BitwiseOR = cv2.bitwise_or (čtverec, elipsa) cv2.imshow ("OR", BitwiseOR) cv2.waitKey (0)
#XOR_shows pouze tam, kde oba existují samostatně
BitwiseXOR = cv2.bitwise_xor (čtverec, elipsa) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
# NOT_shows vše, co není součástí elipsy a operace NOT lze použít pouze na jednu postavu
BitwiseNOT_elp = cv2.bitwise_not (elipsa) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Konvoluce a rozmazání
Konvoluce je matematická operace provedena na dvou funkcí produkujících třetí funkci, která je zpravidla modifikovanou verzí původní funkci.
Výstupní obrázek = obrázek Funkce Velikost jádra
V počítačovém vidění používáme jádra k určení velikosti, nad kterou spustíme naši manipulační funkci nad naším obrazem.
Rozmazání je operace, při které průměrujeme pixely v oblasti (jádro)
OpenCV rozostří obraz použitím jader, jádro vám řekne, jak změnit hodnotu daného pixelu jeho kombinací s různým množstvím sousedních pixelů, které se jádro použije na každý pixel v obraze jeden po druhém, aby se vytvořil konečný obraz.
Jednoduše řečeno, obrazová konvoluce je jednoduše elementární násobení dvou matic následované součtem.
Můžeme to jednoduše pochopit na následujícím příkladu.
Výše uvedené je jádro 3X3.
Násobíme 1/25, abychom normalizovali, tj. Součet na 1 jsme zvyšovali intenzitu nebo snižovali intenzitu jako v případě zesvětlení nebo ztmavení obrázků.
Pojďme zkouška OpenCV rozmazání metodu filter2D, daná funkce cv2.filter2D (image, -1, kernel)
import cv2 import numpy jako np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', obrázek) cv2.waitKey (0)
# vytvoření matice jádra 3x3
kernel_3x3 = np.ones ((3,3), np.float32) / 9
# používáme cv2.filter2D k propojení jádra s obrázkem
blurred = cv2.filter2D (image, -1, kernel_3x3) cv2.imshow ('3x3_blurring', blurred) cv2.waitKey (0)
# vytvoření matice jádra 7x7
kernel_7x7 = np.ones ((7,7), np.float32) / 49
# používáme cv2.filter2D k propojení jádra s obrázkem
blurred = cv2.filter2D (image, -1, kernel_7x7) cv2.imshow ('7x7_blurring', blurred) cv2.waitKey (0) cv2.destroyAllWindows ()
Existují i jiné typy metod rozmazání:
cv2.blur - Zprůměruje hodnotu přes zadané okno.
cv2.GaussianBlur - Podobné, ale používá Gaussovo okno (větší důraz na body kolem středu).
cv2.medianBlur– Používá medián všech prvků v okně.
cv2.bilateralFilter– Rozostří při zachování ostrých hran, zachová hrany a detaily čar.
Níže uvidíme jeden po druhém, nejprve zobrazíme původní obrázek pomocí níže uvedeného kódu:
import cv2 import numpy jako np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', obrázek) cv2.waitKey (0)
cv2.blur:
V této metodě se zprůměrování provádí sloučením obrazu s filtrem normalizovaného boxu, to zaujme místo pod boxem a nahradí centrální prvek. Zde musí být velikost krabice lichá a pozitivní .
# cv2.blur blur = cv2.blur (obrázek, (3,3)) cv2.imshow ('Průměrování', rozmazání) cv2.waitKey (0)
cv2.Gaussian Blur:
# cv2.GaussianBlur # místo boxového filtru, zkusme Gaussovo jádro Gaussian = cv2.GaussianBlur (obrázek, (7,7), 0) cv2.imshow ('Gaussian Bluring', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Trvá to medián všech pixelů pod oblastí jádra a centrální prvek je nahrazen touto hodnotou mediánu.
# cv2.medianBlur # vezme medián všech pixelů pod oblastí jádra a centrální prvek # je nahrazen touto střední hodnotou. střední hodnota = cv2.medianBlur (obrázek 5) cv2.imshow ('medián rozmazání', medián) cv2.waitKey (0)
cv2.bilateralFilter:
Bilaterální je velmi účinný při odstraňování šumu při zachování ostrých hran
# cv2.bilaterálníFilter #Bilaterální je velmi účinný při odstraňování šumu při zachování ostrých hran bilaterálních = cv2.bilateralFilter (obrázek, 9,75,75) cv2.imshow ('bilaterální rozmazání', bilaterální) cv2.waitKey (0) cv2. destruAllWindows ()
Odhlučení obrazu bez lokálního znamená Denoising
import cv2 import numpy jako np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', obrázek) cv2.waitKey (0)
#parameter after None is the filter strength 'h' (5-10 is a good range) # next is h for color components, set the same value as h again
dst = cv2.fastNlMeansDenoisingColored (obrázek, žádný, 6,6,7,21) cv2.imshow ('Fast znamená denois', dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Existují 4 variace odminování jiných než místních prostředků
cv2.fastNlMeansDenoising () - pro jeden obrázek v šedé stupnici
cv2.fastNlMeansDenoisingColored () - jednobarevný obrázek
cv2.fastNlmeansDenoisingMulti () - pro stupně šedi v pořadí obrázků
cv2.fastNlmeansDenoisingcoloredMulti () - pro barevnou sekvenci obrázků
3. Ostření - Obrácení rozostření obrazu
Ostření je opakem rozmazání, zesiluje nebo zdůrazňuje okraje obrazu.
Jádro =,,
Naše matice jádra má součet do jedné, takže není nutné ji normalizovat (tj. Vynásobit faktorem na stejnou jasnost jako u původní), pokud není jádro normalizováno na 1, obraz by byl světlejší nebo tmavší.
import CV2 import numpy jako np obrázek = cv2.imread ('') elephant.jpg cv2.imshow ('původní', obraz) cv2.waitKey (0)
kernel_sharpening = np.array (,
])
# použití ostření jádra na vstupní obrázek
zostřený = cv2.filter2D (obrázek, -1, kernel_sharpening) cv2.imshow ('naostřený obrázek', naostřený) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Threshoding (binarizace)
Prahová hodnota je akt převodu obrazu do binární formy. V opencv je samostatná funkce pro prahování definována jako
Cv2.threshold (obrázek, prahová hodnota, maximální hodnota, typ prahové hodnoty)
Existují následující typy prahových hodnot:
- cv2.THRESH_BINARY - nejběžnější
- cv2. THRESH_BINARY_INV - nejběžnější
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
POZNÁMKA: Před prahováním je třeba obrázek převést na stupně šedi
import CV2 import numpy jako NP #load obrázek ve stupních šedi obrazu = cv2.imread ('gradient.jpg', 0) cv2.imshow ('původní', obraz) cv2.waitKey (0)
#hodnota pod 127 přejde na 0 (černá) a nad 127 přejde na 255 (bílá)
_, thresh1 = cv2.threshold (obrázek, 127 255, cv2.THRESH_BINARY) cv2.imshow ('1 práh', thresh1) cv2.waitKey (0)
#value below 127 goes to 255 and values above 127 goes to 0 (rub of above)
_, thresh2 = cv2.threshold (obrázek, 127 255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 threshold', thresh2) cv2.waitKey (0)
#value above 127 are truncated (held) at 127, the 255 argument is unused.
_, thresh3 = cv2.threshold (obrázek, 127 255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc', thresh3) cv2.waitKey (0)
#hodnoty pod 127 jde na 0, nad 127 se nemění
_, thresh4 = cv2.threshold (obrázek, 127 255, cv2.THRESH_TOZERO) cv2.imshow ('4 threshold', thresh4) cv2.waitKey (0)
#Revesrse výše, pod 127 se nemění, nad 127 jde na nulu
_, thresh5 = cv2.threshold (obrázek, 127 255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 threshold', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Dilatace, eroze, otevírání / zavírání
Jedná se o operace v oblasti matematické morfologie
Dilatace - přidává pixely na hranice objektu v obraze.
Eroze - Odstraní pixely na hranicích objektu v obrázku.
Otevření - Eroze následovaná dilatací.
Uzavření - dilatace následovaná erozí.
Otevírání je velmi užitečné pro odšumění obrázků, protože nejprve ztenčí obraz erozí (odstraní šum) a poté jej rozšíří.
Zmatek s dilatací a erozí
Někdy dochází k záměně mezi dilatací a erozí obvykle u obrázků s bílým pozadím, protože opencv považuje bílé pozadí za obrázek, který má být rozšířen nebo erodován místo původního obrázku, takže v tomto případě eroze funguje jako dilatace a naopak, jak je ukázáno na ukázce obrázku je uvedeno níže.
Nezapomeňte, že dilatace přidává pixely na hranice objektů v obraze, zatímco eroze odstraňuje pixely na hranicích objektů v obraze
import cv2 import numpy jako np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
#Eroze
# Pojďme definovat naši velikost jádra
jádro = np.ones ((5,5), np.uint8)
# teď obrázek erodujeme, zde není iterace, kdy chcete obrázek erodovat
eroze = cv2.erode (obrázek, jádro, iterace = 1) cv2.imshow ('Eroze', eroze) cv2.waitKey (0)
# dilatace
dilatace = cv2.dilate (obrázek, jádro, iterace = 1) cv2.imshow ('dilatace', dilatace) cv2.waitKey (0)
#otevření, Dobré pro odstranění hluku
opening = cv2.morphologyEx (obrázek, cv2.MORPH_OPEN, jádro) cv2.imshow ('otevření', otevření) cv2.waitKey (0)
#closing, Dobré pro odstranění hluku
zavírání = cv2.morphologyEx (obrázek, cv2.MORPH_CLOSE, jádro) cv2.imshow ('zavírání', zavírání) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Detekce hran a přechody obrazu
Detekce hran je v počítačovém vidění velmi důležitou oblastí, zejména při práci s obrysy.
Okraje lze definovat jako hranice obrazu, ve skutečnosti jsou to hrany, které definují objekt v obrazech, zachovávají mnoho informací o obrázku.
Formálně lze hrany definovat jako náhlé změny (diskontinuity) v obraze a mohou kódovat tolik informací jako pixely.
Výše uvedený obrázek ukazuje, jak počítačové vidění identifikuje a rozpoznává obraz.
Algoritmy detekce hran: - Existují tři hlavní typy algoritmů detekce hran
- Sobel - pro zdůraznění vertikálních nebo horizontálních obrázků.
- Laplacian - optimální díky nízké chybovosti, dobře definovaným hranám a přesné detekci.
- Algoritmus detekce Canny Edge (vytvořený Johnem F. Cannym v roce 1986)
1. Aplikuje Gaussovo rozostření
2. Vyhledá gradient intenzity obrazu
3. aplikuje non-maximální potlačení (tj. Odstraní pixely, které nejsou hranami).
4. Hystereze aplikuje prahovou hodnotu (tj. Pokud je pixel v horní a dolní prahové hodnotě, považuje se to za hranu)
import cv2 import numpy jako np image = cv2.imread ('input.jpg', 0) výška, šířka = image.shape
#sobel
#extrahování okrajů sobel
sobel_x = cv2.Sobel (obrázek, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (obrázek, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('originál', obrázek) cv2.waitKey (0) cv2.imshow ('sobelx', sobel_x) cv2.waitKey (0)
#Sobely
cv2.imshow ('sobely', sobel_y) cv2.waitKey (0)
sobel_OR = cv2.bitwise_or (sobel_x, sobel_y) cv2.imshow ('sobelOR', sobel_OR) cv2.waitKey (0)
#laplaian
laplacian = cv2.Laplacian (obrázek, cv2.CV_64F) cv2.imshow ('Laplacian', laplacian) cv2.waitKey (0)
Algoritmus #canny edge detection používá hodnoty gradientu jako prahové hodnoty # v
canny musíme zadat dvě hodnoty: threshold1 a threshold2.
# jakýkoli přechod větší než prahová hodnota 2 je považován za okraj.
# jakýkoli přechod větší než prahová hodnota 1 se nepovažuje za hranu.
#values v mezi prahem 1 a prahu 2 jsou buď jako okraj nebo non-hrana
#on, jak jsou spojeny jejich intenzity, v tomto případě všechny hodnoty pod 60 jsou považovány za
#non okrajích wheareas libovolnou hodnotu vyšší než 120 ° C jsou považovány za hrany.
canny = cv2.Canny (obrázek, 60 120) cv2.imshow ('canny', canny ) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Perspektivní a afinní transformace
Vraťme se o krok zpět a podívejme se na afinní a neafinické transformace, původní obrázek zobrazený níže je zjevně neafinický, protože hrany se v určitém okamžiku setkají, nicméně můžeme jej narovnat pokřivením a pohledem přeměnit.
Pro tuto perspektivní transformaci potřebujeme čtyři souřadnice původního obrazu a poté čtyři body výstupního obrazu, které jsou označeny body_A a body_B. Nejprve pomocí těchto bodů spočítáme transformační matici M pomocí funkce getPerspectiveTransform.
A pak je tato matice dána funkci warpPerspective k vygenerování konečného výstupu.
Pojďme si nejprve vyzkoušet perspektivní transformaci.
import cv2 import numpy jako np import matplotlib.pyplot jako plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# koordinátor 4 rohů původního obrázku
points_A = np.float32 (,,,])
# souřadnice 4 rohů požadovaného výstupu
# používáme poměr papíru A4 1: 1,41
points_B = np.float32 (,,,])
#použijte dvě sady dvou bodů k výpočtu matice předpokládané transformace, M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (image, M, (420 594)) cv2.imshow ('warpprespective', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()
Affine transformace je snazší než non-afinní transformace, protože k získání transformace potřebujeme jen tři body. Celý proces jde stejně, ale místo perspektivní transformace máme nyní afinní transformaci a také definujeme cols a řádky v warpAffine z tvarové funkce namísto ručního zadání.
import cv2 import numpy jako np import matplotlib.pyplot jako plt image = cv2.imread ('box.jpg') řádky, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
# koordinátor 3 rohů původního obrázku
points_A = np.float32 (,,])
# souřadnice 3 rohů požadovaného výstupu
# používáme poměr papíru A4 1: 1,41
points_B = np.float32 (,,])
#použijte dvě sady dvou bodů k výpočtu afinní
# transformační matice, M.
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (image, M, (cols, lines)) cv2.imshow ('warpaffine', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Aplikace Live Sketch
Nejprve si po přečtení všech výše uvedených funkcí pro manipulaci s obrázky gratulujte, že jste se k tomuto mini projektu přidali. Takže v tomto mini projektu Pythonu OpenCV se naučíme některé nové koncepty smyček a funkcí. Pokud jste obeznámeni s programováním, musíte mít širší představu o tom, jaké jsou funkce a smyčky. V pythonu však základní koncept smyček a funkcí zůstává stejný, ale způsob jejich definování se trochu mění.
Na začátku tohoto programu tedy můžeme vidět určitou skupinu příkazů směřujících pod „ def skica (obrázek): “ toto je formální definice funkce skupiny příkazů spolupracujících pro určitý výstup.
Tento náčrt je tedy funkcí, v pythonu je funkce definována znakem „def“ a končí značkou „:“. Také příkazy, které musí být uvnitř funkce nebo můžete říci, které jsou vyžadovány pro správnou funkci, jsou funkcí automaticky zarovnány na stranu. Takže aby vyšly z funkcí, musely být příkazy úplně zarovnány doleva. Další odkazy najdete na google o tom, jak jsou funkce definovány v pythonu.
Takže v této funkci náčrtu jsme zavedli několik vrstev zpracování obrazu, které se spojily a poskytly výstup. Nejprve se obrázek převede na stupně šedi, aby jej mohl opencv snadno zpracovat, a poté se na obraz v šedé stupnici aplikuje Gaussovo rozostření, aby se snížil šum. Pak se hrany extrahují pomocí algoritmu detekce hran cannyho, pak se na obraz definovaný hranou aplikuje binární inverze, zde by binární inverzi mohl provést také bitwise_NOT, ale my jsme záměrně vybrali tuto prahovou binární inverzi, protože dává svobodu nastavovat jeho parametry, dokud nezískáme jasný obraz.
Všimněte si také, že funkce vezme obraz argumentů a vrátí dva argumenty ret a mask. Zatímco ret je Boolean, který říká, že funkce je úspěšně spuštěna nebo ne, a maska je konečným výstupem funkce, tj. Zpracovaného obrazu.
Pak druhý koncept operačního webové kamery v OpenCV, která se provádí pomocí cv2.VideoCapture (0) funkce, která ukládá obrázek do objektu víčkem , které cap lze číst s cap.read () funkce, i zde si uvědomit, že víčko. read () je uvnitř nekonečné smyčky while, protože neustále musel pořizovat obrázky, aby mu poskytlo pocit živého videa, kde snímková frekvence videa bude snímková frekvence vaší webové kamery, která je většinou mezi 24 až 60 fps.
cap.read () vrací ret a frame, kde ret je Boolean, což značí, že funkce byla úspěšně spuštěna nebo ne, a frame obsahuje obrázek pořízený webovou kamerou.
Níže je uveden kompletní Python OpenCV kód pro spuštění Live Sketch
import CV2 import numpy jako NP funkce #sketch generování def nákres (obrázek): #convert obraz ve stupních šedé img_gray = cv2.cvtColor (obraz, cv2.COLOR_BGR2GRAY) #cleaning tvoří obraz pomocí Gaussovo rozostření img_gray_blur = cv2.GaussianBlur (img_gray, (5,5), 0) #extract edge canny_edges = cv2.Canny (img_gray_blur, 10,70) #do invert binarize the image ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) return mask #initialize webcam, cap je objekt poskytovaný zachycením videa # obsahuje Boolean označující, zda byl úspěšný (ret) #it také obsahuje obrázky shromážděné z webové kamery (rám) cap = cv2.VideoCapture (0), zatímco True: ret, frame = cap.read () cv2.imshow ('livesketcher', skica (rám)), pokud cv2.waitKey (1) == 13: # 13 je enterkey break #release camera a zavřete okno, nezapomeňte uvolnit webovou kameru pomocí cap.release () cap.release () cv2.destroyAllWindows ()
Tímto končí část 2 manipulace s obrázky v Pythonu-OpenCV. Chcete-li dobře porozumět počítačovému vidění a OpenCV, projděte si předchozí články (Začínáme s Python OpenCV a manipulací s obrázky v Pythonu OpenCV (část 1)) a pomocí počítačového vidění si budete moci vytvořit něco skvělého.