$search
00001 00002 00003 #ifdef __LINUX__ 00004 #include "cob_people_detection/PeopleDetector.h" 00005 #include "cob_vision_utils/GlobalDefines.h" 00006 #else 00007 #include "cob_vision/cob_people_detection/common/include/cob_people_detection/PeopleDetector.h" 00008 #include "cob_common/cob_vision_utils/common/include/cob_vision_utils/GlobalDefines.h" 00009 #endif 00010 00011 #include <opencv/cv.h> 00012 #include <opencv/cvaux.h> 00013 00014 using namespace ipa_PeopleDetector; 00015 00016 PeopleDetector::PeopleDetector(void) 00017 { 00018 m_face_cascade = 0; 00019 m_range_cascade = 0; 00020 } 00021 00022 unsigned long PeopleDetector::Init(std::string directory) 00023 { 00024 // Load Haar-Classifier for frontal face-, eyes- and body-detection 00025 std::string faceCascadePath = directory + "haarcascades/haarcascade_frontalface_alt2.xml"; 00026 // todo: 00027 std::string rangeCascadePath = directory + "haarcascades/haarcascade_range_multiview_5p_bg.xml"; 00028 //std::string rangeCascadePath = directory + "haarcascades/haarcascade_range_multiview_5p_bg+.xml"; // + "haarcascades/haarcascade_range.xml"; 00029 m_face_cascade = (CvHaarClassifierCascade*)cvLoad(faceCascadePath.c_str(), 0, 0, 0 ); //"ConfigurationFiles/haarcascades/haarcascade_frontalface_alt2.xml", 0, 0, 0 ); 00030 m_range_cascade = (CvHaarClassifierCascade*)cvLoad(rangeCascadePath.c_str(), 0, 0, 0 ); 00031 00032 // Create Memory 00033 m_storage = cvCreateMemStorage(0); 00034 00035 return ipa_Utils::RET_OK; 00036 } 00037 00038 PeopleDetector::~PeopleDetector(void) 00039 { 00040 // Release Classifiers and memory 00041 cvReleaseHaarClassifierCascade(&m_face_cascade); 00042 cvReleaseHaarClassifierCascade(&m_range_cascade); 00043 cvReleaseMemStorage(&m_storage); 00044 } 00045 00046 unsigned long PeopleDetector::DetectColorFaces(cv::Mat& img, std::vector<cv::Rect>& faceCoordinates) 00047 { 00048 IplImage imgPtr = (IplImage)img; 00049 CvSeq* faces = cvHaarDetectObjects( 00050 &imgPtr, 00051 m_face_cascade, 00052 m_storage, 00053 m_faces_increase_search_scale, 00054 m_faces_drop_groups, 00055 CV_HAAR_DO_CANNY_PRUNING, 00056 cvSize(m_faces_min_search_scale_x, m_faces_min_search_scale_y) 00057 ); 00058 00059 cv::Size parentSize; 00060 cv::Point roiOffset; 00061 for(int i=0; i<faces->total; i++) 00062 { 00063 cv::Rect* face = (cv::Rect*)cvGetSeqElem(faces, i); 00064 img.locateROI(parentSize, roiOffset); 00065 face->x += roiOffset.x; // todo: check what happens if the original matrix is used without roi 00066 face->y += roiOffset.y; 00067 faceCoordinates.push_back(*face); 00068 } 00069 00070 return ipa_Utils::RET_OK; 00071 } 00072 00073 unsigned long PeopleDetector::InterpolateUnassignedPixels(cv::Mat& img) 00074 { 00075 CV_Assert( img.type() == CV_8UC3 ); 00076 00077 cv::Mat temp = img.clone(); 00078 00079 uchar* data = img.data; 00080 uchar* data2 = temp.data; 00081 int stride = img.step; 00082 for (int repetitions=0; repetitions<10; repetitions++) 00083 { 00084 // each pixel with a value can propagate its value to black pixels in the 4 pixel neighborhoud 00085 for (int v=1; v<img.rows-1; v++) 00086 { 00087 for (int u=1; u<img.cols-1; u++) 00088 { 00089 // only pixels with a value can propagate their value 00090 int index = v*stride + 3*u; 00091 if (data[index] != 0) 00092 { 00093 uchar val = data[index]; 00094 if (data2[index-3] == 0) for (int i=-3; i<0; i++) data2[index+i] = val; // left 00095 if (data2[index+3] == 0) for (int i=3; i<6; i++) data2[index+i] = val; // right 00096 if (data2[index-stride] == 0) for (int i=-stride; i<-stride+3; i++) data2[index+i] = val; // up 00097 if (data2[index+stride] == 0) for (int i=stride; i<stride+3; i++) data2[index+i] = val; // down 00098 } 00099 } 00100 } 00101 // copy back new data 00102 for (int i=0; i<img.rows*stride; i++) data[i] = data2[i]; 00103 } 00104 return ipa_Utils::RET_OK; 00105 } 00106 00107 unsigned long PeopleDetector::DetectRangeFace(cv::Mat& img, std::vector<cv::Rect>& rangeFaceCoordinates, bool fillUnassignedDepthValues) 00108 { 00109 rangeFaceCoordinates.clear(); 00110 00111 if (fillUnassignedDepthValues) InterpolateUnassignedPixels(img); 00112 //cv::namedWindow("depth image"); 00113 //cv::imshow("depth image", img); 00114 //cv::waitKey(10); 00115 IplImage imgPtr = (IplImage)img; 00116 CvSeq* rangeFaces = cvHaarDetectObjects 00117 ( 00118 &imgPtr, 00119 m_range_cascade, 00120 m_storage, 00121 m_range_increase_search_scale, 00122 m_range_drop_groups, 00123 CV_HAAR_DO_CANNY_PRUNING, 00124 cvSize(m_range_min_search_scale_x, m_range_min_search_scale_y) 00125 ); 00126 00127 for(int i=0; i<rangeFaces->total; i++) 00128 { 00129 cv::Rect *rangeFace = (cv::Rect*)cvGetSeqElem(rangeFaces, i); 00130 rangeFaceCoordinates.push_back(*rangeFace); 00131 } 00132 00133 return ipa_Utils::RET_OK; 00134 } 00135 00136 unsigned long PeopleDetector::DetectFaces(cv::Mat& img, cv::Mat& rangeImg, std::vector<cv::Rect>& colorFaceCoordinates, std::vector<cv::Rect>& rangeFaceCoordinates, std::set<size_t>& colorToRangeFaceDependency, bool fillUnassignedDepthValues) 00137 { 00138 colorFaceCoordinates.clear(); 00139 colorToRangeFaceDependency.clear(); 00140 00141 //######################################## Option1 ######################################## 00142 DetectRangeFace(rangeImg, rangeFaceCoordinates, fillUnassignedDepthValues); 00143 for(int i=0; i<(int)rangeFaceCoordinates.size(); i++) 00144 { 00145 cv::Rect rangeFace = rangeFaceCoordinates[i]; 00146 00147 rangeFace.y += (int)(rangeFace.height*0.1); 00148 00149 cv::Mat areaImg = img(rangeFace); 00150 00151 // Detect color Faces and store the corresponding range face index if images were found 00152 size_t numberColorFacesBefore = colorFaceCoordinates.size(); 00153 DetectColorFaces(areaImg, colorFaceCoordinates); 00154 if ((colorFaceCoordinates.size()-numberColorFacesBefore) != 0) colorToRangeFaceDependency.insert(i); 00155 } 00156 //######################################## /Option1 ######################################## 00157 00158 //######################################## Option2 ######################################## 00159 /*DetectRangeFace(rangeImg, rangeFaceCoordinates); 00160 IplImage imgPtr = (IplImage)img; 00161 IplImage* areaImg = cvCloneImage(&imgPtr); 00162 char* rowPtr = 0; 00163 for (int row=0; row<areaImg->height; row++ ) 00164 { 00165 rowPtr = (char*)(areaImg->imageData + row*areaImg->widthStep); 00166 for (int col=0; col<areaImg->width; col++ ) 00167 { 00168 bool inrect=false; 00169 for(int i=0; i<(int)rangeFaceCoordinates->size(); i++) 00170 { 00171 cv::Rect rangeFace = rangeFaceCoordinates[i]; 00172 00173 rangeFace.y += rangeFace.height*0.1; 00174 00175 if((col > rangeFace.x && col < (rangeFace.x + rangeFace.width)) && (row > rangeFace.y && row < (rangeFace.y + rangeFace.height))) 00176 { 00177 inrect=true; 00178 break; 00179 } 00180 } 00181 00182 if(!inrect) 00183 { 00184 rowPtr[col*3] = 0; 00185 rowPtr[col*3+1] = 0; 00186 rowPtr[col*3+2] = 0; 00187 } 00188 } 00189 } 00190 00191 // Detect color Faces 00192 cv::Mat areaImgMat(areaImg); 00193 DetectColorFaces(areaImgMat, colorFaceCoordinates); 00194 areaImgMat.release(); 00195 cvReleaseImage(&areaImg);*/ 00196 //######################################## /Option2 ######################################## 00197 00198 return ipa_Utils::RET_OK; 00199 } 00200 00201 unsigned long PeopleDetector::AddFace(cv::Mat& img, cv::Rect& face, std::string id, std::vector<cv::Mat>& images, std::vector<std::string>& ids) 00202 { 00203 //IplImage *resized_8U1 = cvCreateImage(cvSize(100, 100), 8, 1); 00204 cv::Mat resized_8U1(100, 100, CV_8UC1); 00205 ConvertAndResize(img, resized_8U1, face); 00206 00207 // Save image 00208 images.push_back(resized_8U1); 00209 ids.push_back(id); 00210 00211 return ipa_Utils::RET_OK; 00212 } 00213 00214 unsigned long PeopleDetector::ConvertAndResize(cv::Mat& img, cv::Mat& resized, cv::Rect& face) 00215 { 00216 cv::Mat temp; 00217 cv::cvtColor(img, temp, CV_BGR2GRAY); 00218 cv::Mat roi = temp(face); 00219 cv::resize(roi, resized, resized.size()); 00220 00221 return ipa_Utils::RET_OK; 00222 } 00223 00224 cv::Mat PeopleDetector::preprocessImage(cv::Mat& input_image) 00225 { 00226 // todo: 00227 return input_image; 00228 00229 // do a modified census transform 00230 cv::Mat output(input_image.cols, input_image.rows, input_image.type()); 00231 //cv::Mat smoothedImage = input_image.clone(); 00232 //cv::GaussianBlur(smoothedImage, smoothedImage, cv::Size(3,3), 0, 0, cv::BORDER_REPLICATE); 00233 00234 for (int v=0; v<input_image.rows; v++) 00235 { 00236 uchar* srcPtr = input_image.ptr(v); 00237 //uchar* smoothPtr = smoothedImage.ptr(v); 00238 uchar* outPtr = output.ptr(v); 00239 for (int u=0; u<input_image.cols; u++) 00240 { 00241 int ctOutcome = 0; 00242 int offset = -1; 00243 for (int dv=-1; dv<=1; dv++) 00244 { 00245 for (int du=-1; du<=1; du++) 00246 { 00247 if (dv==0 && du==0) continue; 00248 offset++; 00249 if (v+dv<0 || v+dv>=input_image.rows || u+du<0 || u+du>=input_image.cols) continue; 00250 //if (*smoothPtr < *(srcPtr+dv*input_image.step+du)) ctOutcome += 1<<offset; 00251 if (*srcPtr < *(srcPtr+dv*input_image.step+du)) ctOutcome += 1<<offset; 00252 } 00253 } 00254 *outPtr = ctOutcome; 00255 00256 srcPtr++; 00257 outPtr++; 00258 } 00259 } 00260 00261 // cv::imshow("census transform", output); 00262 // cv::waitKey(); 00263 00264 return output; 00265 } 00266 00267 unsigned long PeopleDetector::PCA(int* nEigens, std::vector<cv::Mat>& eigenVectors, cv::Mat& eigenValMat, cv::Mat& avgImage, std::vector<cv::Mat>& faceImages, cv::Mat& projectedTrainFaceMat) 00268 { 00269 CvTermCriteria calcLimit; 00270 00271 // Set the number of eigenvalues to use 00272 (*nEigens) = faceImages.size()-1; 00273 00274 // Allocate memory 00275 cv::Size faceImgSize(faceImages[0].cols, faceImages[0].rows); 00276 eigenVectors.resize(*nEigens, cv::Mat(faceImgSize, CV_32FC1)); 00277 eigenValMat.create(1, *nEigens, CV_32FC1); 00278 avgImage.create(faceImgSize, CV_32FC1); 00279 00280 // Set the PCA termination criterion 00281 calcLimit = cvTermCriteria(CV_TERMCRIT_ITER, (*nEigens), 1); 00282 00283 // Convert vector to array 00284 IplImage** faceImgArr = (IplImage**)cvAlloc((int)faceImages.size()*sizeof(IplImage*)); 00285 for(int j=0; j<(int)faceImages.size(); j++) 00286 { 00287 // todo: preprocess 00288 cv::Mat preprocessedImage = preprocessImage(faceImages[j]); 00289 IplImage temp = (IplImage)preprocessedImage; 00290 faceImgArr[j] = cvCloneImage(&temp); 00291 } 00292 00293 // Convert vector to array 00294 IplImage** eigenVectArr = (IplImage**)cvAlloc((int)eigenVectors.size()*sizeof(IplImage*)); 00295 for(int j=0; j<(int)eigenVectors.size(); j++) 00296 { 00297 IplImage temp = (IplImage)eigenVectors[j]; 00298 eigenVectArr[j] = cvCloneImage(&temp); 00299 } 00300 00301 // Compute average image, eigenvalues, and eigenvectors 00302 IplImage avgImageIpl = (IplImage)avgImage; 00303 cvCalcEigenObjects((int)faceImages.size(), (void*)faceImgArr, (void*)eigenVectArr, CV_EIGOBJ_NO_CALLBACK, 0, 0, &calcLimit, &avgImageIpl, (float*)(eigenValMat.data)); 00304 00305 // todo: 00306 cv::normalize(eigenValMat,eigenValMat, 1, 0, /*CV_L1*/CV_L2); //, 0); 0=bug? 00307 00308 // Project the training images onto the PCA subspace 00309 projectedTrainFaceMat.create(faceImages.size(), *nEigens, CV_32FC1); 00310 for(int i=0; i<(int)faceImages.size(); i++) 00311 { 00312 IplImage temp = (IplImage)faceImages[i]; 00313 cvEigenDecomposite(&temp, *nEigens, eigenVectArr, 0, 0, &avgImageIpl, (float*)projectedTrainFaceMat.data + i* *nEigens); //attention: if image step of projectedTrainFaceMat is not *nEigens * sizeof(float) then reading functions which access with (x,y) coordinates might fail 00314 }; 00315 00316 // Copy back 00317 int eigenVectorsCount = (int)eigenVectors.size(); 00318 eigenVectors.clear(); 00319 for (int i=0; i<(int)eigenVectorsCount; i++) eigenVectors.push_back(cv::Mat(eigenVectArr[i], true)); 00320 00321 // Clean 00322 for (int i=0; i<(int)faceImages.size(); i++) cvReleaseImage(&(faceImgArr[i])); 00323 for (int i=0; i<(int)eigenVectors.size(); i++) cvReleaseImage(&(eigenVectArr[i])); 00324 cvFree(&faceImgArr); 00325 cvFree(&eigenVectArr); 00326 00327 return ipa_Utils::RET_OK; 00328 } 00329 00330 unsigned long PeopleDetector::RecognizeFace(cv::Mat& colorImage, std::vector<cv::Rect>& colorFaceCoordinates, int* nEigens, std::vector<cv::Mat>& eigenVectors, cv::Mat& avgImage, cv::Mat& faceClassAvgProjections, 00331 std::vector<int>& index, int *threshold, int *threshold_FS, cv::Mat& eigenValMat, cv::SVM* personClassifier) 00332 { 00333 float* eigenVectorWeights = 0; 00334 00335 cv::Mat resized_8U1(100, 100, CV_8UC1); // = cvCreateImage(cvSize(100, 100), 8, 1); 00336 00337 eigenVectorWeights = (float *)cvAlloc(*nEigens*sizeof(float)); 00338 00339 // Convert vector to array 00340 IplImage** eigenVectArr = (IplImage**)cvAlloc((int)eigenVectors.size()*sizeof(IplImage*)); 00341 for(int j=0; j<(int)eigenVectors.size(); j++) 00342 { 00343 IplImage temp = (IplImage)eigenVectors[j]; 00344 eigenVectArr[j] = cvCloneImage(&temp); 00345 } 00346 00347 for(int i=0; i<(int)colorFaceCoordinates.size(); i++) 00348 { 00349 cv::Rect face = colorFaceCoordinates[i]; 00350 ConvertAndResize(colorImage, resized_8U1, face); 00351 // todo: preprocess 00352 cv::Mat preprocessedImage = preprocessImage(resized_8U1); 00353 00354 IplImage avgImageIpl = (IplImage)avgImage; 00355 00356 // Project the test image onto the PCA subspace 00357 IplImage resized_8U1Ipl = (IplImage)resized_8U1; 00358 cvEigenDecomposite(&resized_8U1Ipl, *nEigens, eigenVectArr, 0, 0, &avgImageIpl, eigenVectorWeights); 00359 00360 // Calculate FaceSpace Distance 00361 cv::Mat srcReconstruction = cv::Mat::zeros(eigenVectors[0].size(), eigenVectors[0].type()); 00362 for(int i=0; i<(int)eigenVectors.size(); i++) srcReconstruction += eigenVectorWeights[i]*eigenVectors[i]; 00363 cv::Mat temp; 00364 00365 // todo: 00366 // cv::Mat reconstrTemp = srcReconstruction + avgImage; 00367 // cv::Mat reconstr(eigenVectors[0].size(), CV_8UC1); 00368 // reconstrTemp.convertTo(reconstr, CV_8UC1, 1); 00369 // cv::imshow("reconstruction", reconstr); 00370 // cv::waitKey(); 00371 00372 resized_8U1.convertTo(temp, CV_32FC1, 1.0/255.0); 00373 double distance = cv::norm((temp-avgImage), srcReconstruction, cv::NORM_L2); 00374 00375 //######################################## Only for debugging and development ######################################## 00376 //std::cout.precision( 10 ); 00377 std::cout << "FS_Distance: " << distance << std::endl; 00378 //######################################## /Only for debugging and development ######################################## 00379 00380 // -2=distance to face space is too high 00381 // -1=distance to face classes is too high 00382 if(distance > *threshold_FS) 00383 { 00384 // No face 00385 index.push_back(-2); 00386 //index.push_back(-2); why twice? apparently makes no sense. 00387 } 00388 else 00389 { 00390 int nearest; 00391 ClassifyFace(eigenVectorWeights, &nearest, nEigens, faceClassAvgProjections, threshold, eigenValMat, personClassifier); 00392 if(nearest < 0) index.push_back(-1); // Face Unknown 00393 else index.push_back(nearest); // Face known, it's number nearest 00394 } 00395 } 00396 00397 // Clear 00398 for (int i=0; i<(int)eigenVectors.size(); i++) cvReleaseImage(&(eigenVectArr[i])); 00399 cvFree(&eigenVectorWeights); 00400 cvFree(&eigenVectArr); 00401 return ipa_Utils::RET_OK; 00402 } 00403 00404 unsigned long PeopleDetector::ClassifyFace(float *eigenVectorWeights, int *nearest, int *nEigens, cv::Mat& faceClassAvgProjections, int *threshold, cv::Mat& eigenValMat, cv::SVM* personClassifier) 00405 { 00406 double leastDistSq = DBL_MAX; 00407 //todo: 00408 int metric = 2; // 0 = Euklid, 1 = Mahalanobis, 2 = Mahalanobis Cosine 00409 00410 00411 for(int i=0; i<faceClassAvgProjections.rows; i++) 00412 { 00413 double distance=0; 00414 double cos=0; 00415 double length_sample=0; 00416 double length_projection=0; 00417 for(int e=0; e<*nEigens; e++) 00418 { 00419 if (metric < 2) 00420 { 00421 float d = eigenVectorWeights[e] - ((float*)(faceClassAvgProjections.data))[i * *nEigens + e]; 00422 if (metric==0) distance += d*d; //Euklid 00423 else distance += d*d /* / */ / ((float*)(eigenValMat.data))[e]; //Mahalanobis 00424 } 00425 else 00426 { 00427 cos += eigenVectorWeights[e] * ((float*)(faceClassAvgProjections.data))[i * *nEigens + e] / ((float*)(eigenValMat.data))[e]; 00428 length_projection += ((float*)(faceClassAvgProjections.data))[i * *nEigens + e] * ((float*)(faceClassAvgProjections.data))[i * *nEigens + e] / ((float*)(eigenValMat.data))[e]; 00429 length_sample += eigenVectorWeights[e]*eigenVectorWeights[e] / ((float*)(eigenValMat.data))[e]; 00430 } 00431 } 00432 if (metric < 2) 00433 distance = sqrt(distance); 00434 else 00435 { 00436 length_sample = sqrt(length_sample); 00437 length_projection = sqrt(length_projection); 00438 cos /= (length_projection * length_sample); 00439 distance = -cos; 00440 } 00441 00442 //######################################## Only for debugging and development ######################################## 00443 //std::cout.precision( 10 ); 00444 std::cout << "Distance_FC: " << distance << std::endl; 00445 //######################################## /Only for debugging and development ######################################## 00446 00447 if(distance < leastDistSq) 00448 { 00449 leastDistSq = distance; 00450 if(leastDistSq > *threshold) *nearest = -1; 00451 else *nearest = i; 00452 } 00453 } 00454 00455 // todo: 00456 // if (personClassifier != 0 && *nearest != -1) 00457 // { 00458 // cv::Mat temp(1, *nEigens, CV_32FC1, eigenVectorWeights); 00459 // std::cout << "class. output: " << (int)personClassifier->predict(temp) << "\n"; 00460 // *nearest = (int)personClassifier->predict(temp); 00461 // } 00462 00463 return ipa_Utils::RET_OK; 00464 } 00465 00466 unsigned long PeopleDetector::CalculateFaceClasses(cv::Mat& projectedTrainFaceMat, std::vector<std::string>& id, int *nEigens, cv::Mat& faceClassAvgProjections, 00467 std::vector<std::string>& idUnique, cv::SVM* personClassifier) 00468 { 00469 std::cout << "PeopleDetector::CalculateFaceClasses ... "; 00470 00471 // Look for face classes 00472 idUnique.clear(); 00473 for(int i=0; i<(int)id.size(); i++) 00474 { 00475 std::string face_class = id[i]; 00476 bool class_exists = false; 00477 00478 for(int j=0; j<(int)idUnique.size(); j++) 00479 { 00480 if(!idUnique[j].compare(face_class)) 00481 { 00482 class_exists = true; 00483 } 00484 } 00485 00486 if(!class_exists) 00487 { 00488 idUnique.push_back(face_class); 00489 } 00490 } 00491 00492 //id.clear(); 00493 //cv::Mat faces_tmp = projectedTrainFaceMat.clone(); 00494 cv::Mat temp = cv::Mat::zeros((int)idUnique.size(), *nEigens, projectedTrainFaceMat.type()); 00495 temp.convertTo(faceClassAvgProjections, projectedTrainFaceMat.type()); 00496 //for (int i=0; i<((int)idUnique.size() * *nEigens); i++) 00497 // for (int i=0; i<((int)id.size() * *nEigens); i++) 00498 // { 00499 // ((float*)(projectedTrainFaceMat.data))[i] = 0; 00500 // } 00501 00502 // Look for FaceClasses 00503 // for(int i=0; i<(int)idUnique.size(); i++) 00504 // { 00505 // std::string face_class = idUnique[i]; 00506 // bool class_exists = false; 00507 // 00508 // for(int j=0; j<(int)id.size(); j++) 00509 // { 00510 // if(!id[j].compare(face_class)) 00511 // { 00512 // class_exists = true; 00513 // } 00514 // } 00515 // 00516 // if(!class_exists) 00517 // { 00518 // id.push_back(face_class); 00519 // } 00520 // } 00521 00522 // cv::Size newSize(id.size(), *nEigens); 00523 // projectedTrainFaceMat.create(newSize, faces_tmp.type()); 00524 00525 // Calculate FaceClasses 00526 for(int i=0; i<(int)idUnique.size(); i++) 00527 { 00528 std::string face_class = idUnique[i]; 00529 00530 for(int e=0; e<*nEigens; e++) 00531 { 00532 int count=0; 00533 for(int j=0;j<(int)id.size(); j++) 00534 { 00535 if(!(id[j].compare(face_class))) 00536 { 00537 ((float*)(faceClassAvgProjections.data))[i * *nEigens + e] += ((float*)(projectedTrainFaceMat.data))[j * *nEigens + e]; 00538 count++; 00539 } 00540 } 00541 ((float*)(faceClassAvgProjections.data))[i * *nEigens + e] /= (float)count; 00542 } 00543 } 00544 00545 00546 // todo: machine learning technique for person identification 00547 if (personClassifier != 0) 00548 { 00549 //std::cout << "\n"; 00550 // prepare ground truth 00551 cv::Mat data(id.size(), *nEigens, CV_32FC1); 00552 cv::Mat labels(id.size(), 1, CV_32SC1); 00553 std::ofstream fout("svm.dat", std::ios::out); 00554 for(int sample=0; sample<(int)id.size(); sample++) 00555 { 00556 // copy data 00557 for (int e=0; e<*nEigens; e++) 00558 { 00559 data.at<float>(sample, e) = ((float*)projectedTrainFaceMat.data)[sample * *nEigens + e]; 00560 fout << data.at<float>(sample, e) << "\t"; 00561 } 00562 // find corresponding label 00563 for(int i=0; i<(int)idUnique.size(); i++) // for each person 00564 if(!(id[sample].compare(idUnique[i]))) // compare the labels 00565 labels.at<int>(sample) = i; // and assign the corresponding label's index from the idUnique list 00566 fout << labels.at<int>(sample) << "\n"; 00567 } 00568 fout.close(); 00569 00570 // train the classifier 00571 cv::SVMParams svmParams(CvSVM::NU_SVC, CvSVM::RBF, 0.0, 0.001953125, 0.0, 0.0, 0.8, 0.0, 0, cv::TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 100, FLT_EPSILON)); 00572 //personClassifier->train_auto(data, labels, cv::Mat(), cv::Mat(), svmParams, 10, cv::SVM::get_default_grid(CvSVM::C), CvParamGrid(0.001953125, 2.01, 2.0), cv::SVM::get_default_grid(CvSVM::P), CvParamGrid(0.0125, 1.0, 2.0)); 00573 personClassifier->train(data, labels, cv::Mat(), cv::Mat(), svmParams); 00574 cv::SVMParams svmParamsOptimal = personClassifier->get_params(); 00575 std::cout << "Optimal SVM params: gamma=" << svmParamsOptimal.gamma << " nu=" << svmParamsOptimal.nu << "\n"; 00576 } 00577 00578 std::cout << "done\n"; 00579 00580 return ipa_Utils::RET_OK; 00581 } 00582