FaceDetectDoc.cpp
上传用户:sdsuchuang
上传日期:2013-01-12
资源大小:2228k
文件大小:15k
源码类别:

图形图像处理

开发平台:

Visual C++

  1. // FaceDetectDoc.cpp : implementation of the CFaceDetectDoc class
  2. //
  3. #include "stdafx.h"
  4. #include "FaceDetect.h"
  5. #include "DIB.h"
  6. #include "FaceDetectDoc.h"
  7. #include "FaceDetectView.h"
  8. #include "LikelyHood.h"
  9. #include "math.h"
  10. #define WIDTHBYTES(bits)  ((bits+31)/32*4)
  11. //#include "ReplaceDoc.h"
  12. #ifdef _DEBUG
  13. #define new DEBUG_NEW
  14. #undef THIS_FILE
  15. static char THIS_FILE[] = __FILE__;
  16. #endif
  17. extern HANDLE hDIB;
  18. extern HANDLE hDIB1;
  19. extern HANDLE hDIBTemp;
  20. extern HANDLE hDIBTemp1;
  21. extern class DIB gDib;
  22. extern int gheight;
  23. extern int gwidth;
  24. extern WORD gwBytesPerLine;
  25. #define IDC_BMPSHOW                     1000
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CFaceDetectDoc
  28. IMPLEMENT_DYNCREATE(CFaceDetectDoc, CDocument)
  29. BEGIN_MESSAGE_MAP(CFaceDetectDoc, CDocument)
  30. //{{AFX_MSG_MAP(CFaceDetectDoc)
  31. ON_COMMAND(ID_READY_GetFaceOutLline, OnREADYGetFaceOutLline)
  32. //}}AFX_MSG_MAP
  33. END_MESSAGE_MAP()
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CFaceDetectDoc construction/destruction
  36. CFaceDetectDoc::CFaceDetectDoc()
  37. {
  38. // TODO: add one-time construction code here
  39.  m_bFaceOK = false;
  40. }
  41. CFaceDetectDoc::~CFaceDetectDoc()
  42. {
  43. }
  44. BOOL CFaceDetectDoc::OnNewDocument()
  45. {
  46. if (!CDocument::OnNewDocument())
  47. return FALSE;
  48. // TODO: add reinitialization code here
  49. // (SDI documents will reuse this document)
  50. return TRUE;
  51. }
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CFaceDetectDoc serialization
  54. void CFaceDetectDoc::Serialize(CArchive& ar)
  55. {
  56. if (ar.IsStoring())
  57. {
  58. // TODO: add storing code here
  59. }
  60. else
  61. {
  62. // TODO: add loading code here
  63. }
  64. }
  65. /////////////////////////////////////////////////////////////////////////////
  66. // CFaceDetectDoc diagnostics
  67. #ifdef _DEBUG
  68. void CFaceDetectDoc::AssertValid() const
  69. {
  70. CDocument::AssertValid();
  71. }
  72. void CFaceDetectDoc::Dump(CDumpContext& dc) const
  73. {
  74. CDocument::Dump(dc);
  75. }
  76. #endif //_DEBUG
  77. /////////////////////////////////////////////////////////////////////////////
  78. // CFaceDetectDoc commands
  79. BOOL CFaceDetectDoc::OnOpenDocument(LPCTSTR lpszPathName) 
  80. {
  81. if (!CDocument::OnOpenDocument(lpszPathName))
  82. return FALSE;
  83. if(hDIB)
  84. GlobalFree(hDIB);
  85.    path=lpszPathName;
  86. hDIB = gDib.LoadDIB(lpszPathName);
  87. ASSERT(hDIB != NULL);
  88. hDIBTemp = gDib.CopyHandle(hDIB);
  89. LPBITMAPINFOHEADER lpbi;
  90. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  91. gheight = lpbi->biHeight;
  92. gwidth = lpbi->biWidth;
  93.     m_nWndWidth = gwidth;
  94. m_nWndHeight=gheight ;
  95. gwBytesPerLine = gDib.BytePerLine(hDIB);
  96. GlobalUnlock(hDIB);
  97. return TRUE;
  98. }
  99. BOOL CFaceDetectDoc::OnOpenDocument1(LPCTSTR lpszPathName) 
  100. {
  101. if (!CDocument::OnOpenDocument(lpszPathName))
  102. return FALSE;
  103. if(hDIB1)
  104. GlobalFree(hDIB1);
  105.    path=lpszPathName;
  106. hDIB1 = gDib.LoadDIB(lpszPathName);
  107. ASSERT(hDIB1 != NULL);
  108. hDIBTemp1 = gDib.CopyHandle(hDIB1);
  109. LPBITMAPINFOHEADER lpbi;
  110. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB1);
  111. gheight = lpbi->biHeight;
  112. gwidth = lpbi->biWidth;
  113.     m_nWndWidth = gwidth;
  114. m_nWndHeight=gheight ;
  115. gwBytesPerLine = gDib.BytePerLine(hDIB1);
  116. GlobalUnlock(hDIB);
  117. return TRUE;
  118. }
  119. ///////////////////////获取图片数据//////////////////
  120. void CFaceDetectDoc::OnREADYGetFaceOutLline() 
  121. {
  122. // BYTE *colorTable;
  123. if(!hDIB)
  124. {
  125. ::AfxMessageBox("请确认是否有图片?");return ;
  126. }
  127. READYGetFaceOutLline1() ;
  128. }
  129. void CFaceDetectDoc::READYGetFaceOutLline1() 
  130. {
  131. DIB *m_pMainDib=new DIB();
  132.    //BYTE *m_pDib=m_pMainDib->GetBits();
  133. // colorTable = (BYTE *)m_pDib;
  134.    //////////////////////////////////////////////////////
  135.     HDIB hNewDIB = NULL;
  136. LPBITMAPINFOHEADER lpSrc,lpDest;
  137. LPBYTE lpS,lpD;
  138. DWORD dwBytesPerLine;
  139. DWORD dwImgSize;
  140. // WORD wBytesPerLine;
  141. unsigned i ,j,height,width;
  142. if(!hDIB)
  143. return ;
  144. lpSrc = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  145. dwBytesPerLine = WIDTHBYTES(24*(lpSrc->biWidth));
  146. dwImgSize = lpSrc->biHeight * dwBytesPerLine;
  147. //申请新的内存,大小等于原来图象的大小
  148. hNewDIB = GlobalAlloc(GHND,sizeof(BITMAPINFOHEADER)+dwImgSize);
  149. lpDest = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
  150. //保存图片的长宽、颜色深度等信息
  151.     memcpy((void*)lpDest,(void*)lpSrc,sizeof(BITMAPINFOHEADER));
  152. DWORD dwSBytesPerLine;
  153. dwSBytesPerLine = (24*(lpSrc->biWidth)+31)/32*4;
  154. height = lpDest->biHeight;
  155. width = lpDest->biWidth;
  156. lpS = (LPBYTE)lpSrc;
  157. // wBytesPerLine = this->BytePerLine(hDIB);//
  158. lpD = (LPBYTE)lpDest;
  159. lpS = lpS + sizeof(BITMAPINFOHEADER);
  160. lpD = lpD + sizeof(BITMAPINFOHEADER);
  161.    ////////////////////////////////////////////////////
  162.   
  163. int byteBitCount  = m_pMainDib->GetBiBitCount()/8;
  164. m_tOriPixelArray  = new RGBQUAD*[height];
  165. m_tResPixelArray  = new RGBQUAD*[height];
  166. for(i=0; i<height; i++)
  167. {
  168. m_tOriPixelArray[i] = new RGBQUAD[width];
  169. m_tResPixelArray[i] = new RGBQUAD[width];
  170. }
  171.     LPBYTE lpData;
  172. long lOffset;
  173. lpData = gDib.FindDIBBits(hDIB);
  174.     WORD gwBytesPerLine = gDib.BytePerLine(hDIB);
  175. for(i=0; i<height; i++)
  176. {
  177. for(j=0; j<width; j++)
  178. {  
  179. lOffset = gDib.PixelOffset(i, j, gwBytesPerLine);
  180.             m_tOriPixelArray[i][j].rgbBlue =*(lpData + lOffset++);
  181.     m_tOriPixelArray[i][j].rgbGreen=*(lpData + lOffset++);
  182. m_tOriPixelArray[i][j].rgbRed  =*(lpData + lOffset++);
  183. m_tOriPixelArray[i][j].rgbReserved = 0;
  184. m_tResPixelArray[i][j]=m_tOriPixelArray[i][j];
  185. }
  186. }
  187. m_nWndWidth=width;
  188.     m_nWndHeight=height;
  189.   method1 =new CLikelyHood(m_tOriPixelArray,m_nWndWidth,m_nWndHeight);
  190.   
  191.   Likehood(m_nWndWidth,m_nWndHeight) ;
  192.   OnBtnBinary();
  193.   
  194.   HistogramV();
  195.   OnBtnHistogramH();
  196.   
  197.   OnBtnMarkFace();
  198.   ///////////////////////////////////////////////
  199.   /*
  200.   for(int k1=top;k1<bottom; k1++)
  201. for(int k=left;k<right; k++)
  202.             if(method1->m_pBinaryArray[k1][k]==1)
  203. {
  204.   lOffset = gDib.PixelOffset(k1, k, gwBytesPerLine);
  205.                *(lpData+lOffset)=255;
  206.                *(lpData+lOffset+1)=255;
  207.    *(lpData+lOffset+2)=255;
  208.    }
  209.  */
  210. ////////////////////////////////////////////////////
  211.   
  212. }
  213. ////////////////////////////////////////////////////////////////////////////////
  214. // 计算相似度
  215. ////////////////////////////////////////////////////////////////////////////////
  216. void CFaceDetectDoc::Likehood(int m_WndWidth,int m_WndHeight) 
  217. {
  218. int i,j;
  219. SetCursor(LoadCursor(NULL,IDC_WAIT));
  220.     
  221. method1->CalLikeHood();
  222. for( i=0; i<m_WndHeight; i++)
  223. for( j=0; j<m_WndWidth;  j++)
  224. {
  225. m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =m_tResPixelArray[i][j].rgbRed=(int)(method1->m_pLikeliHoodArray[i][j]*255);
  226.     
  227. }
  228. //MakeBitMap();
  229.   
  230. SetCursor(LoadCursor(NULL,IDC_ARROW));
  231. }
  232. ////////////////////////////////////////////////////////////////////////////////
  233. // 二值化
  234. ////////////////////////////////////////////////////////////////////////////////
  235. void CFaceDetectDoc::OnBtnBinary() 
  236. {
  237. SetCursor(LoadCursor(NULL,IDC_WAIT));
  238. int i,j;
  239. //  long lOffset;
  240.  LPBYTE lpData = gDib.FindDIBBits(hDIB);
  241.     WORD gwBytesPerLine = gDib.BytePerLine(hDIB);
  242. if(!method1->CalBinary())
  243. {
  244. AfxMessageBox("请先计算相似度!");
  245. SetCursor(LoadCursor(NULL,IDC_ARROW));
  246. return;
  247. }
  248.     
  249. for(i=0; i<m_nWndHeight; i++)
  250. for( j=0; j<m_nWndWidth;  j++)
  251. {
  252. m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
  253. m_tResPixelArray[i][j].rgbRed  = (int)(method1->m_pBinaryArray[i][j]*255);
  254. }
  255. // MakeBitMap();
  256. SetCursor(LoadCursor(NULL,IDC_ARROW));
  257. //MyDraw();
  258. }
  259. ////////////////////////////////////////////////////////////////////////////////
  260. // 画图
  261. ////////////////////////////////////////////////////////////////////////////////
  262. /*
  263. void CFaceDetectDoc::MyDraw()
  264. {
  265. CRect rc;
  266. m_pResMap=new CBitmap();
  267. pDCShow->GetWindow()->GetClientRect(&rc);
  268. pDCShow->Rectangle(&rc);
  269. CDC dc;
  270. CBitmap *pOldBitmap;
  271. dc.CreateCompatibleDC(pDCShow);
  272. pOldBitmap=dc.SelectObject(m_pResMap);
  273. pDCShow->StretchBlt(0,0,m_nWndWidth,m_nWndHeight,&dc,0,0,m_nWndWidth,m_nWndHeight,SRCCOPY);
  274. dc.SelectObject(pOldBitmap);
  275. dc.DeleteDC();
  276. }
  277. */
  278. ////////////////////////////////////////////////////////////////////////////////
  279. // 垂直方向的直方图
  280. ////////////////////////////////////////////////////////////////////////////////
  281. void CFaceDetectDoc::HistogramV() 
  282. {
  283. SetCursor(LoadCursor(NULL,IDC_WAIT));
  284. for(int i=0; i<m_nWndHeight; i++)
  285. {
  286. int count = 0;
  287. for(int j=0; j<m_nWndWidth;  j++)
  288. {
  289. if(method1->m_pBinaryArray[i][j] == 1) count++;
  290. m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
  291. m_tResPixelArray[i][j].rgbRed  = 255;
  292. }
  293. for(j=0; j<count;  j++)
  294. {
  295. m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
  296. m_tResPixelArray[i][j].rgbRed  = 0;
  297. }
  298. }
  299. // MakeBitMap();
  300. SetCursor(LoadCursor(NULL,IDC_ARROW));
  301. }
  302. ////////////////////////////////////////////////////////////////////////////////
  303. // 水平方向直方图
  304. ////////////////////////////////////////////////////////////////////////////////
  305. void CFaceDetectDoc::OnBtnHistogramH() 
  306. {
  307. SetCursor(LoadCursor(NULL,IDC_WAIT));
  308. for(int j=0; j<m_nWndWidth;  j++)
  309. {
  310. int count = 0;
  311. for(int i=0; i<m_nWndHeight; i++)
  312. {
  313. if(method1->m_pBinaryArray[i][j] == 1) count++;
  314. m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
  315. m_tResPixelArray[i][j].rgbRed  = 255;
  316. }
  317. for(i=m_nWndHeight-1; i>=m_nWndHeight-count;i--)
  318. {
  319. m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
  320. m_tResPixelArray[i][j].rgbRed  = 0;
  321. }
  322. }
  323. // MakeBitMap();
  324. SetCursor(LoadCursor(NULL,IDC_ARROW));
  325. }
  326. ////////////////////////////////////////////////////////////////////////////////
  327. //标记脸部区域
  328. ////////////////////////////////////////////////////////////////////////////////
  329. void CFaceDetectDoc::OnBtnMarkFace() 
  330. {
  331. SetCursor(LoadCursor(NULL,IDC_WAIT));
  332. int *temp = new int[m_nWndWidth];
  333. int max = 0;
  334. int pos = -1;
  335. for(int j=0; j<m_nWndWidth;  j++)////////////////计算出每行占有的脸部像素点数
  336. {
  337. int count = 0;
  338. for(int i=0; i<m_nWndHeight; i++)
  339. {
  340. if(method1->m_pBinaryArray[i][j]== 1) count++;
  341. }
  342. temp[j] = count;
  343. if(count > max)////////////////////////获取哪一行具有的脸部像素点数最多,记下数目和第几行
  344. {
  345. max = count;
  346. pos = j;
  347. }
  348. }
  349. for(l=pos; l>=0; l--)////////////////////////向上获取具有的脸部像素点数最多的一半的行
  350. {
  351. if(temp[l]<max*0.2||l==0)
  352. {
  353. left = l;
  354. break;
  355. }
  356. }
  357. for(l=pos; l<m_nWndWidth; l++)////////////////////////向下获取具有的脸部像素点数最多的1/3的行
  358. {
  359. if(temp[l]<max*0.3||l==m_nWndWidth-1)
  360. {
  361. right = l;
  362. break;
  363. }
  364. }
  365. for(int i=0; i<m_nWndHeight; i++)
  366. {
  367. int count = 0;
  368. for(l = left;l<=right;l++)
  369. {
  370. if(method1->m_pBinaryArray[i][l] == 1) count++;
  371. }
  372. if(count>=(right-left)*0.5)
  373. {
  374. top = i;
  375. break;
  376. }
  377. }
  378. bottom = (int)(top+(right-left)*1.5)>=m_nWndHeight? m_nWndHeight-1:(int)(top+(right-left)*1.5);
  379. CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
  380.  
  381. for(i=top;i<=bottom;i++)
  382. {
  383. m_tResPixelArray[i][left].rgbBlue=255;
  384. m_tResPixelArray[i][left].rgbGreen = m_tResPixelArray[i][left].rgbRed = 0;
  385. m_tResPixelArray[i][right].rgbBlue=255;
  386. m_tResPixelArray[i][right].rgbGreen = m_tResPixelArray[i][right].rgbRed = 0;
  387. }
  388. for(j=left;j<=right;j++)
  389. {
  390. m_tResPixelArray[top][j].rgbBlue=255;
  391. m_tResPixelArray[top][j].rgbGreen = m_tResPixelArray[top][j].rgbRed = 0;
  392. m_tResPixelArray[bottom][j].rgbBlue=255;
  393. m_tResPixelArray[bottom][j].rgbGreen = m_tResPixelArray[bottom][j].rgbRed = 0;
  394. }
  395. // MakeBitMap();
  396. SetCursor(LoadCursor(NULL,IDC_ARROW));
  397.    //////////////////////////////////////////////////////////////////////////////////////
  398.   
  399. for(int h=bottom;h<m_nWndHeight;h++)
  400.    {    int count=0;
  401.    for(int w=left;w<right;w++)
  402.    {
  403.    if(method1->m_pBinaryArray[h][w] == 1)
  404.    count++;
  405.    }
  406.               if(count>=(right-left)*0.5)
  407.   bottom++;
  408.    
  409.    
  410.    }
  411.    
  412. CFaceDetectView *Gd=new CFaceDetectView();
  413. Gd->DrawLine(left,top,bottom,right);
  414.   //////////////////////////////////////////////////////////////////////////////////////
  415.        
  416. if(m_bFaceOK)
  417. {
  418. //ReplaceDoc dlg;
  419. // if(dlg.DoModal()==IDOK)
  420. // {
  421. CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
  422. CRect rect(left,top,right,bottom);
  423. m_rFaceRegion = rect;
  424. // MakeBitMap();
  425. //}
  426. }
  427. else
  428. {
  429. m_bFaceOK = true;
  430. CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
  431. CRect rect(left,top,right,bottom);
  432. m_rFaceRegion = rect;
  433. // MakeBitMap();
  434. }
  435. }
  436. ////////////////////////////////////////////////////////////////////////////////
  437. // 拷贝位图
  438. // 参数:  dest-目标位图指针
  439. //         source-源位图指针
  440. ////////////////////////////////////////////////////////////////////////////////
  441. bool CFaceDetectDoc::CopyBitMap(RGBQUAD **dest, RGBQUAD **source)
  442. {
  443. if(source==NULL || dest==NULL) 
  444. return false;
  445. for(int i=0; i<m_nWndHeight; i++)
  446. for(int j=0; j<m_nWndWidth; j++)
  447. dest[i][j]=source[i][j];
  448. return true;
  449. }
  450. ////////////////////////////////////////////////////////////////////////////////
  451. // 生成新的位图
  452. ////////////////////////////////////////////////////////////////////////////////
  453. void CFaceDetectDoc::MakeBitMap()
  454. {
  455. CClientDC ClientDC(pDCShow->GetWindow());
  456. if(m_pResMap!=NULL) delete m_pResMap;
  457. m_pResMap=new CBitmap();
  458. m_pResMap->CreateCompatibleBitmap(&ClientDC,m_nWndWidth,m_nWndHeight);
  459. CDC  dc;
  460. dc.CreateCompatibleDC(&ClientDC);
  461. dc.SelectObject(m_pResMap);
  462. for(int i=0; i<m_nWndHeight; i++)
  463. for(int j=0; j<m_nWndWidth; j++)
  464. dc.SetPixelV(j,i,RGB(m_tResPixelArray[i][j].rgbRed,m_tResPixelArray[i][j].rgbGreen,m_tResPixelArray[i][j].rgbBlue));
  465.     
  466. if(m_bFaceOK )
  467. {
  468. CBrush Pen;
  469. Pen.CreateSolidBrush(RGB(255,0,0));
  470. dc.FrameRect(m_rFaceRegion,&Pen);
  471.   Pen.DeleteObject();
  472. }
  473. if(m_bLeftEyeOK) DrawCross(&dc,m_LeftEye,RGB(255,0,0));
  474. if(m_bRightEyeOK) DrawCross(&dc,m_RightEye,RGB(255,0,0));
  475. if(m_bLeftEyeLeftCornerOK) DrawCross(&dc,m_LeftEyeLeftCorner,RGB(255,0,255));
  476. if(m_bLeftEyeRightCornerOK) DrawCross(&dc,m_LeftEyeRightCorner,RGB(255,255,0));
  477. if(m_bRightEyeLeftCornerOK) DrawCross(&dc,m_RightEyeLeftCorner,RGB(255,0,255));
  478. if(m_bRightEyeRightCornerOK) DrawCross(&dc,m_RightEyeRightCorner,RGB(255,255,0));
  479. if(m_bLeftNostrilOK) DrawCross(&dc,m_LeftNostril,RGB(0,255,0));
  480. if(m_bRightNostrilOK) DrawCross(&dc,m_RightNostril,RGB(0,255,0));
  481. if(m_bMidNoseOK) DrawCross(&dc,m_MidNose,RGB(0,255,0));
  482. if(m_bLeftMouthCornerOK) DrawCross(&dc,m_LeftMouthCorner,RGB(0,0,255));
  483. if(m_bRightMouthCornerOK) DrawCross(&dc,m_RightMouthCorner,RGB(0,0,255));
  484. if(m_bMidMouthOK) DrawCross(&dc,m_MidMouth,RGB(0,0,255));
  485. dc.DeleteDC();
  486. // MyDraw();
  487. }
  488. ////////////////////////////////////////////////////////////////////////////////
  489. // 画十字形标记
  490. // 参数:  pDC-CDC指针
  491. //         point-要画的点的坐标
  492. //         crColor-标记得颜色
  493. ////////////////////////////////////////////////////////////////////////////////
  494. void CFaceDetectDoc::DrawCross(CDC *pDC, CPoint point, COLORREF crColor)
  495. {
  496. CPen pen,*oldPen;
  497. pen.CreatePen(PS_SOLID,1,crColor);
  498. oldPen = (CPen*)pDC->SelectObject(&pen);
  499. pDC->MoveTo(point.x-7,point.y);
  500. pDC->LineTo(point.x+7,point.y);
  501. pDC->MoveTo(point.x,point.y-7);
  502. pDC->LineTo(point.x,point.y+7);
  503. pDC->SelectObject(oldPen);
  504. pen.DeleteObject();
  505. }