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

Программа распознавания лиц методом главных компонент

Recommended Posts

Пытаюсь переписать распознавание по PCA на новый OpenCv 2.3. Там есть класс РСА, с помощью которого можно реализовать это. Вот что у меня получилось по коду:


#include <opencv2/core/core.hpp>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/gpu/gpu.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/features2d/features2d.hpp>


#include <vector>


using namespace std;


int _tmain(int argc, _TCHAR* argv[])

{

	ArgParser parser(argc, argv);


	char filelist[200]; 


	try {

		if (!parser.queryFilename("filelist", filelist)) {

			printf("Filelist not specified.\n"); 

			_getch();

			return -1;

		}

	}

	catch (char* str) {

		printf("%s\n", str);

		_getch();

		return -1; 

	}


	FilelistProcessor flP(filelist);


	const unsigned numpics = 100;


	vector <cv::Mat> img_tr;


	for (unsigned i = 0; i < numpics; i++) {

		cv::Mat itmp = cv::imread(flP.getfile(i), 0);

		img_tr.push_back(itmp);

	}


	unsigned imsize = img_tr[0].rows*img_tr[0].cols;

	cv::Mat mat_tr(numpics, imsize, img_tr[0].type());


	for (unsigned i = 0; i < numpics; i++) {

		cv::Mat matRow = mat_tr.row(i);

		memcpy(matRow.data, img_tr[i].data, imsize*sizeof(unsigned char));

	}


	const unsigned maxComponents = 60;


	cv::PCA eigenvectorsCompute(mat_tr, cv::Mat(), CV_PCA_DATA_AS_ROW, maxComponents);


	cv::Mat newImg = cv::imread(flP.getfile(numpics + 1), 0);

	cv::Mat newImgTr(1, imsize, img_tr[0].type());

	{

		cv::Mat matRow = newImgTr.row(0);

		memcpy(matRow.data, newImg.data, imsize*sizeof(unsigned char));

	}



	cv::Mat coeffs;

	coeffs.create(1, maxComponents, CV_32F);

	eigenvectorsCompute.project(newImgTr, coeffs);


	return 0;

}

FilelistProcessor - читает список файлов с изображениями лица. Файлов больше 100, поэтому ошибки в количестве векторов быть не может.

Проблема в том, что полученные на выходе coeffs - нулевые. Что может быть не так?

  • Like 1

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


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

Нашла в чем проблема - изображения, по которым строится РСА должны быть приведены к типу CV_32FC1. Тогда все строится вполне корректно. Хотя в процессе поиска ошибки все переписала заново, код стал другим. Может еще есть какие-то неточности.

  • Like 1

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


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

А вы бы могли, эту программу сбросить на электронный ящик diana87@mail.by , т.к. я не могу ее скачать....

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


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

ok, скинул.

Оба варианта, с начала темы и с этой страницы.

PS: Не скачиваться может из-за менеджеров загрузки.

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


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

С марковскими моделями не стал разбираться, а с PCA сразу с ходу пошло дело. Неплохо работает! Мануал на английском тема)

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


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

Есть вопрос, подскажите пожалуйста! Я нахожу в кадре лицо каскадами Хаара. Затем выделяю найденную область(как в примере прямоугольником). Как мне найденную область фотографии сохранить в JPG и сделать строго определенного размера? Например 100х100 пикселей. Спасибо.

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


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

Если в С, то через ROI

http://nashruddin.com/OpenCV_Region_of_Interest_(ROI)

если в с++, то

img(Rect(x,y,w,h)).copyTo(img1);

а затем Resize

http://linuxconfig.org/resize-an-image-with-opencv-cvresize-function

Вот кусок из одной программы подобного назначения:


CvRect * pFaceRect = (CvRect*)cvGetSeqElem(pRectSeq, 0);
cvSetImageROI(pImg, *pFaceRect);
IplImage * pFaceImg =
cvCreateImage( STD_SIZE, IPL_DEPTH_8U, 1 );
cvResize(pImg, pFaceImg, CV_INTER_AREA );
[/code]

  • Like 1

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


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

