CZĘŚĆ IIhome.agh.edu.pl › ~jsw › aipofm › opencvlab2.pdf · dilatation =...

Post on 06-Jul-2020

1 views 0 download

Transcript of CZĘŚĆ IIhome.agh.edu.pl › ~jsw › aipofm › opencvlab2.pdf · dilatation =...

Instalacja

pip install opencv-python

run pip install opencv-contrib-python

CZĘŚĆ II

Przydatne

Potrzebne importy: • import cv2 • import numpy as np

Odczyt, zapis i wyświetlanie obrazu: • img=cv2.imread('cell.jpg') • cv2.imwrite(‚new_image.jpg', img) • cv2.imshow('bin',img)

Operacje morfologiczne

Operacje morfologiczne pozwalają przeprowadzić zaawansowaną analizę kształtów poszczególnych obiektów w obrazie oraz na wyznaczenie ich wzajemnej odległości. Ważną cechą tych przekształceń jest ich łączność, która pozwala na generowanie skomplikowanych algorytmów analizy obrazu: • usuwanie szumu, • izolowanie obiektów, • ekstrakcja cech obiektów, • rozdzielanie i łączenie elementów

Operacje morfologiczne: erozja

• Erozja jest operacją odwrotną do dylatacji; wartość każdego piksela zamieniana jest na wartość lokalnego minimum wszystkich wartości pikseli, które obejmuje jądro transformacji.

• Erozję najczęściej stosuje się do usunięcia usterek obrazu, przykładowo w postaci zaszumienia typu „sól i pieprz” (pojedyncze punkty znikają w wyniku erozji, zaś większe struktury prezentujące wartościową część obrazu pozostają).

Operacje morfologiczne: dylatacja

Dylatacja stanowi splot obrazu ze zdefiniowanym jądrem; wartość każdego piksela zamieniania jest na wartość lokalnego maksimum wszystkich wartości pikseli, które obejmuje wspomniane jądro. Efektem dylatacji jest rozrost w obrazie wypełnionych (różnych ode 0) obszarów. Dylatacja powoduje rozszerzenie jasnych obszarów oraz wypełnianie zagłębień) a erozja ich zmniejszanie oraz likwidacje wypukłości. Ostateczny efekt działania obu operatorów zależy od wyboru jądra. Dylatację najczęściej stosuje się dla wyszukania połączonych składowych obrazu (dużych obszarów o podobnym poziomie intensywności lub barwie).

Erozja i dylatacja: obraz zbinaryzowany

#erozja erosion = cv2.erode(img,kernel,iterations = 1)

#dylatacja dilatation = cv2.dilate(img,kernel,iterations = 1)

kernel = np.ones((5,5),np.uint8)

Erozja i dylatacja: obraz w skali szarości

Gradient morfologiczny • Operacja gradientu morfologicznego polega na odjęciu od wyniku

dylatacji obrazu (nieznacznie zredukowanego) wyniku erozji obrazu (nieznacznie powiększonego). Fakt odjęcia od obrazu powiększonego obrazu pomniejszonego pozwala zachować ciągłość w przebiegu krawędzi, a tym samym może być wstępem do segmentacji obiektów.

• Skutkiem jest pozostawienie w obrazie przebiegu krawędzi i konturów obrazu oryginalnego.

• W przypadku obrazu monochromatycznego zastosowanie gradientu pozwala uzyskać informację o szybkości zmian w poziomie intensywności sąsiadujących pikseli.

gradient A = dilate A − erode(A)

• najczęściej stosowana jest do ekstrakcji krawędzi jasnych obszarów,

które w konsekwencji mogą być rozważane jako całe obiekty (lub fragmenty większych całości).

Otwarcie i zamknięcie

• Operację otwarcia (opening) i zamknięcia (closing) opierają się na złożeniu erozji i dylatacji, wykonanych sekwencyjnie:

opening A = dilate erode A

closing A = erode(dilate A ) • Operacje te nie ograniczają się jedynie do obrazów binarnych:

– operacja zamknięcia na obrazie monochromatycznym pozwala na wyeliminowanie z obrazu wartości mniejszych od swoich sąsiadów,

– operacja otwarcia- na wyeliminowanie wartości większych od tych w sąsiadujących pikselach.

Otwarcie i zamknięcie

• Głównym zastosowaniem operacji otwarcia jest zliczanie obszarów w obrazach binarnych. Przykładowo określając próg dyskryminacji dla komórek w obrazie mikroskopowym, przed przystąpieniem do ich zliczania poprzez otwarcie, można oddzielić komórki znajdujące się w bezpośrednim sąsiedztwie.

