📄 facedetectdlg.cpp
字号:
}
}
for(int i=0; i<m_nWndHeight; i++)
{
int count = 0;
for(l = left;l<=right;l++)
{
if(method1->m_pBinaryArray[i][l] == 1) count++;
}
if(count>=(right-left)*0.5)
{
top = i;
break;
}
}
bottom = (int)(top+(right-left)*1.5)>=m_nWndHeight? m_nWndHeight-1:(int)(top+(right-left)*1.5);
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
for(i=top;i<=bottom;i++)
{
m_tResPixelArray[i][left].rgbBlue=255;
m_tResPixelArray[i][left].rgbGreen = m_tResPixelArray[i][left].rgbRed = 0;
m_tResPixelArray[i][right].rgbBlue=255;
m_tResPixelArray[i][right].rgbGreen = m_tResPixelArray[i][right].rgbRed = 0;
}
for(j=left;j<=right;j++)
{
m_tResPixelArray[top][j].rgbBlue=255;
m_tResPixelArray[top][j].rgbGreen = m_tResPixelArray[top][j].rgbRed = 0;
m_tResPixelArray[bottom][j].rgbBlue=255;
m_tResPixelArray[bottom][j].rgbGreen = m_tResPixelArray[bottom][j].rgbRed = 0;
}
MakeBitMap();
SetCursor(LoadCursor(NULL,IDC_ARROW));
if(m_bFaceOK)
{
ReplaceDlg dlg;
if(dlg.DoModal()==IDOK)
{
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
CRect rect(left,top,right,bottom);
m_rFaceRegion = rect;
MakeBitMap();
}
}
else
{
m_bFaceOK = true;
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
CRect rect(left,top,right,bottom);
m_rFaceRegion = rect;
MakeBitMap();
}
}
////////////////////////////////////////////////////////////////////////////////
// 第二种方法标记脸部区域
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnMarkFace2()
{
if(!method2->m_bBinaryOK)
{
AfxMessageBox("请先计算二值化图");
return;
}
m_bShowFace = true;
SetCursor(LoadCursor(NULL,IDC_WAIT));
int *numR,*numB, i, j, left,right,top,bottom;
int maxnumR = 0, maxnumB = 0;
numR = new int[m_nWndWidth];
numB = new int[m_nWndWidth];
for(j=0;j<m_nWndWidth ;j++)
{
int countR = 0, countB = 0;
for(i=0;i<m_nWndHeight;i++)
{
if(method2->m_pBinaryArray[i][j] == 0)
countR++;
if(method2->m_pBinaryArray[i][j] == 1)
countB++;
}
if(countR > maxnumR) maxnumR = countR;
numR[j] = countR;
if(countB > maxnumB) maxnumB = countB;
numB[j] = countB;
}
CList<CPoint,CPoint> myListR(sizeof(CPoint));
CList<CPoint,CPoint> myListB(sizeof(CPoint));
CPoint tempR,tempB;
int flagR = 0,flagB = 0;
for(j=0;j<m_nWndWidth ;j++)
{
if(flagR == 0)
{
if(numR[j]>maxnumR/2)
{
flagR = 1;
tempR.x = j;
}
}
else
{
if(numR[j]<=maxnumR/2 || j==m_nWndWidth-1)
{
flagR = 0;
tempR.y = j;
myListR.AddTail(tempR);
}
}
if(flagB == 0)
{
if(numB[j]>maxnumB/5)
{
flagB = 1;
tempB.x = j;
}
}
else
{
if(numB[j]<=maxnumB/5 || j==m_nWndWidth-1)
{
flagB = 0;
tempB.y = j;
if(myListB.GetCount() > 1 && (tempB.x-myListB.GetTail().y)<20)
myListB.SetAt(myListB.GetTailPosition(),CPoint(myListB.GetTail().x,j));
else
myListB.AddTail(tempB);
}
}
}
if(numR!=NULL)delete numR;
if(numB!=NULL)delete numB;
int *hairmark, k;
hairmark = new int[m_nWndWidth];
for(j=0;j<m_nWndWidth ;j++) hairmark[j]=0;
for(k=0;k<myListB.GetCount();k++)
{
CPoint temp = myListB.GetAt(myListB.FindIndex(k));
if((temp.y-temp.x)>m_nWndWidth/10)
{
for(int t = temp.x;t<=temp.y;t++)
hairmark[t] = 1;
}
}
for(k=0;k<myListR.GetCount();k++)
{
CPoint temp = myListR.GetAt(myListR.FindIndex(k));
int templeft=-1;
int tempright=-1;
if((temp.y-temp.x)>m_nWndWidth/10)
{
for(int t=temp.x;t<=temp.y;t++)
{
if(hairmark[t]==1)
{
int endpos=t+(temp.y-temp.x)/5;
if(endpos > temp.y)endpos = temp.y;
int yes = 1;
for(int q=t;q<=endpos;q++)
if(hairmark[q]==0) yes = 0;
if(yes == 1)
{
templeft = t;
break;
}
}
}
for(int p=temp.y;p>=temp.x;p--)
{
if(hairmark[p]==1)
{
int beginpos=p-(temp.y-temp.x)/5;
if(beginpos < temp.x)beginpos = temp.x;
int yes = 1;
for(int q=p;q>=beginpos;q--)
if(hairmark[q]==0) yes = 0;
if(yes == 1)
{
tempright = p;
break;
}
}
}
}
if(templeft!=-1 && tempright!=-1)
{
left = templeft;
right = tempright;
break;
}
}
if(hairmark !=NULL) delete hairmark;
myListR.RemoveAll();
myListB.RemoveAll();
if(left-m_nWndWidth/50>0) left-=(int)m_nWndWidth/50;
else left = 0;
if(right+m_nWndWidth/40>m_nWndWidth) right=m_nWndWidth-1;
else right += m_nWndWidth/40;
for(i=0; i<m_nWndHeight; i++)
{
int count = 0;
for(int l = left;l<=right;l++)
{
if(method2->m_pBinaryArray[i][l] == 0) count++;
}
if(count>=(right-left)*0.5)
{
top = i;
break;
}
}
bottom = (int)(top+(right-left)*1.5)>=m_nWndHeight? m_nWndHeight-1:(int)(top+(right-left)*1.5);
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
for(i=top;i<=bottom;i++)
{
m_tResPixelArray[i][left].rgbBlue=255;
m_tResPixelArray[i][left].rgbGreen = m_tResPixelArray[i][left].rgbRed = 0;
m_tResPixelArray[i][right].rgbBlue=255;
m_tResPixelArray[i][right].rgbGreen = m_tResPixelArray[i][right].rgbRed = 0;
}
for(j=left;j<=right;j++)
{
m_tResPixelArray[top][j].rgbBlue=255;
m_tResPixelArray[top][j].rgbGreen = m_tResPixelArray[top][j].rgbRed = 0;
m_tResPixelArray[bottom][j].rgbBlue=255;
m_tResPixelArray[bottom][j].rgbGreen = m_tResPixelArray[bottom][j].rgbRed = 0;
}
MakeBitMap();
SetCursor(LoadCursor(NULL,IDC_ARROW));
if(m_bFaceOK)
{
ReplaceDlg dlg;
if(dlg.DoModal()==IDOK)
{
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
CRect rect(left,top,right,bottom);
m_rFaceRegion = rect;
MakeBitMap();
}
}
else
{
m_bFaceOK = true;
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
CRect rect(left,top,right,bottom);
m_rFaceRegion = rect;
MakeBitMap();
}
}
////////////////////////////////////////////////////////////////////////////////
// 标记嘴巴
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnMarkMouse()
{
int i,j;
if(!(m_bLeftEyeOK&&m_bRightEyeOK))
{
AfxMessageBox("请先确定眼睛");
return;
}
//左右眼的水平区域
int nLeft,nRight,nTop,nBottom;
nLeft = m_rFaceRegion.left-5 > 0 ? m_rFaceRegion.left-5:0;
nRight = m_rFaceRegion.right+5 < m_nWndWidth? m_rFaceRegion.right+5:m_nWndWidth-1;
nTop = m_rFaceRegion.top-5 > 0 ? m_rFaceRegion.top-5:0;
nBottom = m_rFaceRegion.bottom+5< m_nWndHeight?m_rFaceRegion.bottom+5:m_nWndHeight-1;
SetPixelArray(m_tResPixelArray,0);
for(i=nTop; i<=nBottom; i++)
for(j=nLeft; j<=nRight; j++)
{
BYTE R,G,B;
double temp,dlta;
R = m_tOriPixelArray[i][j].rgbRed;
G = m_tOriPixelArray[i][j].rgbGreen;
B = m_tOriPixelArray[i][j].rgbBlue;
if((R==G) && (G==B)) temp = 0;
else temp = 0.5*(2*R-G-B)/sqrt((R-G)*(R-G)+(R-B)*(G-B));
dlta = acos(temp);
if(dlta < 0.2)
{
m_tResPixelArray[i][j].rgbRed = 255;
}
else m_tResPixelArray[i][j].rgbRed = 0;
}
MakeBitMap();
AfxMessageBox("嘴的肤色鉴定");
//双目斜角
double tanThta;
if(m_RightEye.y == m_LeftEye.y) tanThta = 0;
else tanThta = (m_RightEye.y - m_LeftEye.y)/(m_RightEye.x - m_LeftEye.x);
//双目距离
int EyesDis = (m_RightEye.x-m_LeftEye.x)*(m_RightEye.x-m_LeftEye.x);
EyesDis += (m_RightEye.y-m_LeftEye.y)*(m_RightEye.y-m_LeftEye.y);
EyesDis = (int)sqrt(EyesDis);
//双目平均高度
int EyeV = (m_RightEye.y + m_LeftEye.y)/2;
//可能的嘴的区域
int MouthUp = (EyeV+1.0*EyesDis) > nBottom ? nBottom:(int)(EyeV+1.0*EyesDis);
int MouthDown = (EyeV+1.5*EyesDis) > nBottom ? nBottom:(int)(EyeV+1.5*EyesDis);
int* Y_Arry = new int[MouthDown-MouthUp];
for(i =0 ;i < MouthDown-MouthUp ;i++) Y_Arry[i] = 0;
int* X_Arry = new int[EyesDis];
for(i =0 ;i < EyesDis ;i++) X_Arry[i] = 0;
for(i = MouthUp ; i < MouthDown; i++)
for(j = m_LeftEye.x; j< m_RightEye.x; j++)
{
if(m_tResPixelArray[i][j].rgbRed == 255)
{
Y_Arry[i-MouthUp] ++;
X_Arry[j-m_LeftEye.x] ++;
}
}
int maxY = 0;
for(i =0 ;i < MouthDown-MouthUp ;i++)
{
if(Y_Arry[i]>maxY)
{
maxY = Y_Arry[i];
m_MidMouth.y = i+MouthUp - (MouthDown-MouthUp)/10;
}
}
m_LeftMouthCorner.y =(int)(m_MidMouth.y - tanThta*EyesDis/2);
m_RightMouthCorner.y =(int)(m_MidMouth.y + tanThta*EyesDis/2);
for(i =0 ;i < EyesDis ;i++)
{
if(X_Arry[i]>0)
{
m_LeftMouthCorner.x = i+m_LeftEye.x;
break;
}
}
for(i = EyesDis -1; i >=0 ;i--)
{
if(X_Arry[i]>0)
{
m_RightMouthCorner.x = m_LeftEye.x+i;
break;
}
}
//唇中点较薄
int min = 1000000;
for(i = (int)(3*EyesDis/7+0.5) ; i <= (int)(4*EyesDis/7+0.5);i++)
{
if(X_Arry[i]<min)
{
min = X_Arry[i];
m_MidMouth.x = m_LeftEye.x+i;
}
}
m_MidMouth.x = (int)(m_MidMouth.x+(m_LeftEye.x+EyesDis/2))/2;
m_bMidMouthOK = TRUE;
m_bLeftMouthCornerOK = TRUE;
m_bRightMouthCornerOK = TRUE;
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
MakeBitMap();
}
////////////////////////////////////////////////////////////////////////////////
// 标记鼻子
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnMarkNose()
{
int i,j;
if(!(m_bLeftEyeOK&&m_bRightEyeOK))
{
AfxMessageBox("请先确定眼睛");
return;
}
//左右眼的水平区域
int nLeft,nRight,nTop,nBottom;
nLeft = m_rFaceRegion.left-5 > 0 ? m_rFaceRegion.left-5:0;
nRight = m_rFaceRegion.right+5 < m_nWndWidth? m_rFaceRegion.right+5:m_nWndWidth-1;
nTop = m_rFaceRegion.top-5 > 0 ? m_rFaceRegion.top-5:0;
nBottom = m_rFaceRegion.bottom+5< m_nWndHeight?m_rFaceRegion.bottom+5:m_nWndHeight-1;
SetPixelArray(m_tResPixelArray,0);
for(i=nTop; i<=nBottom; i++)
for(j=nLeft; j<=nRight; j++)
{
double Y;
Y = 0.30*m_tOriPixelArray[i][j].rgbRed+0.59*m_tOriPixelArray[i][j].rgbGreen
+0.11*m_tOriPixelArray[i][j].rgbBlue;
if(Y<100)
{
m_tResPixelArray[i][j].rgbRed = 255;
}
else m_tResPixelArray[i][j].rgbRed = 0;
}
MakeBitMap();
AfxMessageBox("鼻子的肤色鉴定");
//双目斜角
double tanThta;
if(m_RightEye.y == m_LeftEye.y) tanThta = 0;
else tanThta = (m_RightEye.y - m_LeftEye.y)/(m_RightEye.x - m_LeftEye.x);
//双目距离
int EyesDis = (m_RightEye.x-m_LeftEye.x)*(m_RightEye.x-m_LeftEye.x);
EyesDis += (m_RightEye.y-m_LeftEye.y)*(m_RightEye.y-m_LeftEye.y);
EyesDis = (int)sqrt(EyesDis);
//双目平均高度
int EyeV = (m_RightEye.y + m_LeftEye.y)/2;
//可能的鼻子的区域
int NoseUp = (EyeV+0.5*EyesDis) > nBottom ? nBottom:(int)(EyeV+0.5*EyesDis);
int NoseDown = (EyeV+0.8*EyesDis) > nBottom ? nBottom:(int)(EyeV+0.8*EyesDis);
int* Y_Arry = new int[NoseDown-NoseUp];
for(i =0 ;i < NoseDown-NoseUp ;i++) Y_Arry[i] = 0;
int* X_Arry = new int[EyesDis];
for(i =0 ;i < EyesDis ;i++) X_Arry[i] = 0;
for(i = NoseUp ; i < NoseDown; i++)
for(j = m_LeftEye.x+EyesDis/5; j< m_RightEye.x-EyesDis/5; j++)
{
if(m_tResPixelArray[i][j].rgbRed == 255)
{
Y_Arry[i-NoseUp] ++;
X_Arry[j-m_LeftEye.x] ++;
}
}
int maxY = 0;
for(i =0 ;i < NoseDown-NoseUp ;i++)
{
if(Y_Arry[i]>maxY)
{
maxY = Y_Arry[i];
m_MidNose.y = i+NoseUp;
}
}
m_LeftNostril.y =(int)(m_MidNose.y - tanThta*EyesDis/2);
m_RightNostril.y =(int)(m_MidNose.y + tanThta*EyesDis/2);
for(i =0 ;i < EyesDis ;i++)
{
if(X_Arry[i]>0)
{
m_LeftNostril.x = i+m_LeftEye.x;
break;
}
}
for(i = EyesDis-1; i >=0 ;i--)
{
if(X_Arry[i]>0)
{
m_RightNostril.x = i+m_LeftEye.x;
break;
}
}
//唇中点较薄
int min = 1000000;
for(i = (int)(EyesDis/3+0.5) ; i <= (int)(2*EyesDis/3+0.5);i++)
{
if(X_Arry[i]<min)
{
min = X_Arry[i];
m_MidNose.x = m_LeftEye.x+i;
}
}
m_MidNose.x = (m_MidNose.x+(m_LeftEye.x+EyesDis/2))/2;
m_bMidNoseOK = TRUE;
m_bLeftNostrilOK = TRUE;
m_bRightNostrilOK = TRUE;
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
MakeBitMap();
}
////////////////////////////////////////////////////////////////////////////////
// 打开文件
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnOpenfile()
{
CAddSampleDlg FileDlg(TRUE, "", NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT,
"BMP人脸图像(*.bmp)|*.bmp|所有文件(*.*)|*.*||",
AfxGetMainWnd());
CString strFile;
if (FileDlg.DoModal () != IDOK)
return;
POSITION pos = FileDlg.GetStartPosition();
strFile = FileDlg.GetNextPathName(pos);
m_pMainDib->Open(strFile);
m_nWndWidth = m_pMainDib->GetWidth();
m_nWndHeight= m_pMainDib->GetHeight();
m_sFileName = strFile;
m_rFaceRegion.left = m_rFaceRegion.right = m_rFaceRegion.top = m_rFaceRegion.bottom = 0;
m_bLeftEyeOK = m_bRightEyeOK = m_bLeftNostrilOK = m_bRightNostrilOK =
m_bLeftEyeLeftCornerOK = m_bLeftEyeRightCornerOK = m_bRightEyeLeftCornerOK =
m_bRightEyeRightCornerOK = m_bLeftMouthCornerOK = m_bRightMouthCornerOK = false;
m_bMidMouthOK = m_bMidNoseOK = false;
m_LeftEye = m_RightEye = m_LeftEyeLeftCorner = m_LeftEyeRightCorner =
m_LeftNostril = m_RightNostril = m_RightEyeLeftCorner = m_RightEyeRightCorner =
m_LeftMouthCorner = m_RightMouthCorner = m_MidMouth = m_MidNose = CPoint(-1,-1);
SetCursor(LoadCursor(NULL,IDC_WAIT));
//获取像素的值
LoadOriPixel(m_pMainDib);
MakeBitMap();
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
////////////////////////////////////////////////////////////////////////////////
// 画图
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::MyDraw()
{
CRect rc;
pDCShow->GetWindow()->GetClientRect(&rc);
pDCShow->Rectangle(&rc);
CDC dc;
CBitmap *pOldBitmap;
dc.CreateCompatibleDC(pDCShow);
pOldBitmap=dc.SelectObject(m_pResMap);
pDCShow->StretchBlt(0,0,m_nWndWidth,m_nWndHeight,&dc,0,0,m_nWndWidth,m_nWndHeight,SRCCOPY);
dc.SelectObject(pOldBitmap);
dc.DeleteDC();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -