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

Распознавание лиц HMM (Скрытые марковские модели)

Recommended Posts

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

Однако алгоритм работает очень неплохо.

hmm.jpg

Архив с проектом: HMM.RAR

  • Like 1

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


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

Позвольте спросить.

Я взял ваш исходник и решил немного модифицировать так, чтобы работало с WPF и Framework 3.5. Поэтому делаю на C++/CLI. Взял ваши функции для тренировки и распознавания. Но при тренировке во время выполнения программа вылетает после следующей строки:

cvImgToObs_DCT( iplImg, observations, dctSize, noDCTCoeff, stepSize );

Сама ошибка пишется так: An unhandled exception of type 'System.Runtime.InteropServices.SEHException' occurred in HMMFace.exe

Additional information: External component has thrown an exception.

В консоли пишет следующее:

OpenCV Error: Unsupported format or combination of formats () in c

vImgToObs_DCT, file .\cvhmmobs.cpp, line 627

Я, честно говоря в тупике - не знаю в чем проблема и бьюсь головой об стену уже второй день. Может быть сможете помочь и прояснить в чем суть ошибки? Заранее благодарен. Это второй исходник в сети, в котором я нашел реализацию HMM в OpenCV. Первый лежит в вашем архиве.

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


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

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

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


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

После предыдущей ошибки появилась сразу следующая. Программа всегда вылетает на вот этой строке

cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm );

Бьюсь несколько дней над этой проблемой. Ничего не могу сделать. Пробовал как с этим исходником, так и с исходником, с которого был сделан этот исходник. Использую Visual Studio 2008. Делал как в C++, так и в С++/CLI. Ничего не работает. Документация по OpenCV не помогает. Если у вас есть время, то помогите пожалуйста. Очень интересно все-таки разобраться с этим методом.

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


Ссылка на сообщение
Поделиться на других сайтах
После предыдущей ошибки появилась сразу следующая. Программа всегда вылетает на вот этой строке

<!--shcode--><!--shcode--><pre><code class='no-highlight'>cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm );</code></pre><!--ehcode--><!--ehcode-->

Бьюсь несколько дней над этой проблемой. Ничего не могу сделать. Пробовал как с этим исходником, так и с исходником, с которого был сделан этот исходник. Использую Visual Studio 2008. Делал как в C++, так и в С++/CLI. Ничего не работает. Документация по OpenCV не помогает. Если у вас есть время, то помогите пожалуйста. Очень интересно все-таки разобраться с этим методом.

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

Что должны представлять собой аргуенты можно посмотреть здесь: Eigen Objects (PCA) Functions

Настройки VS2008 можно посмотреть здесь (то что касается Opencv): http://www.compvision.ru/forum/index.php?showtopic=95

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


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

...

Спасибо за то, что отвечаете.

В консоли пишется следующее сообщение: Error: Assertion failed (src.typ

e() == dst.type() && src.size() == dst.size()) in unknown function, file .\cxmat

hfuncs.cpp, line 1762

устанавливать cuda пока не пробовал. Но думаю, что она не нужна для работы.

Все остальные настройки сделал как написано у вас. Программа не работает.

Пробовал загружать изображения разных форматов - ошибка остается.

сама программа работает так:

вначале вызывается функция AddStatFromFileImage, в которую передается имя графического файла.

Эта функция потом вызывает функцию Train, в которую передается загруженное из файла изображение.

вот весь код:

void DataBase::AddStatFromFileImage(System::String^ SFilename)

{

	char* filename = (char*)Marshal::StringToHGlobalAnsi(SFilename).ToPointer();

	 	printf(filename);



	CvSize size;

	img_load = cvLoadImage(filename);

	Marshal::FreeHGlobal((System::IntPtr)filename);

	IplImage* img[1];

	size=cvSize(img_load->width,img_load->height);

	img[0] = cvCreateImage( size, IPL_DEPTH_8U, 1 );

	cvSplit(img_load,img[0],NULL,NULL,NULL);

	CvEHMM* stat=0;

	stat = Train(img,1);

}


