używanie OpenCV i SVM z obrazami

Mam trudności z odczytaniem obrazu, wyodrębnieniem funkcji do treningu i testowaniem nowych obrazów w OpenCV przy użyciu maszyn SVM. czy ktoś może mi wskazać świetny link? W tej chwili można się spodziewać, że OpenCV będzie się rozwijał. Ale to nie pomaga w czytaniu w obrazach i nie jestem pewien, jak to włączyć.


Moim celem jest klasyfikacja pikseli w obrazie. Te piksele należą do krzywej. Rozumiem formowanie macierzy treningowej (dla instancja, obraz A 1,1 1,2 1,3 1,4 1,5 2,1 2,2 2,3 2,4 2,5 3,1 3,2 3,3 3,4 3,5

Uformowałbym swoją matrycę treningową jako [3][2]={ {1,1} {1,2} {1,3} {1,4} {1,5} {2,1} ..{} }

Jednak trochę się mylę co do etykiet. Z mojego zrozumienia, muszę określić, który wiersz (obraz) w macierzy treningowej odpowiada, co odpowiada krzywej lub nie-krzywej. Ale jak Mogę oznaczyć wiersz macierzy treningowej (obraz), jeśli niektóre piksele należą do krzywej, a niektóre nie należą do krzywej. Na przykład moja macierz treningowa to [3][2]={ {1,1} {1,2} {1,3} {1,4} {1,5} {2,1} ..{}}, piksele {1,1} i {1,4} należą do krzywej, ale reszta nie.

Author: ROMANIA_engineer, 2013-02-05

1 answers

Miałem do czynienia z tym niedawno, i oto co skończyło się zrobić, aby SVM do pracy dla obrazów.

Aby trenować maszynę SVM na zestawie obrazów, najpierw musisz skonstruować matrycę treningową dla maszyny SVM. Macierz ta jest określona w następujący sposób: każdy wiersz macierzy odpowiada jednemu obrazowi, a każdy element w tym wierszu odpowiada jednej funkcji klasy - w tym przypadku kolor piksela w określonym punkcie. Ponieważ twoje obrazy są 2D, musisz je przekonwertować na Matryca 1D. Długość każdego wiersza będzie obszarem obrazów (należy pamiętać, że obrazy muszą mieć ten sam rozmiar).

Załóżmy, że chciałeś trenować maszynę SVM na 5 różnych obrazach, a każdy obraz miał 4x3 piksele. Najpierw trzeba by zainicjować macierz treningową. Liczba wierszy w matrycy wynosiłaby 5, a liczba kolumn byłaby obszarem obrazu, 4*3 = 12.

int num_files = 5;
int img_area = 4*3;
Mat training_mat(num_files,img_area,CV_32FC1);

Idealnie, num_files i img_area nie byłyby zakodowane na twardo, ale uzyskane z zapętlenia przez katalog i licząc liczbę obrazów i biorąc rzeczywisty obszar obrazu.

Następnym krokiem jest "wypełnienie" wierszy training_mat danymi z każdego obrazu. Poniżej znajduje się przykład działania tego mapowania dla jednego wiersza.

Konwertuj matrycę obrazu 2D na matrycę 1D

Ponumerowałem każdy element macierzy obrazu z tym, gdzie powinien się udać w odpowiednim wierszu w macierzy treningowej. Na przykład, gdyby to był trzeci obraz, byłby to trzeci wiersz w macierzy treningowej.

Ty musiałby zapętlić każdy obraz i odpowiednio ustawić wartość w macierzy wyjściowej. Oto przykład dla wielu obrazów:

Macierz treningowa z wieloma obrazami

Jeśli chodzi o to, jak to zrobić w kodzie, możesz użyć reshape(), ale miałem z tym problemy ze względu na to, że macierze nie są ciągłe. Z doświadczenia wiem, że zrobiłem coś takiego:

Mat img_mat = imread(imgname,0); // I used 0 for greyscale
int ii = 0; // Current column in training_mat
for (int i = 0; i<img_mat.rows; i++) {
    for (int j = 0; j < img_mat.cols; j++) {
        training_mat.at<float>(file_num,ii++) = img_mat.at<uchar>(i,j);
    }
}

Zrób to dla każdego obrazu treningowego(pamiętając o zwiększeniu file_num). Następnie należy skonfigurować macierz treningową prawidłowo przejść do funkcji SVM. Reszta kroków powinna być bardzo podobna do przykładów online.

Należy pamiętać, że podczas tego procesu należy również skonfigurować etykiety dla każdego obrazu treningowego. Na przykład, jeśli klasyfikujesz oczy i nie-oczy na podstawie obrazów, musisz określić, który wiersz w macierzy treningowej odpowiada oku i nie-oku. Jest to określone jako macierz 1D, gdzie każdy element w macierzy 1D odpowiada każdemu wierszowi w macierzy 2D. Wybierz wartości dla każdej klasy (np. -1 dla non-eye i 1 dla eye) i ustawić je w macierzy etykiet.

Mat labels(num_files,1,CV_32FC1);

Więc jeśli trzeci element w tej macierzy labels był -1, to znaczy, że trzeci rząd w macierzy treningowej jest w klasie "nie-oka". Wartości te można ustawić w pętli, w której oceniany jest każdy obraz. Jedną z rzeczy, które możesz zrobić, to posortować dane treningowe w osobne Katalogi dla każdej klasy, i zapętlić obrazy w każdym katalogu i ustawić etykiety na podstawie katalog.

Następną rzeczą do zrobienia jest skonfigurowanie parametrów SVM. Wartości te będą się różnić w zależności od projektu, ale zasadniczo Można zadeklarować obiekt CvSVMParams i ustawić wartości:

CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::POLY;
params.gamma = 3;
// ...etc

W Internecie jest kilka przykładów, jak ustawić te parametry, jak w linku, który zamieściłeś w pytaniu.

Następnie tworzysz obiekt CvSVM i trenujesz go na podstawie swoich danych!

CvSVM svm;
svm.train(training_mat, labels, Mat(), Mat(), params);

W zależności od ilości danych, może to zająć dużo czasu. Po tym jak ukończone szkolenie, można jednak zapisać przeszkolony SVM więc nie trzeba przekwalifikować go za każdym razem.

svm.save("svm_filename"); // saving
svm.load("svm_filename"); // loading
Aby przetestować obrazy za pomocą wytrenowanej maszyny SVM, po prostu przeczytaj obraz, przekonwertuj go na matrycę 1D i przekaż go do svm.predict():
svm.predict(img_mat_1d);

Zwróci wartość na podstawie tego, co ustawisz jako etykiety (np. -1 lub 1, na podstawie powyższego przykładu moje oko/nie oko). Alternatywnie, jeśli chcesz przetestować więcej niż jeden obraz na raz, możesz utworzyć matrycę, która ma ten sam format co macierz treningowa zdefiniowana wcześniej i przekaż ją jako argument. Wartość zwracana będzie jednak inna.

Powodzenia!
 205
Author: Walfie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-04 21:53:20