PageRenderTime 79ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/Workspace/GC/Windows-GCFOM/GC_FaceOrientationMapper/AAM_TDM.cpp

https://github.com/sreedal/GC
C++ | 313 lines | 231 code | 56 blank | 26 comment | 22 complexity | 71437f531267dcc2a4587cbb629a9e98 MD5 | raw file
  1. /****************************************************************************
  2. * AAMLibrary
  3. * http://code.google.com/p/aam-library
  4. * Copyright (c) 2008-2009 by GreatYao, all rights reserved.
  5. ****************************************************************************/
  6. #include "stdafx.h"
  7. #include "AAM_TDM.h"
  8. #include "AAM_PAW.h"
  9. #include <direct.h>
  10. #include <io.h>
  11. //============================================================================
  12. AAM_TDM::AAM_TDM()
  13. {
  14. __MeanTexture = 0;
  15. __TextureEigenVectors = 0;
  16. __TextureEigenValues = 0;
  17. }
  18. //============================================================================
  19. AAM_TDM::~AAM_TDM()
  20. {
  21. cvReleaseMat(&__MeanTexture);
  22. cvReleaseMat(&__TextureEigenVectors);
  23. cvReleaseMat(&__TextureEigenValues);
  24. }
  25. //============================================================================
  26. void AAM_TDM::Train(const file_lists& pts_files, const file_lists& img_files,
  27. const AAM_PAW& m_warp,
  28. double texture_percentage /* = 0.975 */,
  29. bool registration /* = true */)
  30. {
  31. int nPoints = m_warp.nPoints();
  32. int nPixels = m_warp.nPix()*3;
  33. int nSamples = pts_files.size();
  34. CvMat *AllTextures = cvCreateMat(nSamples, nPixels, CV_64FC1);
  35. CvMat * matshape = cvCreateMat(1, nPoints*2, CV_64FC1);
  36. for(int i = 0; i < nSamples; i++)
  37. {
  38. IplImage* image = cvLoadImage(img_files[i].c_str(), -1);
  39. AAM_Shape trueshape;
  40. if(!trueshape.ReadAnnotations(pts_files[i]))
  41. trueshape.ScaleXY(image->width, image->height);
  42. trueshape.Point2Mat(matshape);
  43. AAM_Common::CheckShape(matshape, image->width, image->height);
  44. CvMat t; cvGetRow(AllTextures, &t, i);
  45. m_warp.CalcWarpTexture(matshape, image, &t);
  46. cvReleaseImage(&image);
  47. }
  48. cvReleaseMat(&matshape);
  49. // align texture so as to minimize the lighting variation
  50. AAM_TDM::AlignTextures(AllTextures);
  51. //now do pca
  52. DoPCA(AllTextures, texture_percentage);
  53. if(registration) SaveSeriesTemplate(AllTextures, m_warp);
  54. cvReleaseMat(&AllTextures);
  55. }
  56. //============================================================================
  57. void AAM_TDM::DoPCA(const CvMat* AllTextures, double percentage)
  58. {
  59. printf("Doing PCA of textures datas...");
  60. int nSamples = AllTextures->rows;
  61. int nPixels = AllTextures->cols;
  62. int nEigenAtMost = MIN(nSamples, nPixels);
  63. CvMat* tmpEigenValues = cvCreateMat(1, nEigenAtMost, CV_64FC1);
  64. CvMat* tmpEigenVectors = cvCreateMat(nEigenAtMost, nPixels, CV_64FC1);
  65. __MeanTexture = cvCreateMat(1, nPixels, CV_64FC1 );
  66. cvCalcPCA(AllTextures, __MeanTexture,
  67. tmpEigenValues, tmpEigenVectors, CV_PCA_DATA_AS_ROW);
  68. double allSum = cvSum(tmpEigenValues).val[0];
  69. double partSum = 0.0;
  70. int nTruncated = 0;
  71. double largesteigval = cvmGet(tmpEigenValues, 0, 0);
  72. for(int i = 0; i < nEigenAtMost; i++)
  73. {
  74. double thiseigval = cvmGet(tmpEigenValues, 0, i);
  75. if(thiseigval / largesteigval < 0.0001) break; // firstly check(remove small values)
  76. partSum += thiseigval;
  77. ++ nTruncated;
  78. if(partSum/allSum >= percentage) break; //secondly check
  79. }
  80. __TextureEigenValues = cvCreateMat(1, nTruncated, CV_64FC1);
  81. __TextureEigenVectors = cvCreateMat(nTruncated, nPixels, CV_64FC1);
  82. CvMat G;
  83. cvGetCols(tmpEigenValues, &G, 0, nTruncated);
  84. cvCopy(&G, __TextureEigenValues);
  85. cvGetRows(tmpEigenVectors, &G, 0, nTruncated);
  86. cvCopy(&G, __TextureEigenVectors);
  87. cvReleaseMat(&tmpEigenVectors);
  88. cvReleaseMat(&tmpEigenValues);
  89. printf("Done (%d/%d)\n", nTruncated, nEigenAtMost);
  90. }
  91. //============================================================================
  92. void AAM_TDM::CalcTexture(const CvMat* lamda, CvMat* t)
  93. {
  94. cvBackProjectPCA(lamda, __MeanTexture, __TextureEigenVectors, t);
  95. }
  96. //============================================================================
  97. void AAM_TDM::CalcParams(const CvMat* t, CvMat* lamda)
  98. {
  99. cvProjectPCA(t, __MeanTexture, __TextureEigenVectors, lamda);
  100. }
  101. //============================================================================
  102. void AAM_TDM::Clamp(CvMat* lamda, double s_d /* = 3.0 */)
  103. {
  104. double* fastp = lamda->data.db;
  105. double* fastv = __TextureEigenValues->data.db;
  106. int nmodes = nModes();
  107. double limit;
  108. for(int i = 0; i < nmodes; i++)
  109. {
  110. limit = s_d*sqrt(fastv[i]);
  111. if(fastp[i] > limit) fastp[i] = limit;
  112. else if(fastp[i] < -limit) fastp[i] = -limit;
  113. }
  114. }
  115. //============================================================================
  116. void AAM_TDM::AlignTextures(CvMat* AllTextures)
  117. {
  118. printf("Align textures to minimize the lighting variation ...\n");
  119. int nsamples = AllTextures->rows;
  120. int npixels = AllTextures->cols;
  121. CvMat* meanTexture = cvCreateMat(1, npixels, CV_64FC1);
  122. CvMat* lastMeanEstimate = cvCreateMat(1, npixels, CV_64FC1);
  123. CvMat* constmeanTexture = cvCreateMat(1, npixels, CV_64FC1);
  124. CvMat ti;
  125. // calculate the mean texture
  126. AAM_TDM::CalcMeanTexture(AllTextures, meanTexture);
  127. AAM_TDM::ZeroMeanUnitLength(meanTexture);
  128. cvCopy(meanTexture, constmeanTexture);
  129. // do a number of alignment iterations until convergence
  130. double diff, diff_max = 1e-6;
  131. const int max_iter = 15;
  132. for(int iter = 0; iter < max_iter; iter++)
  133. {
  134. cvCopy(meanTexture, lastMeanEstimate);
  135. //align all textures to the mean texture estimate
  136. for(int i = 0; i < nsamples; i++)
  137. {
  138. cvGetRow(AllTextures, &ti, i);
  139. AAM_TDM::NormalizeTexture(meanTexture, &ti);
  140. }
  141. //estimate new mean texture
  142. AAM_TDM::CalcMeanTexture(AllTextures, meanTexture);
  143. AAM_TDM::NormalizeTexture(constmeanTexture, meanTexture);
  144. // test if the mean estimate has converged
  145. diff = cvNorm(meanTexture, lastMeanEstimate);
  146. printf("\tAlignment iteration #%i, mean texture est. diff. = %g\n", iter, diff );
  147. if(diff <= diff_max) break;
  148. }
  149. cvReleaseMat(&meanTexture);
  150. cvReleaseMat(&lastMeanEstimate);
  151. cvReleaseMat(&constmeanTexture);
  152. }
  153. //============================================================================
  154. void AAM_TDM::CalcMeanTexture(const CvMat* AllTextures, CvMat* meanTexture)
  155. {
  156. CvMat submat;
  157. for(int i = 0; i < meanTexture->cols; i++)
  158. {
  159. cvGetCol(AllTextures, &submat, i);
  160. cvmSet(meanTexture, 0, i, cvAvg(&submat).val[0]);
  161. }
  162. }
  163. //============================================================================
  164. void AAM_TDM::NormalizeTexture(const CvMat* refTextrure, CvMat* Texture)
  165. {
  166. AAM_TDM::ZeroMeanUnitLength(Texture);
  167. double alpha = cvDotProduct(Texture, refTextrure);
  168. if(alpha != 0) cvConvertScale(Texture, Texture, 1.0/alpha, 0);
  169. }
  170. //============================================================================
  171. void AAM_TDM::ZeroMeanUnitLength(CvMat* Texture)
  172. {
  173. CvScalar mean = cvAvg(Texture);
  174. cvSubS(Texture, mean, Texture);
  175. double norm = cvNorm(Texture);
  176. cvConvertScale(Texture, Texture, 1.0/norm);
  177. }
  178. //============================================================================
  179. void AAM_TDM::SaveSeriesTemplate(const CvMat* AllTextures, const AAM_PAW& m_warp)
  180. {
  181. printf("Saving the face template image...\n");
  182. if(access("registration", 0)) _mkdir("registration");
  183. if(access("Modes", 0)) _mkdir("Modes");
  184. if(access("Tri", 0)) _mkdir("Tri");
  185. char filename[100];
  186. int i;
  187. for(i = 0; i < AllTextures->rows; i++)
  188. {
  189. CvMat oneTexture;
  190. cvGetRow(AllTextures, &oneTexture, i);
  191. sprintf(filename, "registration/%i.jpg", i);
  192. m_warp.SaveWarpTextureToImage(filename, &oneTexture);
  193. }
  194. for(int nmodes = 0; nmodes < nModes(); nmodes++)
  195. {
  196. CvMat oneVar;
  197. cvGetRow(__TextureEigenVectors, &oneVar, nmodes);
  198. sprintf(filename, "Modes/A%03i.jpg", nmodes+1);
  199. m_warp.SaveWarpTextureToImage(filename, &oneVar);
  200. }
  201. IplImage* templateimg = cvCreateImage
  202. (cvSize(m_warp.Width(), m_warp.Height()), IPL_DEPTH_8U, 3);
  203. IplImage* convexImage = cvCreateImage
  204. (cvSize(m_warp.Width(), m_warp.Height()), IPL_DEPTH_8U, 3);
  205. IplImage* TriImage = cvCreateImage
  206. (cvSize(m_warp.Width(), m_warp.Height()), IPL_DEPTH_8U, 3);
  207. m_warp.SaveWarpTextureToImage("Modes/Template.jpg", __MeanTexture);
  208. m_warp.TextureToImage(templateimg, __MeanTexture);
  209. cvSetZero(convexImage);
  210. for(i = 0; i < m_warp.nTri(); i++)
  211. {
  212. CvPoint p, q;
  213. int ind1, ind2;
  214. cvCopy(templateimg, TriImage);
  215. ind1 = m_warp.Tri(i, 0); ind2 = m_warp.Tri(i, 1);
  216. p = cvPointFrom32f(m_warp.Vertex(ind1));
  217. q = cvPointFrom32f(m_warp.Vertex(ind2));
  218. cvLine(TriImage, p, q, CV_RGB(255, 255, 255));
  219. cvLine(convexImage, p, q, CV_RGB(255, 255, 255));
  220. ind1 = m_warp.Tri(i, 1); ind2 = m_warp.Tri(i, 2);
  221. p = cvPointFrom32f(m_warp.Vertex(ind1));
  222. q = cvPointFrom32f(m_warp.Vertex(ind2));
  223. cvLine(TriImage, p, q, CV_RGB(255, 255, 255));
  224. cvLine(convexImage, p, q, CV_RGB(255, 255, 255));
  225. ind1 = m_warp.Tri(i, 2); ind2 = m_warp.Tri(i, 0);
  226. p = cvPointFrom32f(m_warp.Vertex(ind1));
  227. q = cvPointFrom32f(m_warp.Vertex(ind2));
  228. cvLine(TriImage, p, q, CV_RGB(255, 255, 255));
  229. cvLine(convexImage, p, q, CV_RGB(255, 255, 255));
  230. sprintf(filename, "Tri/%03i.jpg", i+1);
  231. cvSaveImage(filename, TriImage);
  232. }
  233. cvSaveImage("Tri/convex.jpg", convexImage);
  234. cvReleaseImage(&templateimg);
  235. cvReleaseImage(&convexImage);
  236. cvReleaseImage(&TriImage);
  237. }
  238. //============================================================================
  239. void AAM_TDM::Write(std::ofstream& os)
  240. {
  241. os << nPixels() << " " << nModes() << std::endl;
  242. os << __MeanTexture << std::endl;
  243. os << __TextureEigenValues << std::endl;
  244. os << __TextureEigenVectors << std::endl;
  245. os << std::endl;
  246. }
  247. //============================================================================
  248. void AAM_TDM::Read(std::ifstream& is)
  249. { int _npixels, _nModes;
  250. is >> _npixels >> _nModes;
  251. __MeanTexture = cvCreateMat(1, _npixels, CV_64FC1);
  252. __TextureEigenValues = cvCreateMat(1, _nModes, CV_64FC1);
  253. __TextureEigenVectors = cvCreateMat(_nModes, _npixels, CV_64FC1);
  254. is >> __MeanTexture;
  255. is >> __TextureEigenValues;
  256. is >> __TextureEigenVectors;
  257. }