• Operacja zamknięcia stosuje się w przetwarzaniu obrazów przedstawiających złączone komponenty, celem usunięcia ich nadmiarowej liczby (przykładowo usunięcie segmentów powstałych z zaszumienia obrazu).

• Wynik operacji zamknięcia jest zbliżony do wyniku erozji, a wynik otwarcia do wyniku dylatacji. Otwarcie i zamknięcie pozwalają jednak lepiej zachować pole obszaru.

Otwarcie i zamknięcie

Otwarcie i zamknięcie: obraz zbinaryzowany

opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

Otwarcie i zamknięcie: obraz w skali szarości

TopHat i BlackHat

• Operatory tophat i blackhat służą odpowiednio ekstrakcji jasnych i ciemnych obszarów w obrazie (poziom jasności określany w odniesieniu do najbliższego otoczenia).

• Ekstrakcja obszarów jasnych odejmuje wynik operacji otwarcia (open) wykonanej na obrazie A od obrazu wejściowego A (nieprzetworzonego )

tophat A = A − open A • Ekstrakcja obszarów ciemnych: blackhat A = close A − A • podstawowym zastosowaniem obu operacji jest wyszczególnienie w

obrazie obszarów charakteryzujących się zmianą poziomu jasności w stosunku do obiektu z którym sąsiadują lub są związane (często spotykane w przypadku obrazów mikroskopowych)

TopHat i BlackHat: obraz zbinaryzowany

tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

TopHat i BlackHat: obraz w skali szarości

Dyskretna Transformata Fouriera

Funkcja cv2.dft implementuje algorytm szybkiej transformaty Fouriera zarówno dla sygnałów jedno- jak i dwuwymiarowych (w przypadku obrazów możliwe jest zarówno policzenie dyskretnej transformaty Fouriera dla całego obrazu jako sygnału 2D jak również potraktowanie każdego wiersza osobno jako sygnału jednowymiarowego).

Dyskretna Transformata Fouriera (DFT) img = cv2.imread('cell.jpg',0) f = np.fft.fft2(img) fshift = np.fft.fftshift(f) magnitude_spectrum = 20*np.log(np.abs(fshift))

Poszukiwanie wzorców (Template matching)

• Template matching to metoda wyszukiwania i znajdowania położenia zdefiniowanego wzorca (szablonu) w większym obrazie.

• W bibliotece OpenCV służy do tego funkcja cv2.matchTemplate(), która „przesuwa” szablon nad obrazem wejściowym (jak dla splotu maski i obrazu) z równoczesnym porównaniem szablonu i badanego fragmentu obrazu wejściowego.

Poszukiwanie wzorców (Template Matching)

import cv2 import numpy as np from matplotlib import pyplot as plt img_rgb = cv2.imread('cell.jpg') img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) template = cv2.imread('cell_temp.jpg',0) w, h = template.shape[::-1] res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED) threshold = 0.8 loc = np.where( res >= threshold) for pt in zip(*loc[::-1]): cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2) cv2.imwrite('res2.png',img_rgb)

Poszukiwanie wzorców (Template Matching)

Poszukiwanie wzorców (Template Matching)

Transformata Hougha (wykrywanie okręgów)

W matematyce koło jest reprezentowane równaniem:

(x − x0)2+(y − y

0)2= r2

gdzie: (x0,y0) reprezentuje współrzędne środka okręgu, zaś r jego promień. Równanie to zawiera 3 parametry, stąd obliczenie go wprost z transformaty Hougha wymagałoby implementacji silnika 3D. Biblioteka OpenCV do poszukiwania okręgów wykorzystuje metodę gradientową opartą na informacji o przebiegu krawędzi:

cv2.HoughCircles()

Transformata Hougha (wykrywanie okręgów)

Transformata Hougha (wykrywanie okręgów)

import cv2 import numpy as np img = cv2.imread('cell.jpg',0) img = cv2.medianBlur(img,5) cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,20, param1=100,param2=50,minRadius=15,maxRadius=50) circles = np.uint16(np.around(circles)) for i in circles[0,:]: # draw the outer circle cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2) # draw the center of the circle cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) cv2.imshow('detected circles',cimg) cv2.imwrite('circles5.jpg', cimg) cv2.waitKey(0) cv2.destroyAllWindows()

Transformata Hougha (wykrywanie okręgów)

Segmentacja (watershed)

img = cv2.imread('cell_gray.jpg') gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU) kernel = np.ones((3,3),np.uint8) # noise removal opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) sure_bg = cv2.dilate(opening,kernel,iterations=3) # sure background area # Finding sure foreground area dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5) ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0) sure_fg = np.uint8(sure_fg) # Finding unknown region unknown = cv2.subtract(sure_bg,sure_fg) ret, markers = cv2.connectedComponents(sure_fg) # marker labelling # Add one to all labels so that sure background is not 0, but 1 markers = markers+1 markers[unknown==255] = 0 # now, mark the region of unknown with zero markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] cv2.imwrite('wshed.jpg',img)

