11 //#include "HMMDemo.h"
12 //#include "FaceBase.h"
15 #include "multiprocdiv.h"
17 #define NONE_FINISH_WORK -1
23 #define CHECK_TRAIN_FOR_BREAK(mac_thrArr,mac_thrParams,mac_numProc) \
24 if( thrFinishWork == BRAKE_WORK ) { \
27 for( mac_i = 0; mac_i < mac_numProc; mac_i ++ ) { \
28 if( mac_thrParams[mac_i].working == true ) { \
29 mac_thrParams[mac_i].doNext = false; \
30 ResumeThread( mac_thrArr[mac_i] ); \
34 for( pos = base.GetPersonList().GetHeadPosition(); pos; ) \
36 CPerson* person = base.GetPersonList().GetNext( pos ); \
37 person->SetTrainFlag( false ); \
40 for( mac_i = 0; mac_i < mac_numProc; mac_i ++ ) { \
41 if( mac_thrParams[mac_i].working == true ) { \
43 _RPT1( _CRT_WARN, "Terminating thread #%d\n", mac_i ); \
44 if( !TerminateThread( mac_thrArr[mac_i], 1 ) ) { \
45 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, buf, 256, 0 ); \
46 _RPT1( _CRT_WARN, "TerminateThread returned: %s\n", buf ); \
49 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, buf, 256, 0 ); \
50 _RPT1( _CRT_WARN, "TerminateThread returned: %s\n", buf ); \
52 WaitForSingleObject( mac_thrArr[mac_i], 3000 ); \
55 base.DeleteHMMInfo(); \
56 CloseHandle( g_hevtWakeUpControlThread ); \
57 DeleteCriticalSection( &g_critSect ); \
58 hCtrlTrainThread = 0; \
59 trainParam.frame->EnableItemsAfterTrain(); \
63 #define CHECK_TRAIN_FOR_BREAK1(mac_thrArr,mac_thrParams,mac_numProc) \
64 if( thrFinishWork == BRAKE_WORK ) { \
66 for( mac_i = 0; mac_i < mac_numProc; mac_i ++ ) { \
67 if( mac_thrParams[mac_i].working == true ) { \
68 mac_thrParams[mac_i].doNext = false; \
69 ResumeThread( mac_thrArr[mac_i] ); \
73 for( mac_i = 0; mac_i < mac_numProc; mac_i ++ ) { \
74 if( mac_thrParams[mac_i].working == true ) { \
76 _RPT1( _CRT_WARN, "Terminating thread #%d\n", mac_i ); \
77 if( !TerminateThread( mac_thrArr[mac_i], 1 ) ) { \
78 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, buf, 256, 0 ); \
79 _RPT1( _CRT_WARN, "TerminateThread returned: %s\n", buf ); \
82 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, buf, 256, 0 ); \
83 _RPT1( _CRT_WARN, "TerminateThread returned: %s\n", buf ); \
85 WaitForSingleObject( mac_thrArr[mac_i], 30 ); \
88 CloseHandle( g_hevtWakeUpControlThread ); \
89 DeleteCriticalSection( &g_critSect ); \
90 hCtrlTrainThread = 0; \
94 struct TrainThreadParams {
102 HANDLE g_hevtWakeUpControlThread;
103 CRITICAL_SECTION g_critSect;
105 DWORD dwCtrlTrainThread;
106 HANDLE hCtrlTrainThread;
108 volatile int thrFinishWork;
110 StartTrainParams trainParam;
112 //DWORD WINAPI ThreadProc(
113 // LPVOID lpParameter // thread data
116 DWORD trainFunc( LPVOID param )
118 TrainThreadParams* thrParams = (TrainThreadParams*)param;
119 int threadNum = thrParams->threadNum;
120 HANDLE hThread = thrParams->hThread;
122 int anotherThrBlocksVar;
124 InterlockedExchange( (long*)&(thrParams->working), (int)true );
126 while( thrParams->doNext )
128 person = thrParams->person;
130 _RPT1( _CRT_WARN, "Thread #%d begins\n", threadNum );
132 EnterCriticalSection( &g_critSect );
134 LeaveCriticalSection( &g_critSect );
137 person->UnloadRest();
139 if( !thrParams->doNext ) {
144 _RPT1( _CRT_WARN, "Thread #%d ends\n", threadNum );
146 EnterCriticalSection( &g_critSect );
147 thrParams->doNext = false;
148 anotherThrBlocksVar = true;
149 while( anotherThrBlocksVar )
151 if( thrFinishWork == NONE_FINISH_WORK ) {
152 thrFinishWork = threadNum;
153 anotherThrBlocksVar = false;
156 LeaveCriticalSection( &g_critSect );
158 EnterCriticalSection( &g_critSect );
162 _RPT1( _CRT_WARN, "Thread #%d sets event\n", threadNum );
164 SetEvent( g_hevtWakeUpControlThread );
165 LeaveCriticalSection( &g_critSect );
167 _RPT1( _CRT_WARN, "Thread #%d suspends\n", threadNum );
169 SuspendThread( hThread );
173 _RPT1( _CRT_WARN, "Thread #%d resumes\n", threadNum );
174 } // while( thrParams->doNext )
176 _RPT1( _CRT_WARN, "Thread #%d finishes\n", threadNum );
178 InterlockedExchange( (long*)&(thrParams->working), (int)false );
182 DWORD ctrlTrainThreadFunc( LPVOID param )
187 DWORD dwTrainThread[32];
188 HANDLE hTrainThread[32];
189 TrainThreadParams thrParams[32];
194 InitializeCriticalSection( &g_critSect );
195 g_hevtWakeUpControlThread = CreateEvent( 0, true, false, "WakeUpCtrlTrainThread" );
197 GetSystemInfo( &sysInfo );
198 numProc = sysInfo.dwNumberOfProcessors;
203 CloseHandle( g_hevtWakeUpControlThread );
204 DeleteCriticalSection( &g_critSect );
205 hCtrlTrainThread = 0;
209 trainParam.frame->DisableItemsForTrain();
214 // Single processor code
215 CHMMDemoDoc* doc = ( (StartTrainParams*)param )->doc;
218 CFaceBase& base = doc->GetFaceBase();
219 base.TrainAll( ( (StartTrainParams*)param )->flag );
222 // Multiple processor code
223 CHMMDemoDoc* doc = ( (StartTrainParams*)param )->doc;
226 CFaceBase& base = doc->GetFaceBase();
229 for( i = 0; i < numProc; i ++ )
231 affMask |= ( 1 << i );
233 for( i = 0; i < numProc; i ++ )
235 thrParams[i].threadNum = i;
236 thrParams[i].working = true;
237 hTrainThread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)trainFunc, &(thrParams[i]), CREATE_SUSPENDED, &(dwTrainThread[i]) );
238 thrParams[i].hThread = hTrainThread[i];
239 thrParams[i].doNext = false;
240 PRIOR SetThreadPriority( hTrainThread[i], THREAD_PRIORITY_BELOW_NORMAL );
241 //SetThreadAffinityMask( hTrainThread[i], affMask );
242 //SetThreadIdealProcessor( hTrainThread[i], (DWORD)i );
245 thrFinishWork = NONE_FINISH_WORK;
246 ResetEvent( g_hevtWakeUpControlThread );
247 for( i = 0, pos = base.GetPersonList().GetHeadPosition(); pos; )
249 person = base.GetPersonList().GetNext(pos);
251 _RPT2( _CRT_WARN, "%s %d\n", "pos = ", (int)pos );
253 if( (( (StartTrainParams*)param )->flag == TRAIN_UNTRAINED) && person->IsTrained() ) continue;
255 EnterCriticalSection( &g_critSect );
257 _RPT1( _CRT_WARN, "Giving execute to thread #%d\n", i );
259 thrParams[i].person = person;
260 thrParams[i].doNext = true;
261 LeaveCriticalSection( &g_critSect );
263 _RPT1( _CRT_WARN, "Resuming thread #%d\n", i );
265 ResumeThread( hTrainThread[i] );
273 WaitForSingleObject( g_hevtWakeUpControlThread, INFINITE );
274 CHECK_TRAIN_FOR_BREAK( hTrainThread, thrParams, numProc );
276 _RPT1( _CRT_WARN, "Main thread gets last event from thread #%d\n", thrFinishWork );
278 EnterCriticalSection( &g_critSect );
279 ResetEvent( g_hevtWakeUpControlThread );
280 thrParams[ thrFinishWork ].doNext = false;
282 _RPT1( _CRT_WARN, "Resuming thread #%d\n", thrFinishWork );
284 ResumeThread( hTrainThread[ thrFinishWork ] );
285 thrFinishWork = NONE_FINISH_WORK;
287 LeaveCriticalSection( &g_critSect );
289 } // if( i == numProc )
291 i = base.GetPersonList().GetCount() - numProc;
293 WaitForSingleObject( g_hevtWakeUpControlThread, INFINITE );
294 CHECK_TRAIN_FOR_BREAK( hTrainThread, thrParams, numProc );
296 _RPT0( _CRT_WARN, "Main thread gets event\n" );
298 EnterCriticalSection( &g_critSect );
299 ResetEvent( g_hevtWakeUpControlThread );
300 person = base.GetPersonList().GetNext(pos);
302 _RPT1( _CRT_WARN, "pos = %d\n", (int)pos );
304 while( pos && person->IsTrained() ) {
305 if( (( (StartTrainParams*)param )->flag != TRAIN_UNTRAINED) ) {
306 person = base.GetPersonList().GetNext(pos);
313 _RPT1( _CRT_WARN, "Giving execute to thread #%d\n", thrFinishWork );
315 thrParams[ thrFinishWork ].person = person;
316 thrParams[ thrFinishWork ].doNext = true;
318 _RPT1( _CRT_WARN, "Resuming thread #%d\n", thrFinishWork );
320 ResumeThread( hTrainThread[ thrFinishWork ] );
321 thrFinishWork = NONE_FINISH_WORK;
324 LeaveCriticalSection( &g_critSect );
326 _RPT1( _CRT_WARN, "i = %d\n", i );
328 //WaitForSingleObject( g_hevtWakeUpControlThread, INFINITE );
331 for( i = 0; i < numProc; i ++ ) {
336 WaitForSingleObject( g_hevtWakeUpControlThread, INFINITE );
337 CHECK_TRAIN_FOR_BREAK( hTrainThread, thrParams, numProc );
339 _RPT1( _CRT_WARN, "Main thread gets last event from thread #%d\n", thrFinishWork );
341 EnterCriticalSection( &g_critSect );
342 ResetEvent( g_hevtWakeUpControlThread );
343 thrNum = thrFinishWork;
344 thrParams[thrNum].doNext = false;
346 _RPT1( _CRT_WARN, "Resuming thread #%d\n", thrFinishWork );
348 resumeRes = ResumeThread( hTrainThread[thrNum] );
349 thrFinishWork = NONE_FINISH_WORK;
350 LeaveCriticalSection( &g_critSect );
352 _RPT1( _CRT_WARN, "Waiting for finishing thread #%d\n", thrNum );
354 while( !resumeRes ) {
355 resumeRes = ResumeThread( hTrainThread[thrNum] );
357 WaitForSingleObject( hTrainThread[thrNum], INFINITE );
360 } // if( i == numProc ) else
361 for( i = 0; i < numProc; i ++ )
363 thrParams[i].doNext = false;
364 if( thrParams[i].working == true ) {
366 _RPT1( _CRT_WARN, "Resuming thread #%d\n", i );
368 while( !ResumeThread( hTrainThread[i] ) && thrParams[i].working == true ) {
372 _RPT1( _CRT_WARN, "Waiting for finishing thread #%d\n", i );
374 WaitForSingleObject( hTrainThread[i], INFINITE );
378 } // if( numProc == 1 )
381 _RPT0( _CRT_WARN, "Main thread: All is Ok!\n" );
383 CloseHandle( g_hevtWakeUpControlThread );
384 DeleteCriticalSection( &g_critSect );
385 hCtrlTrainThread = 0;
386 trainParam.frame->EnableItemsAfterTrain();
388 } // ctrlTrainThreadFunc
390 bool startTrain( CHMMDemoDoc* doc, CMainFrame* frame, int flag )
392 static bool trainingStartsFirstTime = true;
393 bool anotherThrBlocksVar;
395 if( trainingStartsFirstTime ) {
396 trainingStartsFirstTime = false;
397 hCtrlTrainThread = 0;
400 if( hCtrlTrainThread ) {
401 EnterCriticalSection( &g_critSect );
402 anotherThrBlocksVar = true;
403 while( anotherThrBlocksVar )
405 if( thrFinishWork == NONE_FINISH_WORK ) {
406 thrFinishWork = BRAKE_WORK;
407 anotherThrBlocksVar = false;
410 LeaveCriticalSection( &g_critSect );
412 EnterCriticalSection( &g_critSect );
416 _RPT0( _CRT_WARN, "Main thread sets break event\n" );
418 SetEvent( g_hevtWakeUpControlThread );
419 LeaveCriticalSection( &g_critSect );
422 trainParam.doc = doc;
423 trainParam.frame = frame;
424 trainParam.flag = flag;
426 hCtrlTrainThread = CreateThread( NULL, 0,
427 (LPTHREAD_START_ROUTINE)ctrlTrainThreadFunc, &trainParam, 0, &dwCtrlTrainThread );
428 PRIOR SetThreadPriority( hCtrlTrainThread, THREAD_PRIORITY_BELOW_NORMAL );
438 struct InputRecogChildThread {
439 INPUT_STRUCT_COMMON_PARAMS();
445 struct InputCtrlChildThread {
451 CImageBaseView* baseview;
454 COMMON_GLOBAL_VARS(recognizeThread,InputCtrlChildThread);
457 /*struct InputRecogChildThread {
458 int threadNum; bool doNext; HANDLE hThread; bool working;
464 struct InputCtrlChildThread {
470 CImageBaseView* baseview;
473 CRITICAL_SECTION recognizeThreadCritSect; HANDLE recognizeThreadEvent; volatile int recognizeThreadMessage; HANDLE recognizeThreadThreadHandle; InputCtrlChildThread recognizeThreadInputStruct;
476 // recognize child thread function
477 BEGIN_CHILD_THREAD_FUNCTION(recognizeThread,InputRecogChildThread);
478 BEGIN_CHILD_THREAD_CORE();
479 cvEstimateObsProb( params->info, params->hmm );
480 *(params->like_array) = cvEViterbi( params->info, params->hmm );
481 END_CHILD_THREAD_CORE();
482 END_CHILD_THREAD_FUNCTION();
485 // recognize control thread function
486 BEGIN_CTRL_THREAD_FUNCTION(recognizeThread,InputCtrlChildThread,InputRecogChildThread,0,0,0);
489 if ( params->rect == CRect( 0,0,0,0 ) )
491 params->rect.bottom = params->image->Height();
492 params->rect.right = params->image->Width();
495 float like_array[1000]; ASSERT( params->faceBase->GetPersonList().GetCount() < 1000 );
498 gray_img.CopyOf( *(params->image), 0 );
500 IplImage* ipl = gray_img.GetImage();
503 ipl_roi.xOffset = params->rect.left;
504 ipl_roi.yOffset = params->rect.top;
505 ipl_roi.height = params->rect.Height();
506 ipl_roi.width = params->rect.Width();
511 bool doRescale = false;
516 if ( params->faceBase->m_useWidth )
519 new_width = params->faceBase->m_scaleWidth;
521 if ( params->faceBase->m_useHeight )
524 new_height = params->faceBase->m_scaleHeight;
526 //recompute width or height if any is absent
527 IplImage* ipl_scaled;
532 new_width = new_height * ipl->roi->width / ipl->roi->height;
534 else if ( !new_height )
536 new_height = new_width * ipl->roi->height / ipl->roi->width;
540 ipl_scaled = cvCreateImage( cvSize( new_width, new_height ), IPL_DEPTH_8U, 1 );
542 iplResizeFit(ipl, ipl_scaled, /*ipl_scaled->width, ipl->width,
543 ipl_scaled->height, ipl->height,*/ IPL_INTER_NN);
550 CvSize cvroi = cvSize( ipl_scaled->roi ? ipl_scaled->roi->width : ipl_scaled->width,
551 ipl_scaled->roi ? ipl_scaled->roi->height : ipl_scaled->height);
556 CV_COUNT_OBS( &cvroi, &(params->faceBase->m_dctSize), &(params->faceBase->m_delta), &num_obs );
558 int vect_len = (params->faceBase->m_obsSize.height)*(params->faceBase->m_obsSize.width);
560 if( params->faceBase->m_suppress_intensity )
565 info = cvCreateObsInfo( num_obs, vect_len );
568 if( params->faceBase->m_suppress_intensity )
570 float* observations = (float*)malloc( num_obs.height * num_obs.width * (vect_len+1) * sizeof(float) );
571 cvImgToObs_DCT( /*normalized_image*/ipl_scaled, observations, params->faceBase->m_dctSize, params->faceBase->m_obsSize, params->faceBase->m_delta );
572 ExtractDCT( observations, info->obs, num_obs.height * num_obs.width, vect_len );
578 //IplImage* normalized_image = cvCreateImage( cvroi, IPL_DEPTH_8U, 1 );
579 //NormalizeImageForHMM( ipl_scaled, normalized_image );
581 cvImgToObs_DCT( /*normalized_image*/ipl_scaled, info->obs, params->faceBase->m_dctSize, params->faceBase->m_obsSize, params->faceBase->m_delta );
583 //cvReleaseImage(&normalized_image);
588 cvReleaseImage( &ipl_scaled );
591 float max_like = -100000000;
592 //int recognized = -1;
594 BEGIN_CTRL_THREAD_CORE(params->faceBase->GetPersonList().GetCount());
596 CPerson* person = params->faceBase->GetPersonList().GetAt( params->faceBase->GetPersonList().FindIndex(i) );
600 if( !person->IsTrained() )
606 childParams.hmm = person->GetHMM().GetIppiEHMM();
608 if (!childParams.hmm) //person not trained
614 //cvEstimateObsProb( info, hmm );
615 //like_array[i] = cvEViterbi( info, hmm );
616 childParams.like_array = &(like_array[i]);
617 childParams.info = info;
619 END_CTRL_THREAD_CORE();
621 for( i = 0; i < MIN(3,params->faceBase->GetPersonList().GetCount()); i ++ )
623 float maxl = -FLT_MAX;
626 for( int j = 0; j < params->faceBase->GetPersonList().GetCount(); j++ )
628 if (like_array[j] > maxl) { maxl = like_array[j]; maxind = j; }
630 //params->three_first[i] = maxind;
632 like_array[maxind] = -FLT_MAX;
634 cvReleaseObsInfo( &info );
638 if( !code ) return result = code;
640 //return MIN(3,params->faceBase->GetPersonList().GetCount());
643 //int result = base.RecognizePerson( camera.GetFrame(), view->GetSelection(),
645 result = MIN(3,params->faceBase->GetPersonList().GetCount());
649 //MessageBox( params->hwnd, "Not all persons are trained", NULL, MB_ICONERROR );
650 MessageBox( 0, "Not all persons are trained", NULL, MB_ICONERROR );
654 CString message = "";
655 for( int i = 0 ; i < result; i++ )
657 CPerson* person = params->base->GetPerson( ranged[i]);
658 message += person->GetName() + "\n";
661 params->baseview->SwitchMode(ranged[0], false);
662 //MessageBox( params->hwnd, (LPCTSTR)message, NULL, MB_ICONEXCLAMATION );
663 MessageBox( 0, (LPCTSTR)message, "Result of recognition", MB_ICONEXCLAMATION );
666 END_CTRL_THREAD_FUNCTION();
668 BEGIN_START_THREAD_FUNCTION(recognizeThread,
669 (CImage& image, CRect rect, /*HWND hwnd,*/
670 CFaceBase& base, CImageBaseView* baseview),InputCtrlChildThread);
671 params->image = ℑ
673 params->base = &base;
674 params->faceBase = &base;
675 params->baseview = baseview;
676 END_START_THREAD_FUNCTION();