void DataBase::ExtractDCT( float* src, float* dst, int numVec, int dstLen )

{

	float *tmpSrc = src + 1;

	float *tmpDst = dst;

	int i;


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

	{

		memcpy( tmpDst, tmpSrc, dstLen * sizeof( float ) );

		tmpSrc += dstLen + 1;

		tmpDst += dstLen;

	}

} 


CvEHMM * DataBase::Train(IplImage **images,int numImages/*,CvEHMM *tmplEhmm*/)

{

//Параметры обучения

	const int OBS_WIDTH = 12;

	const int OBS_HEIGHT = 12;


	const int NO_DCT_COEFF_X = 4;

	const int NO_DCT_COEFF_Y = 4;


	const int STEP_X = 4;

	const int STEP_Y = 4;


	const bool SUPPRESS_INTESITY = false;

	const int MAX_ITER = 80;

	const double STOP_STEP_ITER = 0.01;


	CvEHMM *tmplEhmm;


	// 5 - суперсостояний по 3,6,6,6,3 - соответственно состояний в каждом

	int noStates[] = { 5, 3, 6, 6, 6, 3 };


	// количество Гауссовых смесей для каждого состояния.

	int numMixtures[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };


	//NO_DCT_COEFF_X * NO_DCT_COEFF_Y - 1	т.к. не учитываем первый коэффициент

	int vecSize = NO_DCT_COEFF_X * NO_DCT_COEFF_Y - 1;


	// Переводим в cvSize что бы удобнее было использовать

	CvSize dctSize = cvSize( OBS_WIDTH, OBS_HEIGHT);

	CvSize stepSize = cvSize( STEP_X, STEP_Y );

	CvSize noDCTCoeff = cvSize( NO_DCT_COEFF_X, NO_DCT_COEFF_Y);

	// Вектор наблюдений

	CvImgObsInfo **obsInfoVec;

	// Временное изображение

	IplImage *iplImg;

	// Размерность вектора наблюдений

	int obsVecLen = NO_DCT_COEFF_X * NO_DCT_COEFF_Y;

	// Количество наблюдений

	CvSize noObs;

	// Создали тренируемый объект

	tmplEhmm = cvCreate2DHMM( noStates, numMixtures, vecSize );

	// Для хранения предыдущего значения степени похожести

	float oldLikelihood = 0;

	// Счетчик итераций

	int counter = 0;


	int i;


	if( SUPPRESS_INTESITY )

	{

	//Подавляем первый коэффициент дискретного косинусного преобразования (ДКП)

	obsVecLen--;

	}


   // Создаем массив наблюдений

   obsInfoVec = new CvImgObsInfo*[ numImages ];


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

	{

	   // Загружаем указатель на изображение

	   		iplImg = images[i];

	   // Рассчитываем, сколько нужно произвести ДКП (DCT)

		noObs.width = ( iplImg->width - dctSize.width + stepSize.width ) / stepSize.width;

		noObs.height = ( iplImg->height - dctSize.height + stepSize.height ) / stepSize.height;

	   // Создаем наблюдения для каждого преобразования

		obsInfoVec[ i ] = cvCreateObsInfo( noObs, obsVecLen );


		if( SUPPRESS_INTESITY )

		{

			float *observations = new float[ noObs.height * noObs.width * ( obsVecLen + 1 ) ];

			cvImgToObs_DCT( iplImg, observations, dctSize, noDCTCoeff, stepSize );

						// Подавляем первый коэффициент ДКП

			ExtractDCT( observations, obsInfoVec[ i ]->obs, noObs.height * noObs.width, obsVecLen );

						// Очистка

			if ( observations )

			{

				delete( observations);

			}

		}

	 // Если не подавляем первый коэффициент

		else

		{

			cvImgToObs_DCT( iplImg, obsInfoVec[ i ]->obs, dctSize, noDCTCoeff, stepSize );

		}

		cvUniformImgSegm( obsInfoVec[ i ], tmplEhmm );

		cvReleaseImage( &iplImg );

	}


	cvInitMixSegm( obsInfoVec, numImages, tmplEhmm );


	int trained=0;


	// Процедура обучения

	while( ( !trained ) &&( counter < MAX_ITER ) )

	{ 

		int j;	

		float likelihood = 0;	 

		counter++;


		cvEstimateHMMStateParams( obsInfoVec, numImages, tmplEhmm );

		cvEstimateTransProb( obsInfoVec, numImages, tmplEhmm);


		for( j = 0; j < numImages; j++ )

		{

//////////////////////////////////////////////////////////////////////////////////

// вылетает во время выполнения следующей строки

			cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm );

//////////////////////////////////////////////////////////////////////////////////

			likelihood += cvEViterbi( obsInfoVec[ j ], tmplEhmm );

		}

		likelihood /= numImages * obsInfoVec[ 0 ]->obs_size;

		cvMixSegmL2( &obsInfoVec[ 0 ], numImages, tmplEhmm );

		trained = ( fabs( likelihood - oldLikelihood ) < STOP_STEP_ITER );

		oldLikelihood = likelihood;

   }

	// Очистка

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

	{

		cvReleaseObsInfo( &(obsInfoVec[ i ]) );

	}

	delete []obsInfoVec;

	return tmplEhmm;

}

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


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

