Подтвердить что ты не робот

Используя OpenCV и SVM с изображениями

У меня возникают трудности с чтением изображения, извлечением функций для обучения и тестированием новых изображений в OpenCV с использованием SVM. может кто-нибудь, пожалуйста, укажите мне отличную ссылку? Я рассмотрел OpenCV Введение в поддержку векторных машин. Но это не помогает при чтении изображений, и я не уверен, как его включить.


Большое спасибо за объяснение. Мои цели - классифицировать пиксели в изображении. Эти пиксели будут принадлежать кривым. Я понимаю формирование учебной матрицы (например, изображение 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

Я бы сформировал свою обучающую матрицу как [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} принадлежат кривой, а остальные - нет.

Большое спасибо -

4b9b3361

Ответ 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 данными из каждого изображения. Ниже приведен пример того, как это сопоставление будет работать для одной строки.

Convert 2D image matrix to 1D matrix

Я пронумеровал каждый элемент матрицы изображения, где он должен идти в соответствующей строке в обучающей матрице. Например, если это было третье изображение, это будет третья строка в обучающей матрице.

Вам нужно будет прокрутить каждое изображение и соответственно установить значение в выходной матрице. Вот пример для нескольких изображений:

Training matrix with multiple images

Что касается того, как вы это сделаете в коде, вы можете использовать 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, на основе моего примера eye/non-eye выше). В качестве альтернативы, если вы хотите протестировать несколько изображений за раз, вы можете создать матрицу, которая имеет тот же формат, что и ранее разработанная матрица обучения, и передать ее как аргумент. Возвращаемое значение будет отличаться.

Удачи!