Спасибо большое! Применил cvSetImageROI, все прекрасно работает под C++/cli.

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


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

Еще вопросик есть по этой теме. Для распознавания лица методом главных компонент обязательно преобразовывать цветное изображение в градации серого? Как в этом ПРИМЕРЕ . И если обязательно, то как это сделать? Наверняка есть какая то встроенная функция, но поискав я нашел только работу с каналами RGB. Пробовал копировать 3-х канальное изображение в созданное вот таким методом cvCreateImage( STD_SIZE, IPL_DEPTH_8U, 1 ), сразу вылезает ошибка. Я так понял что нельзя запихнуть автоматом цветное изображение в черно-белое. Как быть?

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


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

Как конвертировать нашел. Функция cvCvtColor(img, im2, CV_BGR2GRAY). Но про необходимость этого конвертирования вопрос актуален)

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


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

можно сразу грузить в грей, конвертировать скорее надо т.к. полезной информации в 3-х каналах не так много(опять же цвет волос) или можно по 3-м каналам отдельно смотреть.

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


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

Нужен совет! Последния два дня меня убивает непонятная вещь, а именно виснет приложение, которое фотографирует, находит лицо ресайзит его и записывает в БД на компьютере. Причем оно виснет оно самым странным образом.

1)Запускаю приложение. При этом сразу отображается видео с камеры на форму.

2)Нажимаю кнопку сфотографировать.

3)Находит лицо.

4)Фотографирует, ресайзит и сохраняет в БД все успешно.

5)Видео продолжает отображаться и вроде все впорядке. Можно даже нажать "Закрыть" и все закроется как надо.

НО

6) Если взять окно и попробовать перетащить его, сразу же "Завершена работа программы.." и "Widows ищет поиск решения данной проблемы.."

Еще одно - на ноутбуке все работает замечательно, ничего подобного не происходит. Практически всё идентично: ОС Windows 7, MS Visual Studio 2010, MS SQL 2008, разве что на ноутбуке стоит 64-х разрядная система.

Думал, что может из-за веб камеры. Но поставил камеру с компьютера на ноутбук, там и с этой камерой все работает прекрасно.

К тому же иногда работает все прекрасно и на компьютере. В связи с чем такое может быть, куда смотреть, что делать даж не знаю. Может у кого то были подобные проблемы?

Спасибо за ваши ответы!

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


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

А если скомпилировать под х64, работает ?

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


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

Если не секрет, как это сделать?) На компьютере где висне стоит ОС 32 разрядная. На ноуте 64-х. Где именно копилировать надо? И как поменять настойки сборки, чтобы это сделать.

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


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

Перетрудился я сегодня, тупить начал )).

А он и в отладочной и в релизной версии одинаково глючит?

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


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

Нет, в отладочной версии еще при запуске "Возникла точка останова" и на ноуте и на компе. Но я отладочную версю запускал с библиотеками OpenCV для релизной версии. Может из-за этого?

Я еще думал что мож из-за фреймворка такое может быть каким то образом? Хотя и на ноутбуке и на компьютере ставился новый 4,5 вроде со студией. Приложение я пытаюсь сделать на 3-м фреймворке. Реально уже не знаю, что придумать.

Еще есть такое, что без нахождения лица работает стабильно. Может слишком много дейсвий при нажатии кнопки происходит и 32-х разрядная система не справляется? Хотя вроде ересь.

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


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

Может. Если отладочную версию с релизными библиотеками запускать, GUI-шные функции глючат по-черному.

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


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

Эх, а что ж делать с моим багом при релизной версии?

Может туплю п острашному.

Нашел еще один момент.