Можно попробовать заменить этот цикл

		for( j = 0; j < numImages; j++ )
{
//////////////////////////////////////////////////////////////////////////////////
// вылетает во время выполнения следующей строки
cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm );
//////////////////////////////////////////////////////////////////////////////////
likelihood += cvEViterbi( obsInfoVec[ j ], tmplEhmm );
}[/code] на
[code]//////////////////////////////////////////////////////////////////////////////////
// вылетает во время выполнения следующей строки
cvEstimateObsProb( obsInfoVec[ 0 ], tmplEhmm );
//////////////////////////////////////////////////////////////////////////////////
likelihood += cvEViterbi( obsInfoVec[ 0 ], tmplEhmm );

и посмотреть будет-ли вылетать, если не будет, значит проблема с количеством элементов массива obsInfoVec, если будет, значит проблема с созданием элементов массива obsInfoVec.

tmplEhmm - используется и ранее по программе, и проблем вроде не вызывает.

И неплохо бы брейкпоинт поставить на эту строчку и посмотреть чему переменные равны.

Или printf-ом их в консоль вывести попытаться.

ЗЫ: Ответы умозрительные, VS сейчас не установлен, проверить не могу.

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


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

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

А вот сами переменные:

totalPeople	0	int

		totalFaces	0	int

		_A_SUBDIR	error: identifier '_A_SUBDIR' out of scope	

-		tmplEhmm	0x014E8180 { level=1 num_states=5 transP=0x014E8200 ...}	CvEHMM*

		level	1	int

		num_states	5	int

-		obsProb	0x00000000	float**

+		*(*tmplEhmm).obsProb	error: cannot obtain value	float*

-		transP	0x014E8200	float*

		*(*tmplEhmm).transP	-0.15415066	float

-		u	{...}	CvEHMM::<unnamed-type-u>

-		ehmm	0x014E8194 { level=0 num_states=3 transP=0x014F8080 ...}	CvEHMM*

		level	0	int

		num_states	3	int

+		obsProb	0x00000000	float**

-		transP	0x014F8080	float*

		*(*(*tmplEhmm).u.ehmm).transP	-0.095310152	float

+		u	{...}	CvEHMM::<unnamed-type-u>

-		state	0x014E8194 { num_mix=0 mu=0x00000003 inv_var=0x014F8080 ...}	CvEHMMState*

-		inv_var	0x014F8080	float*

		*(*(*tmplEhmm).u.state).inv_var	-0.095310152	float

-		log_var_val	0x00000000	float*

		*(*(*tmplEhmm).u.state).log_var_val	0.00000000	float

-		mu	0x00000003	float*

		*(*(*tmplEhmm).u.state).mu	error: unable to access invalid memory location	float

		num_mix	0	int

-		weight	0x014F0080	float*

		*(*(*tmplEhmm).u.state).weight	4.2038954e-045	float

