PageRenderTime 48ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/sreedal/GC
C++ | 435 lines | 337 code | 65 blank | 33 comment | 26 complexity | f28f268d3a5828ef0ffa4dc3c5697c6c 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_CAM.h"
  8. //============================================================================
  9. AAM_CAM::AAM_CAM()
  10. {
  11. __MeanAppearance = 0;
  12. __AppearanceEigenValues = 0;
  13. __AppearanceEigenVectors = 0;
  14. __Qs = 0;
  15. __Qg = 0;
  16. __MeanS = 0;
  17. __MeanG = 0;
  18. __Points = 0;
  19. __Storage = 0;
  20. __pq = 0;
  21. __a = 0;
  22. }
  23. //============================================================================
  24. AAM_CAM::~AAM_CAM()
  25. {
  26. cvReleaseMat(&__MeanAppearance);
  27. cvReleaseMat(&__AppearanceEigenValues);
  28. cvReleaseMat(&__AppearanceEigenVectors);
  29. cvReleaseMat(&__Qg);
  30. cvReleaseMat(&__Qs);
  31. cvReleaseMat(&__MeanS);
  32. cvReleaseMat(&__MeanG);
  33. cvReleaseMat(&__Points);
  34. cvReleaseMemStorage(&__Storage);
  35. cvReleaseMat(&__pq);
  36. cvReleaseMat(&__a);
  37. }
  38. //============================================================================
  39. void AAM_CAM::Train(const file_lists& pts_files,
  40. const file_lists& img_files,
  41. double scale /* = 1.0 */,
  42. double shape_percentage /* = 0.95 */,
  43. double texture_percentage /* = 0.95 */,
  44. double appearance_percentage /* = 0.95 */)
  45. {
  46. //building shape and texture distribution model
  47. std::vector<AAM_Shape> AllShapes;
  48. for(int ii = 0; ii < pts_files.size(); ii++)
  49. {
  50. AAM_Shape Shape;
  51. bool flag = Shape.ReadAnnotations(pts_files[ii]);
  52. if(!flag)
  53. {
  54. IplImage* image = cvLoadImage(img_files[ii].c_str(), -1);
  55. Shape.ScaleXY(image->width, image->height);
  56. cvReleaseImage(&image);
  57. }
  58. AllShapes.push_back(Shape);
  59. }
  60. printf("Build point distribution model...\n");
  61. __shape.Train(AllShapes, scale, shape_percentage);
  62. printf("Build warp information of mean shape mesh...");
  63. __Points = cvCreateMat (1, __shape.nPoints(), CV_32FC2);
  64. __Storage = cvCreateMemStorage(0);
  65. AAM_Shape refShape = __shape.__AAMRefShape/* * scale */;
  66. __paw.Train(refShape, __Points, __Storage);
  67. printf("[%d by %d, %d triangles, %d*3 pixels]\n",
  68. __paw.Width(), __paw.Height(), __paw.nTri(), __paw.nPix());
  69. printf("Build texture distribution model...\n");
  70. __texture.Train(pts_files, img_files, __paw, texture_percentage, true);
  71. __pq = cvCreateMat(1, __shape.nModes()+4, CV_64FC1);
  72. printf("Build combined appearance model...\n");
  73. int nsamples = pts_files.size();
  74. int npointsby2 = __shape.nPoints()*2;
  75. int npixels = __texture.nPixels();
  76. int nfeatures = __shape.nModes() + __texture.nModes();
  77. CvMat* AllAppearances = cvCreateMat(nsamples, nfeatures, CV_64FC1);
  78. CvMat* s = cvCreateMat(1, npointsby2, CV_64FC1);
  79. CvMat* t = cvCreateMat(1, npixels, CV_64FC1);
  80. __MeanS = cvCreateMat(1, npointsby2, CV_64FC1);
  81. __MeanG = cvCreateMat(1, npixels, CV_64FC1);
  82. cvCopy(__shape.GetMean(), __MeanS);
  83. cvCopy(__texture.GetMean(), __MeanG);
  84. //calculate ratio of shape to appearance
  85. CvScalar Sum1 = cvSum(__shape.__ShapesEigenValues);
  86. CvScalar Sum2 = cvSum(__texture.__TextureEigenValues);
  87. __WeightsS2T = sqrt(Sum2.val[0] / Sum1.val[0]);
  88. for(int i = 0; i < nsamples; i++)
  89. {
  90. //Get Shape and Texture respectively
  91. IplImage* image = cvLoadImage(img_files[i].c_str(), -1);
  92. AAM_Shape Shape;
  93. if(!Shape.ReadAnnotations(pts_files[i]))
  94. Shape.ScaleXY(image->width, image->height);
  95. Shape.Point2Mat(s);
  96. __paw.CalcWarpTexture(s, image, t);
  97. __texture.NormalizeTexture(__MeanG, t);
  98. //combine shape and texture parameters
  99. CvMat OneAppearance;
  100. cvGetRow(AllAppearances, &OneAppearance, i);
  101. ShapeTexture2Combined(s, t, &OneAppearance);
  102. cvReleaseImage(&image);
  103. }
  104. //Do PCA of appearances
  105. DoPCA(AllAppearances, appearance_percentage);
  106. int np = __AppearanceEigenVectors->rows;
  107. printf("Extracting the shape and texture part of the combined eigen vectors..\n");
  108. // extract the shape part of the combined eigen vectors
  109. CvMat Ps;
  110. cvGetCols(__AppearanceEigenVectors, &Ps, 0, __shape.nModes());
  111. __Qs = cvCreateMat(np, npointsby2, CV_64FC1);
  112. cvMatMul(&Ps, __shape.GetBases(), __Qs);
  113. cvConvertScale(__Qs, __Qs, 1.0/__WeightsS2T);
  114. // extract the texture part of the combined eigen vectors
  115. CvMat Pg;
  116. cvGetCols(__AppearanceEigenVectors, &Pg, __shape.nModes(), nfeatures);
  117. __Qg = cvCreateMat(np, npixels, CV_64FC1);
  118. cvMatMul(&Pg, __texture.GetBases(), __Qg);
  119. __a = cvCreateMat(1, __AppearanceEigenVectors->cols, CV_64FC1);
  120. }
  121. //============================================================================
  122. void AAM_CAM::ShapeTexture2Combined(const CvMat* Shape, const CvMat* Texture,
  123. CvMat* Appearance)
  124. {
  125. __shape.CalcParams(Shape, __pq);
  126. CvMat mat1, mat2;
  127. cvGetCols(__pq, &mat1, 4, 4+__shape.nModes());
  128. cvGetCols(Appearance, &mat2, 0, __shape.nModes());
  129. cvCopy(&mat1, &mat2);
  130. cvConvertScale(&mat2, &mat2, __WeightsS2T);
  131. cvGetCols(Appearance, &mat2, __shape.nModes(), __shape.nModes()+__texture.nModes());
  132. __texture.CalcParams(Texture, &mat2);
  133. }
  134. //============================================================================
  135. void AAM_CAM::DoPCA(const CvMat* AllAppearances, double percentage)
  136. {
  137. printf("Doing PCA of appearance datas...");
  138. int nSamples = AllAppearances->rows;
  139. int nfeatures = AllAppearances->cols;
  140. int nEigenAtMost = MIN(nSamples, nfeatures);
  141. CvMat* tmpEigenValues = cvCreateMat(1, nEigenAtMost, CV_64FC1);
  142. CvMat* tmpEigenVectors = cvCreateMat(nEigenAtMost, nfeatures, CV_64FC1);
  143. __MeanAppearance = cvCreateMat(1, nfeatures, CV_64FC1 );
  144. cvCalcPCA(AllAppearances, __MeanAppearance,
  145. tmpEigenValues, tmpEigenVectors, CV_PCA_DATA_AS_ROW);
  146. double allSum = cvSum(tmpEigenValues).val[0];
  147. double partSum = 0.0;
  148. int nTruncated = 0;
  149. double largesteigval = cvmGet(tmpEigenValues, 0, 0);
  150. for(int i = 0; i < nEigenAtMost; i++)
  151. {
  152. double thiseigval = cvmGet(tmpEigenValues, 0, i);
  153. if(thiseigval / largesteigval < 0.0001) break; // firstly check
  154. partSum += thiseigval;
  155. ++ nTruncated;
  156. if(partSum/allSum >= percentage) break; //secondly check
  157. }
  158. __AppearanceEigenValues = cvCreateMat(1, nTruncated, CV_64FC1);
  159. __AppearanceEigenVectors = cvCreateMat(nTruncated, nfeatures, CV_64FC1);
  160. CvMat G;
  161. cvGetCols(tmpEigenValues, &G, 0, nTruncated);
  162. cvCopy(&G, __AppearanceEigenValues);
  163. cvGetRows(tmpEigenVectors, &G, 0, nTruncated);
  164. cvCopy(&G, __AppearanceEigenVectors);
  165. cvReleaseMat(&tmpEigenVectors);
  166. cvReleaseMat(&tmpEigenValues);
  167. printf("Done (%d/%d)\n", nTruncated, nEigenAtMost);
  168. }
  169. //============================================================================
  170. void AAM_CAM::CalcLocalShape(CvMat* s, const CvMat* c)
  171. {
  172. cvMatMul(c, __Qs, s);
  173. cvAdd(s, __MeanS, s);
  174. }
  175. //============================================================================
  176. void AAM_CAM::CalcGlobalShape(CvMat* s, const CvMat* pose)
  177. {
  178. int npoints = s->cols/2;
  179. double* fasts = s->data.db;
  180. double a=cvmGet(pose,0,0)+1, b=cvmGet(pose,0,1),
  181. tx=cvmGet(pose,0,2), ty=cvmGet(pose,0,3);
  182. double x, y;
  183. for(int i = 0; i < npoints; i++)
  184. {
  185. x = fasts[2*i ];
  186. y = fasts[2*i+1];
  187. fasts[2*i ] = a*x-b*y+tx;
  188. fasts[2*i+1] = b*x+a*y+ty;
  189. }
  190. }
  191. //============================================================================
  192. void AAM_CAM::CalcTexture(CvMat* t, const CvMat* c)
  193. {
  194. cvMatMul(c, __Qg, t);
  195. cvAdd(t, __MeanG, t);
  196. }
  197. //============================================================================
  198. void AAM_CAM::CalcParams(CvMat* c, const CvMat* bs, const CvMat* bg)
  199. {
  200. double* fasta = __a->data.db;
  201. double* fastbs = bs->data.db;
  202. double* fastbg = bg->data.db;
  203. int i;
  204. for(i = 0; i < bs->cols; i++) fasta[i] = __WeightsS2T * fastbs[i];
  205. for(i = 0; i < bg->cols; i++) fasta[i+bs->cols] = fastbg[i];
  206. cvProjectPCA(__a, __MeanAppearance, __AppearanceEigenVectors, c);
  207. }
  208. //============================================================================
  209. void AAM_CAM::Clamp(CvMat* c, double s_d /* = 3.0 */)
  210. {
  211. double* fastc = c->data.db;
  212. double* fastv = __AppearanceEigenValues->data.db;
  213. int nmodes = nModes();
  214. double limit;
  215. for(int i = 0; i < nmodes; i++)
  216. {
  217. limit = s_d*sqrt(fastv[i]);
  218. if(fastc[i] > limit) fastc[i] = limit;
  219. else if(fastc[i] < -limit) fastc[i] = -limit;
  220. }
  221. }
  222. //============================================================================
  223. void AAM_CAM::DrawAppearance(IplImage* image, const AAM_Shape& Shape, CvMat* Texture)
  224. {
  225. AAM_PAW paw;
  226. int x1, x2, y1, y2, idx1 = 0, idx2 = 0;
  227. int tri_idx, v1, v2, v3;
  228. int minx, miny, maxx, maxy;
  229. paw.Train(Shape, __Points, __Storage, __paw.GetTri(), false);
  230. AAM_Shape refShape = __paw.__referenceshape;
  231. double minV, maxV;
  232. cvMinMaxLoc(Texture, &minV, &maxV);
  233. cvConvertScale(Texture, Texture, 1/(maxV-minV)*255, -minV*255/(maxV-minV));
  234. minx = Shape.MinX(); miny = Shape.MinY();
  235. maxx = Shape.MaxX(); maxy = Shape.MaxY();
  236. for(int y = miny; y < maxy; y++)
  237. {
  238. y1 = y-miny;
  239. for(int x = minx; x < maxx; x++)
  240. {
  241. x1 = x-minx;
  242. idx1 = paw.Rect(y1, x1);
  243. if(idx1 >= 0)
  244. {
  245. tri_idx = paw.PixTri(idx1);
  246. v1 = paw.Tri(tri_idx, 0);
  247. v2 = paw.Tri(tri_idx, 1);
  248. v3 = paw.Tri(tri_idx, 2);
  249. x2 = paw.Alpha(idx1)*refShape[v1].x + paw.Belta(idx1)*refShape[v2].x +
  250. paw.Gamma(idx1)*refShape[v3].x;
  251. y2 = paw.Alpha(idx1)*refShape[v1].y + paw.Belta(idx1)*refShape[v2].y +
  252. paw.Gamma(idx1)*refShape[v3].y;
  253. idx2 = __paw.Rect(y2, x2);
  254. if(idx2 < 0) continue;
  255. CV_IMAGE_ELEM(image, byte, y, 3*x) = cvmGet(Texture, 0, 3*idx2);
  256. CV_IMAGE_ELEM(image, byte, y, 3*x+1) = cvmGet(Texture, 0, 3*idx2+1);
  257. CV_IMAGE_ELEM(image, byte, y, 3*x+2) = cvmGet(Texture, 0, 3*idx2+2);
  258. }
  259. }
  260. }
  261. }
  262. //============================================================================
  263. void AAM_CAM::Write(std::ofstream& os)
  264. {
  265. __shape.Write(os);
  266. __texture.Write(os);
  267. __paw.Write(os);
  268. os << __AppearanceEigenVectors->rows << " " << __AppearanceEigenVectors->cols
  269. << " " << __WeightsS2T << std::endl;
  270. os << __MeanAppearance;
  271. os << __AppearanceEigenValues;
  272. os << __AppearanceEigenVectors;
  273. os << __Qs;
  274. os << __Qg;
  275. os << __MeanS;
  276. os << __MeanG;
  277. }
  278. //============================================================================
  279. void AAM_CAM::Read(std::ifstream& is)
  280. {
  281. __shape.Read(is);
  282. __texture.Read(is);
  283. __paw.Read(is);
  284. int np, nfeatures;
  285. is >> np >> nfeatures >> __WeightsS2T;
  286. __MeanAppearance = cvCreateMat(1, nfeatures, CV_64FC1);
  287. __AppearanceEigenValues = cvCreateMat(1, np, CV_64FC1);
  288. __AppearanceEigenVectors = cvCreateMat(np, nfeatures, CV_64FC1);
  289. __Qs = cvCreateMat(np, __shape.nPoints()*2, CV_64FC1);
  290. __Qg = cvCreateMat(np, __texture.nPixels(), CV_64FC1);
  291. __MeanS = cvCreateMat(1, __shape.nPoints()*2, CV_64FC1);
  292. __MeanG = cvCreateMat(1, __texture.nPixels(), CV_64FC1);
  293. is >> __MeanAppearance;
  294. is >> __AppearanceEigenValues;
  295. is >> __AppearanceEigenVectors;
  296. is >> __Qs;
  297. is >> __Qg;
  298. is >> __MeanS;
  299. is >> __MeanG;
  300. __Points = cvCreateMat (1, __shape.nPoints(), CV_32FC2);
  301. __Storage = cvCreateMemStorage(0);
  302. __pq = cvCreateMat(1, __shape.nModes()+4, CV_64FC1);
  303. __a = cvCreateMat(1, __AppearanceEigenVectors->cols, CV_64FC1);
  304. }
  305. //============================================================================
  306. static AAM_CAM *g_cam;
  307. static const int n = 6;//appearance modes
  308. static int b_c[n];
  309. static const int offset = 40;
  310. static CvMat* c = 0;//conbined appearance parameters
  311. static CvMat* s = 0;//shape instance
  312. static CvMat* t = 0;//texture instance
  313. static IplImage* image = 0;
  314. static AAM_Shape aam_s;
  315. //============================================================================
  316. //============================================================================
  317. void ontrackcam(int pos)
  318. {
  319. if(c == 0)
  320. {
  321. c = cvCreateMat(1, g_cam->nModes(), CV_64FC1);cvZero(c);
  322. s = cvCreateMat(1, g_cam->__shape.nPoints()*2, CV_64FC1);
  323. t = cvCreateMat(1, g_cam->__texture.nPixels(), CV_64FC1);
  324. }
  325. double var;
  326. //registrate appearance parameters
  327. for(int i = 0; i < n; i++)
  328. {
  329. var = 3*sqrt(g_cam->Var(i))*(double(b_c[i])/offset-1.0);
  330. cvmSet(c, 0, i, var);
  331. }
  332. //generate shape and texture instance
  333. g_cam->CalcLocalShape(s, c);
  334. g_cam->CalcTexture(t, c);
  335. //warp texture instance from base mesh to current shape instance
  336. aam_s.Mat2Point(s);
  337. int w = aam_s.GetWidth(), h = aam_s.MaxY()-aam_s.MinY();
  338. aam_s.Translate(w, h);
  339. if(image == 0)image = cvCreateImage(cvSize(w*2,h*2), 8, 3);
  340. cvSet(image, cvScalar(128, 128, 128));
  341. g_cam->DrawAppearance(image, aam_s, t);
  342. cvNamedWindow("Combined Appearance Model",1);
  343. cvShowImage("Combined Appearance Model", image);
  344. if(cvWaitKey(10) == '27')
  345. {
  346. cvReleaseImage(&image);
  347. cvReleaseMat(&s);
  348. cvReleaseMat(&t);
  349. cvReleaseMat(&c);
  350. cvDestroyWindow("Parameters");
  351. cvDestroyWindow("Combined Appearance Model");
  352. }
  353. }
  354. //============================================================================
  355. void AAM_CAM::ShowVariation()
  356. {
  357. printf("Show modes of appearance variations...\n");
  358. cvNamedWindow("Parameters",1);
  359. //create trackbars for appearance
  360. for(int i = 0; i < n; i++)
  361. {
  362. char barname[100];
  363. sprintf(barname, "a %d", i);
  364. b_c[i] = offset;
  365. cvCreateTrackbar(barname, "Parameters", &b_c[i], 2*offset+1, ontrackcam);
  366. }
  367. g_cam = this;
  368. ontrackcam(1);
  369. cvWaitKey(0);
  370. }