PageRenderTime 78ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/external/opencv/cvaux/src/cvfacedetection.cpp

https://gitlab.com/brian0218/rk3188_r-box_android4.2.2_sdk
C++ | 486 lines | 325 code | 98 blank | 63 comment | 50 complexity | 5fe17c6b520cd7bbd3b6e6937f578a8c MD5 | raw file
  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // Intel License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2000, Intel Corporation, all rights reserved.
  14. // Third party copyrights are property of their respective owners.
  15. //
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistribution's of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. //
  22. // * Redistribution's in binary form must reproduce the above copyright notice,
  23. // this list of conditions and the following disclaimer in the documentation
  24. // and/or other materials provided with the distribution.
  25. //
  26. // * The name of Intel Corporation may not be used to endorse or promote products
  27. // derived from this software without specific prior written permission.
  28. //
  29. // This software is provided by the copyright holders and contributors "as is" and
  30. // any express or implied warranties, including, but not limited to, the implied
  31. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  32. // In no event shall the Intel Corporation or contributors be liable for any direct,
  33. // indirect, incidental, special, exemplary, or consequential damages
  34. // (including, but not limited to, procurement of substitute goods or services;
  35. // loss of use, data, or profits; or business interruption) however caused
  36. // and on any theory of liability, whether in contract, strict liability,
  37. // or tort (including negligence or otherwise) arising in any way out of
  38. // the use of this software, even if advised of the possibility of such damage.
  39. //
  40. //M*/
  41. ///////////////////////////////////////////////
  42. //// Created by Khudyakov V.A. bober@gorodok.net
  43. //////////////////////////////////////////////
  44. // FaceDetection.cpp: implementation of the FaceDetection class.
  45. //
  46. //////////////////////////////////////////////////////////////////////
  47. #include "_cvaux.h"
  48. #include "_cvfacedetection.h"
  49. int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata);
  50. //////////////////////////////////////////////////////////////////////
  51. // Construction/Destruction
  52. //////////////////////////////////////////////////////////////////////
  53. FaceDetection::FaceDetection()
  54. {
  55. m_imgGray = NULL;
  56. m_imgThresh = NULL;
  57. m_mstgContours = NULL;
  58. memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
  59. m_mstgRects = NULL;
  60. m_seqRects = NULL;
  61. m_iNumLayers = 16;
  62. assert(m_iNumLayers <= MAX_LAYERS);
  63. m_pFaceList = new List();
  64. m_bBoosting = false;
  65. }// FaceDetection()
  66. FaceDetection::~FaceDetection()
  67. {
  68. if (m_imgGray)
  69. cvReleaseImage(&m_imgGray);
  70. if (m_imgThresh)
  71. cvReleaseImage(&m_imgThresh);
  72. if (m_mstgContours)
  73. cvReleaseMemStorage(&m_mstgContours);
  74. if (m_mstgRects)
  75. cvReleaseMemStorage(&m_mstgRects);
  76. }// ~FaceDetection()
  77. void FaceDetection::FindContours(IplImage* imgGray)
  78. {
  79. ReallocImage(&m_imgThresh, cvGetSize(imgGray), 1);
  80. if (NULL == m_imgThresh)
  81. return;
  82. //
  83. int iNumLayers = m_iNumLayers;
  84. int iMinLevel = 0, iMaxLevel = 255, iStep = 255 / iNumLayers;
  85. ThresholdingParam(imgGray, iNumLayers, iMinLevel, iMaxLevel, iStep);
  86. // init
  87. cvReleaseMemStorage(&m_mstgContours);
  88. m_mstgContours = cvCreateMemStorage();
  89. if (NULL == m_mstgContours)
  90. return;
  91. memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
  92. cvReleaseMemStorage(&m_mstgRects);
  93. m_mstgRects = cvCreateMemStorage();
  94. if (NULL == m_mstgRects)
  95. return;
  96. m_seqRects = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvContourRect), m_mstgRects);
  97. if (NULL == m_seqRects)
  98. return;
  99. // find contours
  100. for (int l = iMinLevel, i = 0; l < iMaxLevel; l += iStep, i++)
  101. {
  102. cvThreshold(imgGray, m_imgThresh, (double)l, (double)255, CV_THRESH_BINARY);
  103. if (cvFindContours(m_imgThresh, m_mstgContours, &m_seqContours[i], sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE))
  104. AddContours2Rect(m_seqContours[i], l, i);
  105. }
  106. // sort rects
  107. cvSeqSort(m_seqRects, CompareContourRect, NULL);
  108. }// void FaceDetection::FindContours(IplImage* imgGray)
  109. #define GIST_STEP 10
  110. #define GIST_NUM (256 / GIST_STEP)
  111. #define GIST_MIN 32
  112. void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
  113. {
  114. assert(imgGray != NULL);
  115. assert(imgGray->nChannels == 1);
  116. int i, j;
  117. // create gistogramm
  118. uchar* buffImg = (uchar*)imgGray->imageData;
  119. int gistImg[GIST_NUM + 1] = {0};
  120. for (j = 0; j < imgGray->height; j ++)
  121. {
  122. for (i = 0; i < imgGray->width; i ++)
  123. {
  124. int ind = buffImg[i] / GIST_STEP;
  125. gistImg[ind] ++;
  126. }
  127. buffImg += imgGray->widthStep;
  128. }
  129. // params
  130. for (i = 0; i <= GIST_NUM; i ++)
  131. {
  132. if (gistImg[i] >= GIST_MIN)
  133. break;
  134. }
  135. iMinLevel = i * GIST_STEP;
  136. for (i = GIST_NUM; i >= 0; i --)
  137. {
  138. if (gistImg[i] >= GIST_MIN)
  139. break;
  140. }
  141. iMaxLevel = i * GIST_STEP;
  142. int dLevels = iMaxLevel - iMinLevel;
  143. if (dLevels <= 0)
  144. {
  145. iMinLevel = 0;
  146. iMaxLevel = 255;
  147. }
  148. else if (dLevels <= iNumLayers)
  149. {
  150. iMinLevel = iMaxLevel - iNumLayers;
  151. if (iMinLevel < 0)
  152. {
  153. iMinLevel = 0;
  154. iMaxLevel = iNumLayers;
  155. }
  156. }
  157. iStep = (iMaxLevel - iMinLevel) / iNumLayers;
  158. }// void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
  159. #ifndef MAX_ERROR
  160. #define MAX_ERROR 0xFFFFFFFF
  161. #endif //MAX_ERROR
  162. void FaceDetection::CreateResults(CvSeq * lpSeq)
  163. {
  164. Face * tmp;
  165. double Max = 0;
  166. double CurStat = 0;
  167. FaceData tmpData;
  168. if (m_bBoosting)
  169. {
  170. tmp = m_pFaceList->GetData();
  171. tmp->CreateFace(&tmpData);
  172. CvFace tmpFace;
  173. tmpFace.MouthRect = tmpData.MouthRect;
  174. tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
  175. tmpFace.RightEyeRect = tmpData.RightEyeRect;
  176. cvSeqPush(lpSeq,&tmpFace);
  177. }else
  178. {
  179. while ( (tmp = m_pFaceList->GetData()) != 0 )
  180. {
  181. CurStat = tmp->GetWeight();
  182. if (CurStat > Max)
  183. Max = CurStat;
  184. }
  185. while ( (tmp = m_pFaceList->GetData()) != 0 )
  186. {
  187. tmp->CreateFace(&tmpData);
  188. CurStat = tmp->GetWeight();
  189. if (CurStat == Max)
  190. {
  191. CvFace tmpFace;
  192. tmpFace.MouthRect = tmpData.MouthRect;
  193. tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
  194. tmpFace.RightEyeRect = tmpData.RightEyeRect;
  195. cvSeqPush(lpSeq,&tmpFace);
  196. }
  197. }
  198. }
  199. }// void FaceDetection::DrawResult(IplImage* img)
  200. void FaceDetection::ResetImage()
  201. {
  202. delete m_pFaceList;
  203. m_pFaceList = new List();
  204. }//FaceDetection::ResetImage
  205. void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
  206. {
  207. assert(m_mstgRects != NULL);
  208. assert(m_seqRects != NULL);
  209. CvContourRect cr;
  210. for (CvSeq* external = seq; external; external = external->h_next)
  211. {
  212. cr.r = cvContourBoundingRect(external, 1 );
  213. cr.pCenter.x = cr.r.x + cr.r.width / 2;
  214. cr.pCenter.y = cr.r.y + cr.r.height / 2;
  215. cr.iNumber = iLayer;
  216. cr.iType = 6;
  217. cr.iFlags = 0;
  218. cr.seqContour = external;
  219. cr.iContourLength = external->total;
  220. cr.iColor = color;
  221. cvSeqPush(m_seqRects, &cr);
  222. for (CvSeq* internal = external->v_next; internal; internal = internal->h_next)
  223. {
  224. cr.r = cvContourBoundingRect(internal, 0);
  225. cr.pCenter.x = cr.r.x + cr.r.width / 2;
  226. cr.pCenter.y = cr.r.y + cr.r.height / 2;
  227. cr.iNumber = iLayer;
  228. cr.iType = 12;
  229. cr.iFlags = 0;
  230. cr.seqContour = internal;
  231. cr.iContourLength = internal->total;
  232. cr.iColor = color;
  233. cvSeqPush(m_seqRects, &cr);
  234. }
  235. }
  236. }// void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
  237. int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* /*userdata*/)
  238. {
  239. return (((CvContourRect*)el1)->pCenter.y - ((CvContourRect*)el2)->pCenter.y);
  240. }// int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata)
  241. void FaceDetection::FindFace(IplImage *img)
  242. {
  243. // find all contours
  244. FindContours(img);
  245. //
  246. ResetImage();
  247. if (m_bBoosting)
  248. PostBoostingFindCandidats(img);
  249. else
  250. FindCandidats();
  251. }// void FaceDetection::FindFace(IplImage *img)
  252. void FaceDetection::FindCandidats()
  253. {
  254. bool bFound1 = false;
  255. MouthFaceTemplate * lpFaceTemplate1;
  256. RFace * lpFace1;
  257. bool bInvalidRect1 = false;
  258. CvRect * lpRect1 = NULL;
  259. for (int i = 0; i < m_seqRects->total; i++)
  260. {
  261. CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
  262. CvRect rect = pRect->r;
  263. if (rect.width >= 2*rect.height)
  264. {
  265. lpFaceTemplate1 = new MouthFaceTemplate(3,rect,3*(double)rect.width/(double)4,
  266. 3*(double)rect.width/(double)4,
  267. (double)rect.width/(double)2,
  268. (double)rect.width/(double)2);
  269. lpFace1 = new RFace(lpFaceTemplate1);
  270. for (int j = 0; j < m_seqRects->total; j++)
  271. {
  272. CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, j);
  273. if ( !bInvalidRect1 )
  274. {
  275. lpRect1 = NULL;
  276. lpRect1 = new CvRect();
  277. *lpRect1 = pRect->r;
  278. }else
  279. {
  280. delete lpRect1;
  281. lpRect1 = new CvRect();
  282. *lpRect1 = pRect->r;
  283. }
  284. if ( lpFace1->isFeature(lpRect1) )
  285. {
  286. bFound1 = true;
  287. bInvalidRect1 = false;
  288. }else
  289. bInvalidRect1 = true;
  290. }
  291. if (bFound1)
  292. {
  293. m_pFaceList->AddElem(lpFace1);
  294. bFound1 = false;
  295. lpFace1 = NULL;
  296. }else
  297. {
  298. delete lpFace1;
  299. lpFace1 = NULL;
  300. }
  301. delete lpFaceTemplate1;
  302. }
  303. }
  304. }
  305. void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
  306. {
  307. BoostingFaceTemplate * lpFaceTemplate1;
  308. RFace * lpFace1;
  309. bool bInvalidRect1 = false;
  310. CvRect * lpRect1 = NULL;
  311. if ( ( !FaceImage->roi ) )
  312. lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(0,0,FaceImage->width,FaceImage->height));
  313. else
  314. lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(FaceImage->roi->xOffset,FaceImage->roi->yOffset,
  315. FaceImage->roi->width,FaceImage->roi->height));
  316. lpFace1 = new RFace(lpFaceTemplate1);
  317. for (int i = 0; i < m_seqRects->total; i++)
  318. {
  319. CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
  320. if ( !bInvalidRect1 )
  321. {
  322. lpRect1 = NULL;
  323. lpRect1 = new CvRect();
  324. *lpRect1 = pRect->r;
  325. }else
  326. {
  327. delete lpRect1;
  328. lpRect1 = new CvRect();
  329. *lpRect1 = pRect->r;
  330. }
  331. if ( lpFace1->isFeature(lpRect1) )
  332. {
  333. //bFound1 = true;
  334. bInvalidRect1 = false;
  335. }else
  336. bInvalidRect1 = true;
  337. }
  338. m_pFaceList->AddElem(lpFace1);
  339. delete lpFaceTemplate1;
  340. }//void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
  341. /////////////////////////
  342. //class Face
  343. //////
  344. //List Class
  345. /////
  346. ListElem::ListElem()
  347. {
  348. m_pNext = this;
  349. m_pPrev = this;
  350. m_pFace = NULL;
  351. }///ListElem::ListElem()
  352. ListElem::ListElem(Face * pFace,ListElem * pHead)
  353. {
  354. m_pNext = pHead;
  355. m_pPrev = pHead->m_pPrev;
  356. pHead->m_pPrev->m_pNext = this;
  357. pHead->m_pPrev = this;
  358. m_pFace = pFace;
  359. }//ListElem::ListElem(Face * pFace)
  360. ListElem::~ListElem()
  361. {
  362. delete m_pFace;
  363. m_pNext->m_pPrev = m_pPrev;
  364. m_pPrev->m_pNext = m_pNext;
  365. }//ListElem::~ListElem()
  366. List::List()
  367. {
  368. m_pHead = new ListElem();
  369. m_FacesCount = 0;
  370. m_pCurElem = m_pHead;
  371. }//List::List()
  372. List::~List()
  373. {
  374. void * tmp;
  375. while((tmp = m_pHead->m_pNext->m_pFace) != 0)
  376. delete m_pHead->m_pNext;
  377. delete m_pHead;
  378. }//List::~List()
  379. int List::AddElem(Face * pFace)
  380. {
  381. new ListElem(pFace,m_pHead);
  382. return m_FacesCount++;
  383. }//List::AddElem(Face * pFace)
  384. Face * List::GetData()
  385. {
  386. m_pCurElem = m_pCurElem->m_pNext;
  387. return m_pCurElem->m_pFace;
  388. }//Face * List::GetData()