-		obsInfoVec	0x0037FAB8	CvImgObsInfo**

-		*obsInfoVec	0x01500080 { obs_x=31 obs_y=31 obs_size=16 ...}	CvImgObsInfo*

-		mix	0x01508080	int*

		*(**obsInfoVec).mix	0	int

-		obs	0x040C4000	float*

		*(**obsInfoVec).obs	957.58331	float

		obs_size	16	int

		obs_x	31	int

		obs_y	31	int

-		state	0x01504080	int*

		*(**obsInfoVec).state	0	int

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


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

Странно вот что:

totalPeople 0 int

totalFaces 0 int

_A_SUBDIR error: identifier '_A_SUBDIR' out of scope

Это не может означать что просто фотки не загружены?

Можно проверить значения элементов массива IplImage **images в функции Train на значение отличное от NULL.

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


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

У меня вот так tmplEhmm:

SS1.jpg

и obsInfoVec[ j ]

SS1.jpg

Может архив проекта выложите, я Vs2008 поставил, посмотрю поближе.

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


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

Все!!! Урррааааа!!!!!!!!!!!!!! Проблема была устранена. Сколько дней бился головой об стену, не зная, в чем ошибка и наконец нашел. Вся проблема была в том, что в последней версии OpenCV есть баги. Сразу после установки OpenCV версии 1.0 все проблемы решились сами собой.

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


Ссылка на сообщение
Поделиться на других сайтах
Все!!! Урррааааа!!!!!!!!!!!!!! Проблема была устранена. Сколько дней бился головой об стену, не зная, в чем ошибка и наконец нашел. Вся проблема была в том, что в последней версии OpenCV есть баги. Сразу после установки OpenCV версии 1.0 все проблемы решились сами собой.

У меня и с 1.1pre1 работает во всяком случае в билдере :)

Хотя баги в 1.1 есть :), но ждем 2.0 (21 сентября) с новыми багами и ++ поддержкой.

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


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

в функции float ComputeLikelihood( IplImage* img, CvEHMM &tmplEhmm) создается объект info = cvCreateObsInfo( noObs, obsVecLen ), но в конце не удаляется, поэтому при обработке большого количества изображений программа падает.

Лечится это заменой

____________________________________

cvEstimateObsProb( info, &tmplEhmm );

return cvEViterbi( info, &tmplEhmm );

____________________________________

на

____________________________________

cvEstimateObsProb( info, &tmplEhmm );

float retval = cvEViterbi( info, &tmplEhmm );

cvReleaseObsInfo(&info);

return retval;

____________________________________

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

Это у меня ошибка?

Я конвертировала программу в Visual Studio 2008. Изменения, которые внесла - сделала консольной, убрала вывод изображений и форму, по сути все функции остались старыми. ;)

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


Ссылка на сообщение
Поделиться на других сайтах
в функции float ComputeLikelihood( IplImage* img, CvEHMM &tmplEhmm) создается объект info = cvCreateObsInfo( noObs, obsVecLen ), но в конце не удаляется, поэтому при обработке большого количества изображений программа падает.

Лечится это заменой

____________________________________

cvEstimateObsProb( info, &tmplEhmm );

return cvEViterbi( info, &tmplEhmm );

____________________________________

на

____________________________________

cvEstimateObsProb( info, &tmplEhmm );

float retval = cvEViterbi( info, &tmplEhmm );

cvReleaseObsInfo(&info);

return retval;

____________________________________

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

Это у меня ошибка?

Я конвертировала программу в Visual Studio 2008. Изменения, которые внесла - сделала консольной, убрала вывод изображений и форму, по сути все функции остались старыми. ;)

Все правильно, вот мои значения likehood[j]:

-82,5132369995117

-80,4748992919922

-77,9187850952148

-75,3669357299805

-81,546272277832

-78,8088073730469

-79,0791778564453

Максимальное среди них -75 :huh: и все работает. Кто его поймет, как счтиать похожесть :).

И номер фотки - 3.

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


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

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

Кстати там еще 1 ошибочка есть при удалении памяти

