использование OpenCV и SVM с изображениями
У меня возникли трудности с чтением изображения, извлечением функций для обучения и тестирования новых изображений в OpenCV с помощью SVMs. может кто-нибудь указать мне на отличную ссылку? Я посмотрел на введение OpenCV для поддержки векторных машин. Но это не помогает с чтением в изображениях, и я не уверен, как включить его.
мои цели-классифицировать пиксели в изображении. Эти пиксели будут принадлежать кривым. Я понимаю формирование обучения матрица (например,
образ
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
Мне бы образовать матрицу обучения как [3][2]={ {1,1} {1,2} {1,3} {1,4} {1,5} {2,1} ..{} }
тем не менее, я немного запутался в ярлыках. Из моего понимания я должен указать, какая строка (изображение) в обучающей матрице соответствует, что соответствует кривой или не кривой. Но, как я могу пометить строку обучающей матрицы (изображение), если есть несколько пикселей, принадлежащих кривая и некоторые не принадлежащие к кривой. Например, моя матрица обучения [3][2]={ {1,1} {1,2} {1,3} {1,4} {1,5} {2,1} ..{} }, пиксели {1,1} и {1,4} принадлежат кривой, а остальные-нет.
1 ответ:
мне пришлось иметь дело с этим в последнее время, и вот что я сделал, чтобы заставить SVM работать для изображений.
чтобы обучить SVM на наборе изображений, сначала вы должны построить обучающую матрицу для SVM. Эта матрица задается следующим образом: каждая строка матрицы соответствует одному изображению, а каждый элемент в этой строке соответствует одному объекту класса-в данном случае цвету пикселя в определенной точке. Так как ваши изображения 2D, вам нужно будет конвертировать их к 1D матрице. Длина каждой строки будет площадь изображения (обратите внимание, что изображения должны быть одинакового размера).
допустим, вы хотели обучить SVM на 5 разных изображениях, и каждое изображение было 4x3 пикселей. Сначала вам нужно будет инициализировать матрицу обучения. Количество строк в матрице будет равно 5, а количество столбцов - это площадь изображения, 4*3 = 12.
int num_files = 5; int img_area = 4*3; Mat training_mat(num_files,img_area,CV_32FC1);в идеале,
num_filesиimg_areaне будет жестко закодирован, но получен от циклического просмотра каталога и подсчета количества изображений и взятия фактической области изображения.следующий шаг - "заполнить" строки
training_matС данными от каждого изображения. Ниже приведен пример того, как это сопоставление будет работать для одной строки.
я пронумеровал каждый элемент матрицы изображения с тем, где он должен идти в соответствующей строке в обучающей матрице. Например, если бы это было третье изображение, это было бы третья строка в обучающей матрице.
вы должны были бы пройти через каждое изображение и установить значение в выходной матрице соответственно. Вот пример для нескольких изображений:
как вы могли бы сделать это в коде, вы могли бы использовать
reshape(), но у меня были проблемы с этим из-за того, что матрицы не являются непрерывными. По моему опыту я сделал что-то вроде этого: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); } }сделайте это для каждого тренировочного изображения (не забывая увеличивать
file_num). После этого вы должны правильно настроить свою матрицу обучения, чтобы перейти в функции SVM. Остальные шаги должны быть очень похожи на примеры онлайн.обратите внимание, что при этом вы также должны настроить метки для каждого обучающего изображения. Так, например, если вы классифицируете глаза и не-глаза на основе изображений, вам нужно будет указать, какая строка в обучающей матрице соответствует глазу и не-глазу. Это указывается как 1D Матрица, где каждый элемент в 1D матрице соответствует каждой строке в 2D матрице. Выберите значения для каждого класса (например, -1 для не-глаза и 1 для глаза) и установите их в матрице меток.
Mat labels(num_files,1,CV_32FC1);так что если 3-й элемент в этом
labelsматрица была -1, это означает, что 3-я строка в обучающей матрице находится в классе" без глаз". Вы можете установить эти значения в цикле, где вы оцениваете каждое изображение. Одна вещь, которую вы можете сделать, это отсортировать обучающие данные в отдельные каталоги для каждого класс, и цикл через изображения в каждом каталоге, и установить метки на основе каталога.следующее, что нужно сделать, это настроить параметры SVM. Эти значения будут варьироваться в зависимости от вашего проекта, но в основном вы объявите
CvSVMParamsобъект и установить значения:CvSVMParams params; params.svm_type = CvSVM::C_SVC; params.kernel_type = CvSVM::POLY; params.gamma = 3; // ...etcесть несколько примеров онлайн о том, как установить эти параметры, как в ссылке, которую вы разместили в вопросе.
Далее, вы создаете
CvSVMобъект и обучить его на основе по вашим данным!CvSVM svm; svm.train(training_mat, labels, Mat(), Mat(), params);в зависимости от того, сколько данных у вас есть, это может занять много времени. Однако после завершения обучения вы можете сохранить обученный SVM, поэтому вам не нужно каждый раз переучивать его.
svm.save("svm_filename"); // saving svm.load("svm_filename"); // loadingчтобы проверить свои изображения с помощью обученного SVM, просто прочитайте изображение, преобразуйте его в 1D матрицу и передайте ее в
svm.predict():svm.predict(img_mat_1d);он вернет значение, основанное на том, что вы установили в качестве своих меток (например, -1 или 1, на основе моего глаза / не-глаза пример выше). Кроме того, если вы хотите проверить несколько изображений одновременно, вы можете создать матрицу, которая имеет тот же формат, что и обучающая матрица, определенная ранее, и передать ее в качестве аргумента. Возвращаемое значение будет другим.
удачи!


Comments