Перейти к содержимому
Compvision.ru
ProgRoman

PCA

Recommended Posts

Сейчас реализую PCA для распознавания(применяю его для сокращения размерности) так как дескрипторы могут получаться довольно большими :) поискал в интернете примеры есть вот вставлю один из примеров использования класса PCA

я брал за основу этот постPCA-opencv как оказалось ссылка http://www.bytefish.de/blog/pca_in_opencv довольно хорошо описывает

но тем не менее возникли вопросы по коду вставлю его ниже



Mat normalize(const Mat& src) 

{

    Mat srcnorm;

    normalize(src, srcnorm, 0, 255, NORM_MINMAX, CV_8UC1);


    return srcnorm;

}



int main(int argc, char* argv[])

{

	string pathD = "E:\\Projects\\ComputerVision\\Data_bases\\att_faces\\";


	vector<Mat> db;


    // load greyscale images (these are from http:// www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html)

    db.push_back(imread(pathD+"s1\\1.pgm",0));

    db.push_back(imread(pathD+"s1\\2.pgm",0));

    db.push_back(imread(pathD+"s1\\3.pgm",0));


    db.push_back(imread(pathD+"s2\\1.pgm",0));

    db.push_back(imread(pathD+"s2\\2.pgm",0));

    db.push_back(imread(pathD+"s2\\3.pgm",0));


    db.push_back(imread(pathD+"s3\\1.pgm",0));

    db.push_back(imread(pathD+"s3\\2.pgm",0));

    db.push_back(imread(pathD+"s3\\3.pgm",0));


    db.push_back(imread(pathD+"s4\\1.pgm",0));

    db.push_back(imread(pathD+"s4\\2.pgm",0));

    db.push_back(imread(pathD+"s4\\3.pgm",0));

	Mat i1 = imread(pathD+"s4\\5.pgm",0).reshape(1,1).row(0);

	Mat imt;

	i1.convertTo(imt, CV_32FC1, 1/255.);


    int total = db[0].rows * db[0].cols;


    // build matrix (column)

    Mat mat(db.size(), total, CV_32FC1);

    for(int i = 0; i < db.size(); i++) 

	{

        Mat X = mat.row(i);

        db[i].reshape(1, 1).row(0).convertTo(X, CV_32FC1, 1/255.);

    }


    // Change to the number of principal components you want:

    int numPrincipalComponents = 12;


    // Do the PCA:

	PCA pca(mat, Mat(), CV_PCA_DATA_AS_ROW, numPrincipalComponents);



	Mat im_pr = pca.project(imt);// это как я понимаю я просто проецирую входное изображение на базис построенный по всей базе

    // Create the Windows:

    namedWindow("avg", 1);

    namedWindow("pc1", 1);

    namedWindow("pc2", 1);

    namedWindow("pc3", 1);


    // Mean face:

    imshow("avg", pca.mean.reshape(1, db[0].rows));


    // First three eigenfaces:

    imshow("pc1", normalize(pca.eigenvectors.row(0)).reshape(1, db[0].rows));

    imshow("pc2", normalize(pca.eigenvectors.row(1)).reshape(1, db[0].rows));

    imshow("pc3", normalize(pca.eigenvectors.row(2)).reshape(1, db[0].rows));


    // Show the windows:

    waitKey(0);	

    return 0;

}

вопросы такие как я понимаю проецирование тут ведётся на всю базу т.е. можно потом будет сравнивать как далеко данный вектор находится от вектора лица(обобщёного лица), а что бы распознавать отдельно по классам каждое изображение как я понимаю нужно отдельно для каждого класса строить матрицу mat которая будет использована для построения проекции входного изображения..

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

После проведения PCA вы получаете базис.

Зачем это нужно? Это делается для того, чтобы уменьшить размерность сравниваемых векторов до количества векторов базиса.

Фактически, Вы получаете статистическую модель лица, управляемую небольшим количеством параметров.

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

Дальше, при помощи PCA мы получаем несколько (сколько задаем сами), собственных векторов матрицы ковариации с максимальными собственными числами (оси, вдоль которых, параметры меняются максимально (ковариация максимальна) ).

Это наш новый базис(новая система координат) размерность которого совпадает с исходной размерностью картинок, т.к. это векторы в исходной системе координат. А состоит он из, скажем 10 векторов с максимальными собственными числами.