delete likehood;

правильно будет

delete [] likehood;

На самом деле, почему меня заинтересовал этот вопрос:

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

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

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


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

Кстати там еще 1 ошибочка есть при удалении памяти

delete likehood;

правильно будет

delete [] likehood;

На самом деле, почему меня заинтересовал этот вопрос:

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

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

Огромное спасибо за отлов багов :)

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

Видимо, лучше использовать этот метод для отсеивания по порогу, а затем применять HMM, для уточнения.

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


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

Спасибо за понятный ответ :)

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

Тогда его можно использовать для уточнения личности. Проверила данный классификатор на своей базе данных лиц. Очень даже ничего работает.

На тестовой выборке из примерно 400 фотографий 70 разных человек 351 были распознаны правильно (тестовая и обучающая выборка не пересекаются). При этом если для некоторых людей, для которых было мало обучающих примеров добавить изображения в обучающую выборку, думаю станет еще лучше.

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


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

Вот кстати решила все-таки попробовать отсечение по порогу похожести. И сразу могу порадовать - результат есть :)

Found 334 correctly out of 402 (Всего было 402 фото 70 людей, корректно были определены 334 из них)

Max likelyhood = -64.166580; (По всей тестовой выборке максимальное значение похожести)

Min likelyhood = -200.293488 (По всей тестовой выборке минимальное значение похожести)

Metrics:

FAR = 0.330827; FRR = 0.074792 (false accept rate - сюда входили незнакомые люди, отнесенные к одному из лиц базы данных, а также знакомые распознанные некорректно и false reject rate - не пропущенные по порогу похожести знакомые)

True Positives = 334; False Positives = 88

True Negatives = 178; False Negatives = 27

Could be correct, but denied = 19 (лица не пропущенные по порогу похожести, но которые были бы правильно распознаны, если бы этого порога не было - будем называть **)

Maxes: Positive = -80.201523; Negative = -87.098999; Denied = -86.298912 (средняя похожесть для правильно распознанных, средняя похожесть для неизвестных лиц, средняя похожесть для **)

В данном исследовании порог отсечения неизвестных лиц - -85.5

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


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

Не могли бы вы поподробнее где вы установили порог похожести.

хорошо бы кусочек кода

и нет ли теории по марковскому узнаванию на русском яз.?

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

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


Ссылка на сообщение
Поделиться на других сайтах
Не могли бы вы поподробнее где вы установили порог похожести.

хорошо бы кусочек кода

и нет ли теории по марковскому узнаванию на русском яз.?

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

Кусочек кода есть сверху, порог похожести ставится на переменную likehood. Как показано в предыдущем посте порог устанавливался на значение -85, возможно это значение подходит не ко всем случаям, нужно провести эксперимент.

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

Есть пара доков, но там совсем немного информации:

лекции_по_hmm.pdf

скрытые_марковские_модели__радужка_.pdf

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


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

спасибо

вот еще в тему

http://www.intsys.msu.ru/magazine/archive/...kov-135-156.pdf

4 мега

там математика по трем методам распознавания

и в конце такая статистика

post-166-1257807665_thumb.jpg

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


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

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

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


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

Скажите, пожалуйста, кто-нибудь решил проблему с

cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm );
при использовании OpenCV 2.0 и выше??:)

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


Ссылка на сообщение
Поделиться на других сайтах
Скажите, пожалуйста, кто-нибудь решил проблему с при использовании OpenCV 2.0 и выше??:(

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

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


Ссылка на сообщение
Поделиться на других сайтах
я столкнулся и тот же вопрос, а также используя OpenCV 2,0 удалось для решения Ваших 1, любезно ждут Вашего высоко оценил ответить, если есть письменное ошибку простить меня, потому что я не русский, и я использую для перевода с английского на русский

Я не знаю как в SVN версии, но в 2.0 и 2.1 это открытая проблема, о которой уже известно разработчикам:

http://sourceforge.net/tracker/index.php?f...amp;atid=376677

Попробую построить SVN версию, и проверю, осталась-ли ошибка.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×