Systemy Wizyjne
Kurs OpenCV
Instrukcja 2
Przetwarzanie obrazu
Skala szarości
Binaryzacja
Filtracja
Histogram
Opracował:
Ziemowit Dworakowski
zdw@agh.edu.pl
Informacja o ćwiczeniu:
Ta instrukcja wprowadza informacje i funkcje służące do podstawowego przetwarzania
obrazów i filmów: Konwersję obrazu do skali szarości, binaryzację obrazu, wyznaczenie
histogramu obrazu oraz podstawowe filtry
Potrzebne funkcje:
W poniższej instrukcji należy skorzystać z bibliotek cv oraz highgui
Skala szarości
W celu konwersji obrazu kolorowego do skali szarości wykorzystujemy funkcję cvtColor, która
przyjmuje informację o obrazie źródłowym, obrazie wyjściowym oraz wykorzystanej funkcji.
Konwersja koloriwego obrazu
Mat frame;
do obrazu w skali szarości
Mat grayframe;
zostanie
wykonana za pomocą następującej linii:
cvtColor(frame,grayframe,CV_RGB2GRAY);
Binaryzacja obrazu
Binaryzacja obrazu w skali szarości wykonywana jest za pomocą funkcji threshold która przyjmuje
informację o obrazie źródłowym, wyjściowym, progu binaryzacji, maksymalnej wartości obrazu po
binaryzacji oraz rodzaju binaryzacji. Standardowa binaryzacja z progiem 125 obrazu
Mat grayframe
z zapisem go do obrazu
Mat grayframe
wykonana zostanie za pomocą następującej linii:
threshold(grayframe, binaryframe, 125, 255,0);
Podmieniając ostatni argument funkcji threshold uzyskujemy różne rodzaje binaryzacji. (Sprawdź w
tutorialu i przetestuj pozostałe sposoby binaryzacji!)
Histogram obrazu
Histogram pozwala w graficzny sposób przedstawić ilość poszczególnych kolorów lub poziomów
jasności na obrazie. Aby narysować histogram potrzebować będziemy Mat-pliku do
przechowywania wyniku, rozmiaru histogramu oraz zakresu danego kanału barwnego:
Mat hist;
int
histSize = 256;
float
range[] = { 0, 255 };
const
float
* histRange = { range };
W tym przykładzie wyznaczymy histogram obrazu uprzednio skonwertowanego na skalę szarości -
zawierającego tylko jeden kanał barwny - przechowujący informację o poziomie szarości każdego
piksela:
calcHist( &grayframe, 1, 0, Mat(), hist, 1, &histSize, &histRange, 1, 0 );
Powyższa funkcja wyznacza histogram dla klatki
Mat grayframe
, wynik zapisuje w obrazie
Mat
hist
. (Sprawdź w tutorialu co przekazywane jest do funkcji w pozostałych argumentach!)
Po wyznaczeniu hitogramu należy go wyświetlić. W tym celu tworzymy obraz a następnie w każdej
kolumnie obrazu rysujemy linię reprezentującą dany poziom szarości:
Mat histImage( histSize, 256, CV_8UC3, Scalar( 0,0,0) );
for
(
int
i = 1; i < histSize; i++ )
{
line( histImage,Point(i,255),Point(i,256-hist.at<
float
>(i)),Scalar(0,200,230),1,8);
}
Rozmywanie obrazu
W celu ograniczenia ilości szumów stosuje się rozmycie obrazu.
Rozmycie gaussowskie wykonujemy korzystając z funkcji przyjmującej obraz wejściowy,
wyjściowy oraz rozmiar maski wykorzystywanej w algorytmie - tutaj 5x5:
GaussianBlur( grayframe, filtered, Size( 5, 5 ), 0, 0 );
Filtry morfologiczne
W celu wykorzystania filtrów erozji, dylacji, otwarcia i zamknięcia trzeba najpierw określić maskę,
która zostanie wykorzystana w procesie filtracji. Maska powinna mieć kształt i rozmiar. W tym
przypadku korzystamy z maski prostokątnej o rozmiarach 4x4:
Mat kernel = getStructuringElement( MORPH_RECT, Size( 4, 4 ));
Po zdefiniowaniu maski wykonujemy filtrację poprzez wykorzystanie odpowiedniej funkcji z
argumentami: obraz wejściowy, obraz wynikowy, rodzaj filtracji, maska:
morphologyEx( frame, filtered, 0, kernel );
Rodzaje filtrów morfologicznych do wyboru:
0 - Erozja
1 - Dylatacja
2 - Otwarcie
3 - Zamknięcie
4 - Gradient
5 - Tophat
6 - Blackhat
Detekcja krawędzi
W celu wykrywania krawędzi na obrazie korzystać można z szeregu różnych filtrów. Filtry Sobel i
Scharr wyznaczają aproksymację dyskretnej pochodnej obrazu w dwóch kierunkach, ...
Poniżej przedstawiona jest implementacja funkcji Sobel i Scharr:
Scharr( grayframe, edgedetection, CV_8UC1, 1, 0, scale, 0, BORDER_DEFAULT );
Sobel( grayframe, edgedetection, CV_8UC1, 0, 1, 3,scale, 0, BORDER_DEFAULT );
Mat grayframe
to obraz wejściowy,
Mat edgedetection
to obraz wyjściowy,
CV_8UC1
oznacza głębię
kolorów, dwie kolejne liczby oznaczają kierunek filtracji. (Wykrywanie krawędzi pionowych lub
poziomych). (
int scale
) oznacza skalę. Sprawdź jakie efekty uzyskasz zmieniając głębię kolorów
na
CV_16UC1
Implementacja Laplasjanu wygląda następująco:
Laplacian(grayframe, edgedetection, CV_8UC1, kernel_size, scale, 0, BORDER_DEFAULT );
Jak poprzednio, argumentami funkcji są obraz wejściowy, wynikowy i głębia kolorów. Dodatkowo
zdefiniować należy rozmiar maski.(
int kernel_size
)
Detekcja krawędzi z zastosowaniem algorytmu Canny Edge Detection wykonywana jest komendą:
Canny(grayframe, edgedetection, 50, 150, kernel_size );
Argumentami funkcji są obraz wejściowy, obraz wynikowy, górny i dolny próg znajdowania
krawędzi oraz rozmiar maski.