Для того чтоб получить при фотографировании картинку качества получше, увеличиваю разрешение считываемого кадра, т.к. видео с камеры отображается в миниатюрном окошке, если убрать это изменение кадра, то все работает, но фото конечно отстойного качества. Может надо как то оптимизировать эту задачу? Хотя все тоже - на ноуте работает с любыми настройками.


                                 timer1->Stop();//


				 Counter = 0; //счетчик времени для показа "Данные записаны в БД"


				 //BuffCount =0;


                                 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 1280); 

				 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 1024);


				 frame = cvQueryFrame( capture );


				 //-------/возврат к миниатюрному изображению/-----------//

				 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, WidthFrame); 

			         cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, HieghtFrame);


Спасибо еще раз, за ваши ответы!

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


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

Сильно похоже на переполнение стека, у Вас таймер останавливается на время вывода кадра?

timer1->Stop(); - это остановка таймера вызывающего функцию или это профилировка ?

Просто ситуация может быть такая:

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

Резюме: Попробуйте останавливать таймер в функции обратного вызова, увеличьте интервал таймера, или уменьшите время выполнения функции обратного вызова.

  • Like 1

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


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

timer1->Stop(); <-- это у меня остановка таймера, который отвечает за воспроизведение кадров в pictureBox.

Спаибо за ответ, очень похоже что у меня как раз эта проблема. Но т.к. я еще новичек в этом деле, особенно с таймерами. Что есть функция обратного вызова у таймера Windows Forms? У системного таймера есть такая функция.

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


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

Smorodov, А почему количество векторов базиса это количество изображений - 1 ?

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


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

2JoQeR: Функция обратного вызова, это та функция, которая вызывается таймером по истечении заданного интервала времени, то есть та самая функция, в которой Вы пишите что должно произойти по таймеру.

2Flame: Теоретически количество векторов базиса может быть любым, в пределах ненулевых собственных значений.

количество изображений - 1 - это, как мне думается, такая opencv-шная фишка (ранних версий),

в 2.4 я считал собственные векторы, этого ограничения нет

http://www.compvision.ru/forum/index.php?showtopic=852&st=20 (пост №37).

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


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

нет -1 это от матана\линала такая фишка(http://www.cognotics.com/opencv/servo_2007_series/part_4/page_2.html ), что когда проецируем можем спроецировать на n-1 измерение, я так понимаю, можем и на меньшее кол-во ,а на большее не можем.

The PCA Subspace

However, the number of principal components we can find is also limited by the number of data points. To see why that is, think of a dataset that consists of just one point. What's the direction of maximum separation for this dataset? There isn't one, because there's nothing to separate. Now consider a dataset with just two points. The line connecting these two points is the first principal component. But there's no second principal component, because there's nothing more to separate: both points are fully on the line.

We can extend this idea indefinitely. Three points define a plane, which is a 2D object, so a dataset with three data points can never have more than two principal components, even if it's in a 3D, or higher, coordinate system. And so on.

In eigenface, each 50x50 face image is treated as one data point (in a 2,500 dimensional "space"). So the number of principal components we can find will never be more than the number of face images minus one.

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


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

А, ну да, это идет от экономного способа поиска матрицы ковариации.

http://opencv.itseez.com/modules/core/doc/operations_on_arrays.html?highlight=calccovarmatrix#cv.CalcCovarMatrix

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

Есть и другой (стандартный) способ, без транспонирования, там матрица ковариации получается размерностью MxM, где M размерность вектора (кол-во точек в изображении).

Прикол в том, что максимальные собственные векторы в этих двух случаях совпадают.

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


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

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

или в данном коде


for (i=0; i < nEigens; i++)

        {

            float d_i = projectedTestFace[i] - coeffs[iTrain][i];

            distSq += d_i * d_i/EigenVals->data.fl[i];

        }

считается эвклидово расстояние? а в статье я так понял расстояние Махаланобиса. Кто знает как его посчитать?

Я так понял что по PCA проще сделать порог отсечения, чем по марковским моделям

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×