Smorodov 578 Report post Posted June 20, 2009 Внутри архива с исходниками лежит источник, откуда я взял большую часть кода, я не все понимаю в этой теме, если кто может дополнить комментарии, буду благодарен. Однако алгоритм работает очень неплохо. Архив с проектом: HMM.RAR 1 Share this post Link to post Share on other sites
Eugene 0 Report post Posted August 20, 2009 Позвольте спросить. Я взял ваш исходник и решил немного модифицировать так, чтобы работало с 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. Первый лежит в вашем архиве. Share this post Link to post Share on other sites
Eugene 0 Report post Posted August 20, 2009 Извините. Все, разобрался. Проблема была в том, что забыл преобразовать изображение в изображение только с градациями серого перед отправкой в функцию тренировки Марковской модели. Share this post Link to post Share on other sites
Eugene 0 Report post Posted August 28, 2009 После предыдущей ошибки появилась сразу следующая. Программа всегда вылетает на вот этой строке cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm ); Бьюсь несколько дней над этой проблемой. Ничего не могу сделать. Пробовал как с этим исходником, так и с исходником, с которого был сделан этот исходник. Использую Visual Studio 2008. Делал как в C++, так и в С++/CLI. Ничего не работает. Документация по OpenCV не помогает. Если у вас есть время, то помогите пожалуйста. Очень интересно все-таки разобраться с этим методом. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 28, 2009 После предыдущей ошибки появилась сразу следующая. Программа всегда вылетает на вот этой строке <!--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 Share this post Link to post Share on other sites
Eugene 0 Report post Posted August 28, 2009 По одной строчке ничего сказать нельзя, посмотрите в дебаггере чему равны значения аргументов перед вызовом функции, и опишите ошибку, которую вызывает эта строка. ... Спасибо за то, что отвечаете. В консоли пишется следующее сообщение: 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; } Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 29, 2009 Можно попробовать заменить этот цикл 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 сейчас не установлен, проверить не могу. Share this post Link to post Share on other sites
Eugene 0 Report post Posted August 31, 2009 С циклом проблем нет, так как он выполняется только один раз. Если убирать цикл, то ошибка остается. Не знаю в чем может быть проблема. Вроде все сделано по документации и все функции вызываются в той же последовательности в той же последовательности, и параметры как в документации. А вот сами переменные: 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 Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 31, 2009 Странно вот что: totalPeople 0 int totalFaces 0 int _A_SUBDIR error: identifier '_A_SUBDIR' out of scope Это не может означать что просто фотки не загружены? Можно проверить значения элементов массива IplImage **images в функции Train на значение отличное от NULL. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 31, 2009 У меня вот так tmplEhmm: и obsInfoVec[ j ] Может архив проекта выложите, я Vs2008 поставил, посмотрю поближе. Share this post Link to post Share on other sites
Eugene 0 Report post Posted August 31, 2009 Все!!! Урррааааа!!!!!!!!!!!!!! Проблема была устранена. Сколько дней бился головой об стену, не зная, в чем ошибка и наконец нашел. Вся проблема была в том, что в последней версии OpenCV есть баги. Сразу после установки OpenCV версии 1.0 все проблемы решились сами собой. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 31, 2009 Все!!! Урррааааа!!!!!!!!!!!!!! Проблема была устранена. Сколько дней бился головой об стену, не зная, в чем ошибка и наконец нашел. Вся проблема была в том, что в последней версии OpenCV есть баги. Сразу после установки OpenCV версии 1.0 все проблемы решились сами собой. У меня и с 1.1pre1 работает во всяком случае в билдере Хотя баги в 1.1 есть , но ждем 2.0 (21 сентября) с новыми багами и ++ поддержкой. Share this post Link to post Share on other sites
Wildcat 2 Report post Posted October 6, 2009 в функции 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. Изменения, которые внесла - сделала консольной, убрала вывод изображений и форму, по сути все функции остались старыми. Share this post Link to post Share on other sites
Smorodov 578 Report post Posted October 8, 2009 в функции 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 и все работает. Кто его поймет, как счтиать похожесть . И номер фотки - 3. Share this post Link to post Share on other sites
Wildcat 2 Report post Posted October 9, 2009 Да, у меня примерно такие же результаты и от одного обучения к другому различаются... Кстати там еще 1 ошибочка есть при удалении памяти delete likehood; правильно будет delete [] likehood; На самом деле, почему меня заинтересовал этот вопрос: Предположим, что кроме известных нам людей из бузя могут появляться люди, не похожие ни на одного человека и их надо отсеивать. Казалось бы хорошо это сделать по порогу похожести, но для этого я хочу понять, что она значит и какой порог ставить... Share this post Link to post Share on other sites
Smorodov 578 Report post Posted October 12, 2009 Да, у меня примерно такие же результаты и от одного обучения к другому различаются... Кстати там еще 1 ошибочка есть при удалении памяти delete likehood; правильно будет delete [] likehood; На самом деле, почему меня заинтересовал этот вопрос: Предположим, что кроме известных нам людей из бузя могут появляться люди, не похожие ни на одного человека и их надо отсеивать. Казалось бы хорошо это сделать по порогу похожести, но для этого я хочу понять, что она значит и какой порог ставить... Огромное спасибо за отлов багов Насколько я знаю, HMM, в такой реализации, работают с закрытыми наборами данных (адекватный результат может быть получен только для лиц из базы), для открытых наборов, и синтеза применяют PCA (метод собственных компонент). Пример тоже есть на форуме, правда тоже для фиксированной базы, но там похожесть измеряется уже более понятным способом, как расстояние между многомерными векторами. Видимо, лучше использовать этот метод для отсеивания по порогу, а затем применять HMM, для уточнения. Share this post Link to post Share on other sites
Wildcat 2 Report post Posted October 12, 2009 Спасибо за понятный ответ PCA уже использую вместе с нейронными сетями, там действительно можно добиться отсеивания неизвестных лиц. Просто думала, что можно дополнить систему еще и классификатором на мерковских моделях. Тогда его можно использовать для уточнения личности. Проверила данный классификатор на своей базе данных лиц. Очень даже ничего работает. На тестовой выборке из примерно 400 фотографий 70 разных человек 351 были распознаны правильно (тестовая и обучающая выборка не пересекаются). При этом если для некоторых людей, для которых было мало обучающих примеров добавить изображения в обучающую выборку, думаю станет еще лучше. Share this post Link to post Share on other sites
Wildcat 2 Report post Posted October 12, 2009 Вот кстати решила все-таки попробовать отсечение по порогу похожести. И сразу могу порадовать - результат есть 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 Share this post Link to post Share on other sites
soff 0 Report post Posted November 6, 2009 Не могли бы вы поподробнее где вы установили порог похожести. хорошо бы кусочек кода и нет ли теории по марковскому узнаванию на русском яз.? какой там принцип вообще хотелось бы понять. а то ошибки самые парадоксальные случаются... Share this post Link to post Share on other sites
Smorodov 578 Report post Posted November 7, 2009 Не могли бы вы поподробнее где вы установили порог похожести. хорошо бы кусочек кода и нет ли теории по марковскому узнаванию на русском яз.? какой там принцип вообще хотелось бы понять. а то ошибки самые парадоксальные случаются... Кусочек кода есть сверху, порог похожести ставится на переменную likehood. Как показано в предыдущем посте порог устанавливался на значение -85, возможно это значение подходит не ко всем случаям, нужно провести эксперимент. По принципу можно посмотреть литературу по ключевым словам Скрытые Марковские Модели, по приложению их к распознаванию лиц толкового ничего на русском не нашел. Есть пара доков, но там совсем немного информации: лекции_по_hmm.pdf скрытые_марковские_модели__радужка_.pdf Share this post Link to post Share on other sites
soff 0 Report post Posted November 9, 2009 спасибо вот еще в тему http://www.intsys.msu.ru/magazine/archive/...kov-135-156.pdf 4 мега там математика по трем методам распознавания и в конце такая статистика Share this post Link to post Share on other sites
Wildcat 2 Report post Posted November 27, 2009 Интересно... у всех такая хорошая статистика в статьях указывается, и всегда по сравнению с остальными предложенный метод выигрывает... Share this post Link to post Share on other sites
spec7r 0 Report post Posted May 13, 2010 Скажите, пожалуйста, кто-нибудь решил проблему с cvEstimateObsProb( obsInfoVec[ j ], tmplEhmm ); при использовании OpenCV 2.0 и выше?? Share this post Link to post Share on other sites
hamam 0 Report post Posted August 25, 2010 Скажите, пожалуйста, кто-нибудь решил проблему с при использовании OpenCV 2.0 и выше?? я столкнулся и тот же вопрос, а также используя OpenCV 2,0 удалось для решения Ваших 1, любезно ждут Вашего высоко оценил ответить, если есть письменное ошибку простить меня, потому что я не русский, и я использую для перевода с английского на русский Share this post Link to post Share on other sites
Smorodov 578 Report post Posted August 25, 2010 я столкнулся и тот же вопрос, а также используя OpenCV 2,0 удалось для решения Ваших 1, любезно ждут Вашего высоко оценил ответить, если есть письменное ошибку простить меня, потому что я не русский, и я использую для перевода с английского на русский Я не знаю как в SVN версии, но в 2.0 и 2.1 это открытая проблема, о которой уже известно разработчикам: http://sourceforge.net/tracker/index.php?f...amp;atid=376677 Попробую построить SVN версию, и проверю, осталась-ли ошибка. Share this post Link to post Share on other sites