Rekonstrukcja obrazu (inpainting) • Rekonstrukcja metodą inpaintingu przeprowadzana jest

w przypadku zdjęć zawierających usterki, mogące wynikać choćby z zabrudzenia obiektywu lub uszkodzeń mechanicznych samego zdjęcia.

• Metoda ta opiera się na pobraniu informacji o kolorze i

teksturze zniszczonego fragmentu z jego krawędzi, a w dalszej kolejności powieleniu i „wymieszaniu” ich wartości.

• Biblioteka OpenCV daje możliwość zdefiniowania

promienia wokół odtwarzanego piksela, określającego zakres pikseli z których informacja będzie rekonstruowana.

Rekonstrukcja obrazu (inpainting)

• Metoda inpaintingu sprawdza się jedynie dla stosunkowo niewielkich obszarów uszkodzenia i z niezbyt zróżnicowaną teksturą (w przeciwnym razie rekonstrukcji może towarzyszyć efekt rozmycia). Metoda nie sprawdzi się również jeśli w brakującym fragmencie znajduje się cała struktura (brak możliwości odtworzenia z krawędzi obszaru).

• Biblioteka OpenCV oferuje 2 algorytmy inpaintingu dostępne jako argumenty funkcji cv2.inpaint():

• INPAINT_TELEA

• INPAINT_NS

Rekonstrukcja obrazu: INPAINT_TELEA (2004) • Algorytm oparty jest o Technikę Szybkiego Marszu (Fast Marching

Technique) • Dla każdego obszaru który ma być zrekonstruowany, algorytm startuje na

granicy zdefiniowanego sąsiedztwa i w kolejnych krokach wypełnia „do środka” wszystkie brakujące obszary.

• Nowa wartość każdego piksela stanowi średnią ważoną wartości pikseli w

otoczeniu o małym promieniu. • Kluczowym czynnikiem jest wybór wag: największe wagi

przyporządkowywane są pikselom w bezpośrednim sąsiedztwie wypełnianego piksela, oraz pikselom wyznaczającym kontur całego obszaru. Po zrekonstruowaniu wartości piksela algorytm przesuwa się do kolejnego, metodą szybkiego marszu.

• Metoda FMM zapewnia, iż w pierwszej kolejności rekonstruowane są piksele

leżące w bezpośrednim sąsiedztwie tych o znanej wartości

Rekonstrukcja obrazu: INPAINT_NS (2001) • Metoda Naviera-Stokesa • Algorytm oparty jest na dynamice płynów i wykorzystuje

równania różniczkowe cząstkowe. • Najpierw wędruje wzdłuż krawędzi od znanych regionów

do nieznanych regionów (warunek ciągłości krawędzi). • Algorytm analizuje linie łączące punkty o tej samej

intensywności, dopasowując wektory gradientowe na granicy odtwarzanego obszaru (wykorzystanie metod z dynamiki płynów). Po ich uzyskaniu kolor jest wypełniany w celu zmniejszenia minimalnej wariancji w tym obszarze

Rekonstrukcja obrazu (inpainting)

Rotacja rows,cols = img.shape M = cv2.getRotationMatrix2D((cols/2,rows/2),45,1) dst = cv2.warpAffine(img,M,(cols,rows))

Deskryptory W OpenCV wykonuje to funkcja cv2.goodFeaturesToTrack():

cv2.goodFeaturesToTrack(img, N, quality_level, euclid_dist) gdzie:

• img – obraz wejściowy (w skali szarości) • N- liczba poszukiwanych rogów • quality_level – współczynnik jakości z przedziału (0,1}> Najczęściej

przyjmuje się wartości z przedziału (0.01,0.1) • euclid_dist – minimalna odległość euklidesowa pomiędzy znalezionymi

rogami

Funkcja ta pozwala obliczyć operatory pochodnych, a następnie w toku analizy wybrać z ich listy drobne punkty do śledzenia oraz zdefiniować ich liczbę (N).

Deskryptory

import numpy as np import cv2 from matplotlib import pyplot as plt img = cv2.imread('squares2.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) corners = cv2.goodFeaturesToTrack(gray,25,0.01,10) corners = np.int0(corners) for i in corners: x,y = i.ravel() cv2.circle(img,(x,y),3,255,-1) cv2.imshow('bin',img) cv2.imwrite('descriptors.jpg',img)

Deskryptory