PageRenderTime 82ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/FaceCapturer/faceRecognitionDLL/faceRecognition.cpp

http://facecomparerdis.codeplex.com
C++ | 434 lines | 393 code | 11 blank | 30 comment | 0 complexity | e51c2fec13593f4824997aa3df2f79e1 MD5 | raw file
  1. /*******************************************************************
  2. * Face Recognition Module
  3. * DESCRIPTION:
  4. * face data base
  5. * /__________faceNum___________\
  6. * \ /
  7. * / \ image1 image2 image3 ... imageN
  8. * | image1 image2 image3 ... imageN
  9. * | image1 image2 image3 ... imageN
  10. * | image1 image2 image3 ... imageN
  11. * imageLen image1 image2 image3 ... imageN
  12. * | image1 image2 image3 ... imageN
  13. * | image1 image2 image3 ... imageN
  14. * \ / image1 image2 image3 ... imageN
  15. * The output (similarity, float type) is stored at similarityResultPtr one by one
  16. * | similarity#1 | similarity#2 | similarity#i | similarity#N |
  17. * NOTE: similarity result#i is the similarity btw image to be recoginized and i-th train face image
  18. * AUTHOR:
  19. * Zeng Yinhui, zengyinhui@msn.com
  20. * HISTORY:
  21. * <10/21/2009><Zeng Yinhui> Init Version.
  22. * <10/24/2009><Zeng Yinhui> Updated the similarity definition
  23. * <11/03/2009><Zeng Yinhui> Updated the interface
  24. *******************************************************************/
  25. #include <stdio.h>
  26. #include <iostream>
  27. #include <limits>
  28. #include <complex>
  29. #include <algorithm>
  30. #include <vector>
  31. #include <math.h>
  32. #include <fstream>
  33. #include "Matrix.h"
  34. #include "EigenvalueVector.h" //header for eigen
  35. //openCV to pre-process img, such as img resize
  36. //#define SKIP_INCLUDES
  37. //#include <afxwin.h>
  38. //#include "stdafx.h"
  39. #include "cv.h"
  40. #include "highgui.h"
  41. #include "cxcore.h"
  42. #define PATH_MAX_LEN 200
  43. using namespace std;
  44. /*macro definition */
  45. #define ORIGINAL_IMG_WIDTH 200
  46. #define ORIGINAL_IMG_HEIGHT 200
  47. #define ORIGINAL_IMG_LEN (ORIGINAL_IMG_WIDTH*ORIGINAL_IMG_HEIGHT)
  48. struct similarityMat
  49. {
  50. float similarity;
  51. char *fileName;
  52. };
  53. /*global variable definition */
  54. string gc_imgSearchPattern = "C:\\faceRecognition\\faceSample\\*.jpg";
  55. string gc_faceSampleRoot = "C:\\faceRecognition\\faceSample\\";
  56. string gc_eigenVectorFile = "C:\\faceRecognition\\data\\EigenVector.txt";
  57. string gc_AverageValueFile = "C:\\faceRecognition\\data\\AverageValue.txt";
  58. string gc_SampleCoefficientFile = "C:\\faceRecognition\\data\\SampleCoefficient.txt";
  59. string gc_FileNameFile = "C:\\faceRecognition\\data\\FileName.txt";
  60. char** gc_sampleFileName;//????????
  61. int gi_sampleCount;
  62. matrixf* meanVectorPtr;
  63. matrixf* trainedEigenSpaceMatPtr;
  64. matrixf* signatureFaceDBPtr;
  65. /*local function definition */
  66. bool smallFront (int i,int j) { return (i<j); }
  67. bool bigFront (int i,int j) { return (i>j); }
  68. void myLog(char* myLog)
  69. {
  70. }
  71. #define TIMELOG(X) //myLog(X)
  72. //return sample count
  73. extern "C" int _declspec(dllexport) FaceTraining(int imgWidth=20, int imgHeight=20, int eigenNum=40)
  74. {
  75. //read image samples to get the number and file list.
  76. WIN32_FIND_DATA FindFileData;
  77. HANDLE hFind;
  78. int sampleCount = 0;//?????????
  79. TIMELOG("enter face training...");
  80. FILE* fp;
  81. if (fopen_s(&fp, gc_FileNameFile.c_str(),"w") != 0)
  82. {
  83. throw "File Can't be opened";
  84. }
  85. string path;
  86. hFind = FindFirstFile(gc_imgSearchPattern.c_str(), &FindFileData);
  87. if (hFind != INVALID_HANDLE_VALUE)
  88. {
  89. sampleCount++;
  90. path = gc_faceSampleRoot + FindFileData.cFileName;
  91. fprintf(fp,"%s\n", path.c_str());
  92. }
  93. while (::FindNextFile(hFind, &FindFileData ))
  94. {
  95. path = gc_faceSampleRoot + FindFileData.cFileName;
  96. fprintf(fp,"%s\n", path.c_str());
  97. sampleCount++;//?????????????
  98. }
  99. FindClose(hFind);
  100. fclose(fp);
  101. TIMELOG("load img samples to faceDBPtr...");
  102. //load img samples to faceDBPtr
  103. if (fopen_s(&fp, gc_FileNameFile.c_str(),"r") != 0)
  104. {
  105. throw "can't open file";
  106. }
  107. int i=0;
  108. IplImage *bigImg;
  109. IplImage *smallImg;
  110. smallImg = cvCreateImage(cvSize(imgWidth, imgHeight), 8, 1);
  111. int smallImgLen = imgHeight*imgWidth;
  112. int height = smallImg->height;
  113. int width = smallImg->width;
  114. int step = smallImg->widthStep;
  115. matrixf faceDBMat(smallImgLen,sampleCount);
  116. for (i=0;i<sampleCount;i++)
  117. {
  118. char sPath[PATH_MAX_LEN];
  119. fscanf_s(fp,"%s\n",sPath, PATH_MAX_LEN);
  120. bigImg = cvLoadImage(sPath, 0);
  121. assert(bigImg != NULL);
  122. cvResize(bigImg, smallImg, CV_INTER_LINEAR); //resize image to small size
  123. cvReleaseImage(&bigImg);
  124. uchar *smallImgData = (uchar*)smallImg->imageData;
  125. for (int h=0; h<height; h++)
  126. {
  127. for (int w=0; w<width; w++)
  128. {
  129. faceDBMat(h*step+w,i) = smallImgData[h*step+w];
  130. }
  131. }
  132. }
  133. fclose(fp);
  134. cvReleaseImage(&smallImg);
  135. TIMELOG("calc eigen vector/value...");
  136. //calc eigen vector/value
  137. //calc the mean matrix
  138. matrixf meanVector(smallImgLen,1); //store mean result
  139. matrixf oneVector(1,sampleCount);//
  140. matrixf meanMat(smallImgLen,sampleCount);//every column is same: meanVector
  141. matrixf faceDBzmMat(smallImgLen,sampleCount);
  142. oneVector =0*oneVector;
  143. oneVector -=-1;// oneVector = oneVector + 1;
  144. MatrixMean(faceDBMat,meanVector,2);//calc mean along with column
  145. meanMat = meanVector * oneVector;
  146. meanMat = -meanMat;
  147. faceDBzmMat = faceDBMat + meanMat; // remove mean
  148. matrixf faceDBzmMatT(sampleCount,smallImgLen);//transpose matrix
  149. MatrixTranspose(faceDBzmMat,faceDBzmMatT);
  150. matrixf eigInMat(sampleCount,sampleCount);
  151. matrixf eigVectorMat(sampleCount,sampleCount);
  152. eigInMat = faceDBzmMatT * faceDBzmMat;//////////////////////////////////////////////////////////////////////////take too much time
  153. //calc the eigen.
  154. //diagonal cell in eigInMat is eigValue.
  155. //eigVectoreMat store the eig vector
  156. //EigenvalueVectorRealSymmetryJacobiB(eigInMat,eigVectorMat,(float)0.00000000001);
  157. EigenvalueVectorRealSymmetryJacobi(eigInMat,eigVectorMat,(float)0.00000000001,200); //////////////////////////////////////////////////////////////////////////
  158. matrixf eigVectorFinalMat(smallImgLen,sampleCount); //V=single(vzm)*V;
  159. eigVectorFinalMat = faceDBzmMat * eigVectorMat;//////////////////////////////////////////////////////////////////////////too much time here
  160. float* eigValue = new float[sampleCount];
  161. for(i=0;i<sampleCount;i++){
  162. eigValue[i] = eigInMat(i,i);
  163. }
  164. vector<float> eigOriginalVector(eigValue,eigValue+sampleCount); //store eigValue into vector in order to be easy to find.
  165. vector<float> eigSortVector(eigValue,eigValue+sampleCount); //store eigValue into vector in order to be easy to find.
  166. vector<float>::iterator eigSortIt;
  167. //sort eigValue by big one in front
  168. sort(eigSortVector.begin(), eigSortVector.end(),bigFront);
  169. //pick up the eigNum eigVectors of largest eigvalue
  170. //store to trainedEigenSpaceMat, eigenNum eigen vectors are picked up.
  171. //V=V(:,end:-1:end-(N-1));
  172. matrixf trainedEigenSpaceMat(smallImgLen,eigenNum);
  173. eigSortIt = eigSortVector.begin();
  174. int offset=0;
  175. for(i=0;i<eigenNum;i++){
  176. offset = find(eigOriginalVector.begin(),eigOriginalVector.end(),*(eigSortVector.begin()+i))-eigOriginalVector.begin();//search n-th biggest eigen value.
  177. for(int row=0;row<smallImgLen;row++){
  178. trainedEigenSpaceMat(row,i) = eigVectorFinalMat(row,offset);//pick up the eigen vector with n-th biggest eigen value.
  179. }
  180. }
  181. //calc signature for each face image
  182. //Each row in signatureFaceDB is the signature for one image.
  183. matrixf signatureFaceDB(sampleCount,eigenNum);
  184. signatureFaceDB = faceDBzmMatT * trainedEigenSpaceMat;
  185. TIMELOG("store eigen vector/value/train image path to file...");
  186. //store eigen vector/value/train image path to file
  187. //store mean value, smallImgLen lines
  188. if (fopen_s(&fp, gc_AverageValueFile.c_str(),"w") != 0)
  189. {
  190. throw "can't open file";
  191. }
  192. else
  193. {
  194. for (i=0;i<smallImgLen;i++)
  195. {
  196. fprintf(fp,"%f\n",meanVector(i,0));
  197. }
  198. }
  199. fclose(fp);
  200. //store eigen vector, smallImgLen*eigenNum
  201. if (fopen_s(&fp, gc_eigenVectorFile.c_str(),"w") != 0)
  202. {
  203. throw "can't open file";
  204. }
  205. else
  206. {
  207. for (int row=0;row<smallImgLen;row++)
  208. {
  209. for (int col=0;col<eigenNum;col++)
  210. {
  211. fprintf(fp,"%12.8f ",trainedEigenSpaceMat(row,col));
  212. }
  213. fprintf(fp,"\n");
  214. }
  215. }
  216. fclose(fp);
  217. //store coefficient that sample in eigen vector, smallImgLen*eigenNum
  218. if (fopen_s(&fp, gc_SampleCoefficientFile.c_str(),"w") != 0)
  219. {
  220. throw "can't open file";
  221. }
  222. else
  223. {
  224. for (int row=0;row<sampleCount;row++)
  225. {
  226. for (int col=0;col<eigenNum;col++)
  227. {
  228. fprintf(fp,"%12.8f ",signatureFaceDB(row,col));
  229. }
  230. fprintf(fp,"\n");
  231. }
  232. }
  233. fclose(fp);
  234. TIMELOG("training is done");
  235. return sampleCount;
  236. }
  237. extern "C" bool _declspec(dllexport) InitData( int sampleCount, int imgLen=400, int eigenNum=40)
  238. {
  239. meanVectorPtr = new matrixf(imgLen,1); //store mean result
  240. trainedEigenSpaceMatPtr = new matrixf(imgLen,eigenNum);
  241. signatureFaceDBPtr = new matrixf (sampleCount,eigenNum);
  242. FILE* fp;
  243. int i;
  244. gc_sampleFileName = new char*[sampleCount];
  245. gi_sampleCount = sampleCount;
  246. if (fopen_s(&fp, gc_FileNameFile.c_str(),"r") != 0)
  247. {
  248. throw "can't open file";
  249. }
  250. for (i=0;i<sampleCount;i++)
  251. {
  252. gc_sampleFileName[i] = new char[PATH_MAX_LEN];
  253. fscanf_s(fp,"%s\n",gc_sampleFileName[i], PATH_MAX_LEN);
  254. }
  255. fclose(fp);
  256. //load eigen vector/value/train image path to file
  257. //load mean value, smallImgLen lines
  258. if (fopen_s(&fp, gc_AverageValueFile.c_str(),"r") != 0)
  259. {
  260. throw "can't open file";
  261. }
  262. else
  263. {
  264. for (i=0;i<imgLen;i++)
  265. {
  266. fscanf_s(fp,"%f\n", &((*meanVectorPtr)(i,0)));
  267. }
  268. }
  269. fclose(fp);
  270. //MatrixLinePrint(*meanVectorPtr);
  271. //load eigen vector, smallImgLen*eigenNum
  272. if (fopen_s(&fp, gc_eigenVectorFile.c_str(),"r") != 0)
  273. {
  274. throw "can't open file";
  275. }
  276. else
  277. {
  278. for (int row=0;row<imgLen;row++)
  279. {
  280. for (int col=0;col<eigenNum;col++)
  281. {
  282. fscanf_s(fp,"%f ",&((*trainedEigenSpaceMatPtr)(row,col)));
  283. }
  284. }
  285. }
  286. fclose(fp);
  287. //load coefficient that sample in eigen vector, smallImgLen*eigenNum
  288. if (fopen_s(&fp, gc_SampleCoefficientFile.c_str(),"r") != 0)
  289. {
  290. throw "can't open file";
  291. }
  292. else
  293. {
  294. for (int row=0;row<sampleCount;row++)
  295. {
  296. for (int col=0;col<eigenNum;col++)
  297. {
  298. fscanf_s(fp,"%f ",&((*signatureFaceDBPtr)(row,col)));
  299. }
  300. //fscanf(fp,"\n");
  301. }
  302. }
  303. fclose(fp);
  304. TIMELOG("IniData End");
  305. //MatrixLinePrint(*signatureFaceDBPtr);
  306. return true;
  307. }
  308. extern "C" void _declspec(dllexport) FaceRecognition(float*currentFace, int sampleCount, similarityMat* similarityPtr, int imgLen, int eigenNum=40)
  309. {
  310. TIMELOG("Entry FaceRecognition");
  311. //fill the image to be recognized into matrix
  312. matrixf imageMat(currentFace,imgLen, 1);
  313. //calc signature for image needing to be recognized
  314. matrixf signatureImage(1,eigenNum);
  315. matrixf imageZmMat(imgLen, 1);
  316. matrixf imageZmMatT(1,imgLen);
  317. imageZmMat = imageMat - (*meanVectorPtr); //col vector of imageLen,p=r-m;
  318. MatrixTranspose(imageZmMat,imageZmMatT);
  319. signatureImage = imageZmMatT * (*trainedEigenSpaceMatPtr); //s=single(p)'*V;
  320. float deltaSum=0.0;
  321. float myMin=(float)3.40282e+038;//numeric_limits<float>::max();
  322. float myMax=(float)1.17549e-038;//numeric_limits<float>::min();
  323. int faceIndex=0;
  324. //calc the normalized delta btw image and face data base image.
  325. for(faceIndex=0;faceIndex<sampleCount;faceIndex++){
  326. //fetch signature of one face, store to signatureTem
  327. deltaSum = 0.0;
  328. for(int j=0;j<eigenNum;j++){
  329. deltaSum += fabs((*signatureFaceDBPtr)(faceIndex,j) - signatureImage(0,j));
  330. }
  331. //store sum of absolute of the delta btw signatureImage & signatureFaceDB
  332. similarityPtr[faceIndex].similarity = deltaSum;
  333. //store max/min
  334. myMin = Min(myMin,deltaSum);
  335. myMax = Max(myMax,deltaSum);
  336. }
  337. //calc the percents on every trained face image: %=(face[i]-min)/(max-min)
  338. for(faceIndex=0;faceIndex<sampleCount;faceIndex++)
  339. {
  340. if (myMin<150000000)
  341. {
  342. similarityPtr[faceIndex].similarity = 1 - (similarityPtr[faceIndex].similarity-myMin) / (myMax-myMin);
  343. }
  344. else
  345. {
  346. similarityPtr[faceIndex].similarity = 0.0;
  347. }
  348. //similarityPtr[faceIndex].similarity = 1 - (similarityPtr[faceIndex].similarity-myMin) / (myMax-myMin);
  349. similarityPtr[faceIndex].fileName = gc_sampleFileName[faceIndex];
  350. }
  351. TIMELOG("End FaceRecognition");
  352. }
  353. extern "C" void _declspec(dllexport) FreeData()
  354. {
  355. for (int i=0;i<gi_sampleCount;i++)
  356. {
  357. delete []gc_sampleFileName[i];
  358. }
  359. delete []gc_sampleFileName;
  360. delete meanVectorPtr;
  361. delete trainedEigenSpaceMatPtr;
  362. delete signatureFaceDBPtr;
  363. }
  364. //end