Длина каждого ряда обучающей матрицы для SVM

Я нашел отличный / исчерпывающий пост / ответ, связанный с этой темой здесь использование OpenCV и SVM с изображениями. Однако у меня есть несколько вопросов, которые я хотел бы уточнить из ответа в ссылке. (так как у меня недостаточно репутации, чтобы написать комментарий).

Что я делал:
Я использую OpenCV SVM для обучения. Функции, используемые для обучающей матрицы, получаются путем вычисления нормированных средних значений R, G и B для каждого изображения. Таким образом, в обучающей матрице имеется 4 столбца в каждой строке (или в каждом изображении). Эти столбцы соответствуют метки (1 или 0), **** нормализованное среднее значение в r канале ****, г а также б канал.

Кстати, мой исходный обучающий файл — это текстовый файл, который я все равно преобразую в float [] [] и даже в объект Mat для подачи в SVM opencv. вот как выглядит файл:

1 0,267053 0,321014 0,411933
1 0,262904 0,314294 0,422802
.
.
0 0,29101 0,337208 0,371782
0 0,261792 0,314494 0,423714

По-видимому, это противоречит утверждению по ссылке, в котором говорится, что размер каждого ряда должен быть эквивалентен размер изображения. Это протокол или какое-то правило? Я просто не могу понять, почему это должно (если это так).

Мой вопрос, При построении обучающей матрицы должна ли длина каждой строки соответствовать площади или размеру изображения? Где, как и в тренировочной матрице, длина каждой строки равна 4. Это неправильно?

Кроме того, достаточно ли иметь только 3 функции (3 столбца) для обучения для классификации / для SVM? Пожалуйста, направьте меня на правильный путь, я сомневаюсь, стоит ли мне продолжать это или есть какой-то другой лучший подход к проблеме.

Я надеюсь, что смогу понять больше концепций, стоящих за шагами SVM. Статьи или связанные образцы будут оценены!

0

Решение

Размер каждой строки не должен быть эквивалентным размеру изображения. Это зависит от того, что у вас есть для функций. Использование средних значений для классификации изображений недостаточно. Просто подумайте о том, как вы классифицируете объекты, когда смотрите на картинку. Вы не вычисляете средние значения, но, вероятно, смотрите на контуры, связанные области, иногда отдельные значения пикселей на фоне обработки мозга.

Итак, чтобы получить больше возможностей, у меня есть предложение для вас. Рассчитать среднее значение каждого столбца для части извлечения объекта. Это будет более полезным, вероятно.

А для извлечения другой функции вы можете использовать PCA. Обычно вы можете указать все значения в пикселях подряд для обучения SVM, но даже для 200 * 200 изображений это дает 40 000 функций, ВАУ, а это очень много. Вам нужно уменьшить это измерение функции, не теряя много информации, это означает сохранение приемлемого процента отклонения. Таким образом, PCA используется для этого, уменьшая размер пространства признаков и сохраняя дисперсию с приемлемой скоростью.

Я постараюсь показать вам, как вы можете уменьшить функциональное пространство с PCA. Сначала вам нужно получить изображения, а затем свернуть изображения в переменную Mat, строка за строкой:

Чтение CSV:

void read_csv (константная строка имя файла, вектор изображения, вектор метки, разделитель символов = ';')
{
файл std :: ifstream (filename.c_str (), ifstream :: in);
если (! файл)
{
string error_message = "Не указан правильный входной файл, проверьте указанное имя файла.";
CV_Error (1, error_message);
}
строка строки, путь, классная метка;
while (getline (файл, строка))
{
струнная лень (линия);

getline (лень, путь, разделитель);
getline (liness, classlabel);

если (! path.empty ()  ! Classlabel.empty ())
{
Mat im = imread (путь, 0);

images.push_back (им);
labels.push_back (atoi (classlabel.c_str ()));
}
}
}

Прокручивание изображений строка за строкой:

Mat rollVectortoMat(const vector<Mat> &data) // data is vector of Mat images
{
Mat dst(static_cast<int>(data.size()), data[0].rows*data[0].cols, CV_32FC1);
for(unsigned int i = 0; i < data.size(); i++)
{
Mat image_row = data[i].clone().reshape(1,1);
Mat row_i = dst.row(i);
image_row.convertTo(row_i,CV_32FC1, 1/255.);
}
return dst;
}

ГЛАВНЫЙ

int main()
{

PCA pca;

vector<Mat> images_train;
vector<Mat> images_test;
vector<int> labels_train;
vector<int> labels_test;

read_csv("train1k.txt",images_train,labels_train);
read_csv("test1k.txt",images_test,labels_test);

Mat rawTrainData = rollVectortoMat(images_train);
Mat rawTestData  = rollVectortoMat(images_test);

Mat trainLabels = getLabels(labels_train);
Mat testLabels  = getLabels(labels_test);

int pca_size = 500;

Mat trainData(rawTrainData.rows, pca_size,rawTrainData.type());
Mat testData(rawTestData.rows,pca_size,rawTestData.type());pca(rawTrainData,Mat(),CV_PCA_DATA_AS_ROW,pca_size);

for(int i = 0; i < rawTrainData.rows ; i++)
pca.project(rawTrainData.row(i),trainData.row(i));

for(int i = 0; i < rawTestData.rows ; i++)
pca.project(rawTestData.row(i),testData.row(i));

}

Подводя итог, вы читаете CSV-файл, который похож на image_path; метка. Чем вы катите изображения в переменную Mat, строка за строкой. Вы применяете PCA, чтобы уменьшить до 500 функции. Я применил это сокращение PCA, чтобы уменьшить 200 * 200 изображений (40000 функций) до 500 размеров объектов. Чем я применил MLP, чтобы классифицировать это. Эти переменные testData и trainData могут также использоваться с SVM. Вы также можете проверить, как тренировать его с MLP в моем SO сообщении:

Сигмоидальный выход OpenCV Neural Network

2

Другие решения

Если каждый пиксель изображения — это элемент, с которым вы хотите обучить SVM, то в каждой строке должны быть перечислены все элементы и, следовательно, все пиксели. В вашем случае, кажется, что у вас есть только 3 функции на изображение (в среднем R, G, B), поэтому не должно быть никаких проблем.

Конечно, вы можете отлично тренировать SVM в 3-х измерениях. Но игнорируя SVM, является ли средний цвет даже разумной метрикой для ваших изображений?

1

По вопросам рекламы [email protected]