Дальше проецируем туда базу лиц, с которыми будем сравнивать (тех кого знаем), получаем их представление в виде 10 чисел, по числу векторов базиса.

Для того, чтобы произвести опознание, надо спроецировать новое лицо на наш новый базис (10 чисел), и найти расстояние по метрике Махаланобиса (ведь мы знаем матрицу ковариации) до каждого из лиц, имеющихся в базе.

До кого расстояние меньше, тот и победил :)

Мне эти два ролика нравятся по теме:

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

это вроде уже обсуждалось, можете посмотреть код в теме про MNIST.

дескрипторы могут получаться довольно большими

большими это какими и сколько времени на всё про всё уходит?

во первых про SVM+PCA http://metaoptimize.com/qa/questions/11595/pca-with-svm

еще гид по настройке SVM

http://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf

есть еще вроде специальные SVM побыстрее(чем libsvm,lightsvm) и заточенные под что то(большая размерность вектора или большой объемы данных), liblinear(только линейная классификация) и herosvm просто быстрее по их бенчмаркам.

проецирование тут ведётся на всю базу т.е. можно потом будет сравнивать как далеко данный вектор находится от вектора лица(обобщёного лица), а что бы распознавать отдельно по классам каждое изображение как я понимаю нужно отдельно для каждого класса строить матрицу mat которая будет использована для построения проекции входного изображения..

базис строиться по всей базе.

но тут остается немного другой вопрос, допустим у нас есть группы лиц - 1 группа это 1 человек, кол-во лиц в группе разное.

мы из всех изображений делаем базис, потом берем новое изображение и проецируем на базис и хотим по какой либо метрике найти ближайшего соседа, получается что мы до этого должны спроецировать все наши лица на базис и потом выполнить knn search? или тут можно взять и усреднить все лица по индивиду и смотреть принадлежность к группе уже так?(т.е. немного сократили для knn search кол-во сэмплов).

еще как быть если в группе мы большее кол-во лиц имеем настоящие и какое то кол-во имеем шум или от другого человека, как отфильтровать? кластеризовать на 2 кластера и взять больший?

и про проблемы.

самое главное это если изображения не выровненны друг относительно друга.

и вычислительные проблемы тут возникают когда мы имеем samples x vector и min(samples,vector) такой большой, что всё начинает не влезать в память.

но тут есть вроде что то типа online learning или probalistic PCA, но я до этого так и не докопал.

п.с. еще есть такая книжка интересная

Face Image Analysis by Unsupervised Learning

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

большими это какими и сколько времени на всё про всё уходит?

по времени не знаю сегодня завтра замерю а по размеру около 10000 вот

ещё интересует вопрос есть ли какие-нибудь методы которые понизят размерность и гарантированно улучшат(ну или точно не ухудшат) распознавательные способности алгоритма ну типа сжатия без потерь информации что-то в таком духе... или может есть какие-нибудь методы по извлечению особо информативных областей из дескрипторов..

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не надо делать по базису на индивида.

Надо сделать один базис на все лица и работать в нем.

Кластеризовать, измерять расстояния и т.д.

Делая базис для каждого индивида отдельно, Вы теряете общую систему координат, и теряете возможность сравнения.

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

А в данной задаче, как я понял, нужно сравнивать индивидов, как их сравнивать, если у каждого своя система координат?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ну да для лиц это не нужно, но там потом уже про классы похоже разговор, типа машины и самолеты.

кстати интересно, что будет если их всё равно в 1 базис слить?

Делая базис для каждого индивида отдельно, Вы теряете общую систему координат, и теряете возможность сравнения.

ну можно наверно просто брать расстояние до ближайшего в классе(или до центра класса) и так сравнивать между классами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Так и надо их слить в один базис (рассматривать в одной системе координат), если хотим найти статистическую модель данных.

ну можно наверно просто брать расстояние до ближайшего в классе(или до центра класса) и так сравнивать между классами.

У меня такое чувство, что это не совсем корректно, опять таки из-за того, что расстояния измеряться будут каждое в своей системе координат.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

http://scikit-learn.org/stable/auto_examples/applications/face_recognition.html#example-applications-face-recognition-py

кстати тут вот PCA делают перед запихиванием в SVM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×