📄 facedetectdlg.cpp
字号:
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
////////////////////////////////////////////////////////////////////////////////
// 水平方向直方图
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnHistogramH()
{
if(!method1->m_bBinaryReady)
{
AfxMessageBox("请先计算二值图");
return;
}
m_bShowFace = false;
SetCursor(LoadCursor(NULL,IDC_WAIT));
for(int j=0; j<m_nWndWidth; j++)
{
int count = 0;
for(int i=0; i<m_nWndHeight; i++)
{
if(method1->m_pBinaryArray[i][j] == 1) count++;
m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
m_tResPixelArray[i][j].rgbRed = 255;
}
for(i=m_nWndHeight-1; i>=m_nWndHeight-count;i--)
{
m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
m_tResPixelArray[i][j].rgbRed = 0;
}
}
MakeBitMap();
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
////////////////////////////////////////////////////////////////////////////////
// 头发的直方图
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnHistogramHair()
{
if(!method2->m_bBinaryOK)
{
AfxMessageBox("请先计算二值图!");
return;
}
m_bShowFace = false;
SetCursor(LoadCursor(NULL,IDC_WAIT));
for(int j=0; j<m_nWndWidth; j++)
{
int count = 0;
for(int i=0; i<m_nWndHeight; i++)
{
if(method2->m_pBinaryArray[i][j] == 1) count++;
m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
m_tResPixelArray[i][j].rgbRed = 255;
}
for(i=m_nWndHeight-1; i>=m_nWndHeight-count;i--)
{
m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
m_tResPixelArray[i][j].rgbRed = 0;
}
}
MakeBitMap();
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
////////////////////////////////////////////////////////////////////////////////
// 垂直方向的直方图
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnHistogramV()
{
if(!method1->m_bBinaryReady)
{
AfxMessageBox("请先计算二值图");
return;
}
m_bShowFace = false;
SetCursor(LoadCursor(NULL,IDC_WAIT));
for(int i=0; i<m_nWndHeight; i++)
{
int count = 0;
for(int j=0; j<m_nWndWidth; j++)
{
if(method1->m_pBinaryArray[i][j] == 1) count++;
m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
m_tResPixelArray[i][j].rgbRed = 255;
}
for(j=0; j<count; j++)
{
m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
m_tResPixelArray[i][j].rgbRed = 0;
}
}
MakeBitMap();
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
////////////////////////////////////////////////////////////////////////////////
// 计算相似度
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnLikehood()
{
m_bShowFace = false;
SetCursor(LoadCursor(NULL,IDC_WAIT));
method1->CalLikeHood();
for(int i=0; i<m_nWndHeight; i++)
for(int j=0; j<m_nWndWidth; j++)
{
m_tResPixelArray[i][j].rgbBlue = m_tResPixelArray[i][j].rgbGreen =
m_tResPixelArray[i][j].rgbRed = (int)(method1->m_pLikeliHoodArray[i][j]*255);
}
MakeBitMap();
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
////////////////////////////////////////////////////////////////////////////////
// 标记眼睛区域
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnMarkEye()
{
int i,j;
if(!m_bFaceOK)
{
AfxMessageBox("请先确定脸部区域");
return;
}
//左右眼的水平区域
CPoint LeftEyeAreaH(-1,-1),RightEyeAreaH(-1,-1);
CPoint LeftEyeAreaV(-1,-1),RightEyeAreaV(-1,-1);
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;
//边缘检查
DoLOG(nLeft,nRight,nTop,nBottom,m_tOriPixelArray,m_tResPixelArray);
///////////////////////////////////
//确认两个眼睛的水平区域
//////////////////////////////////
int nSlidWinWidth = (m_rFaceRegion.right - m_rFaceRegion.left)/6/2;
int nSlidWinHeight = (m_rFaceRegion.bottom - m_rFaceRegion.top)/15/2;
int nMidFaceH = (m_rFaceRegion.right+m_rFaceRegion.left)/2;
int nMidFaceV = (m_rFaceRegion.bottom+m_rFaceRegion.top)/2;
int *tempArray = new int[m_nWndWidth];
for(i = 0; i<m_nWndWidth; i++) tempArray[i] = 0;
for(i=nMidFaceV-nSlidWinHeight; i > m_rFaceRegion.top+6*nSlidWinHeight; i--)
for(j=m_rFaceRegion.left+nSlidWinWidth; j<m_rFaceRegion.right-nSlidWinWidth; j++)
{
int count = 0;
for(int p= -nSlidWinHeight ;p<nSlidWinHeight;p++)
for(int q= -nSlidWinWidth ;q<nSlidWinWidth;q++)
{
if(m_tResPixelArray[i+p][j+q].rgbRed == 0) count++;
}
if(count >= nSlidWinWidth*nSlidWinHeight/3)
{
m_tResPixelArray[i][j].rgbRed = 255;
tempArray[j] ++;
}
}
MakeBitMap();
AfxMessageBox("眼睛的区域鉴别");
CList<CPoint,CPoint&> myList1(sizeof(CPoint));
CList<CPoint,CPoint&> myList2(sizeof(CPoint));
int flag = 0;
CPoint tPoint(-1,-1);
for(i = 0; i<m_nWndWidth; i++)
{
if(tempArray[i] > 0 && flag ==0)
{
tPoint.x = i;
flag = 1;
}
if(tempArray[i] == 0 && flag ==1)
{
tPoint.y = i;
myList1.AddTail(tPoint);
flag = 0;
}
}
delete tempArray;
//去掉长度太小的候选者
for(i=0; i<myList1.GetCount();i++)
{
CPoint temp(-1,-1);
temp = myList1.GetAt(myList1.FindIndex(i));
int minVal = (m_rFaceRegion.right - m_rFaceRegion.left)/20;
if((temp.y-temp.x)>=minVal)
myList2.AddTail(temp);
}
myList1.RemoveAll();
//合并相邻很紧的区域
bool quit = 1;
while(quit)
{
bool doJoin = false;
for(int i=0; i<myList2.GetCount()-1;i++)
{
CPoint temp1(-1,-1),temp2(-1,-1);
temp1 = myList2.GetAt(myList2.FindIndex(i));
temp2 = myList2.GetAt(myList2.FindIndex(i+1));
if((temp2.x-temp1.y)<=(m_rFaceRegion.right - m_rFaceRegion.left)/40)
{
temp1.y = temp2.y;
myList2.RemoveAt(myList2.FindIndex(i));
myList2.RemoveAt(myList2.FindIndex(i));
if(i == 0) myList2.AddHead(temp1);
else myList2.InsertAfter(myList2.FindIndex(i-1),temp1);
doJoin = true;
break;
}
}
if(!doJoin) quit = 0;
}
//没有找到眼睛区域
if(myList2.GetCount()<2)
{
CPoint t=myList2.GetHead();
if((t.y-t.x)>(m_rFaceRegion.right - m_rFaceRegion.left)/2)
{
LeftEyeAreaH.x = t.x;
LeftEyeAreaH.y = t.x+(t.y-t.x)/3;
RightEyeAreaH.x = t.y-(t.y-t.x)/3;
RightEyeAreaH.y = t.y;
}
else
{
AfxMessageBox("确认眼睛位置失败,请手动标定");
return;
}
}
//仅有两个区域
else if(myList2.GetCount()==2)
{
LeftEyeAreaH = myList2.GetHead();
RightEyeAreaH = myList2.GetTail();
}
else //多于两个区域
{
int ldis = -100000;
int rdis = 100000;
for(i=0; i<myList2.GetCount();i++)
{
CPoint temp(-1,-1);
temp = myList2.GetAt(myList2.FindIndex(i));
//右眼
if((temp.x+temp.y)/2 > nMidFaceH)
{
if(((temp.x+temp.y)/2-nMidFaceH)<rdis)
{
rdis = (temp.x+temp.y)/2-nMidFaceH;
RightEyeAreaH = temp;
}
}
//左眼
else
{
if(((temp.x+temp.y)/2-nMidFaceH)>ldis)
{
ldis = (temp.x+temp.y)/2-nMidFaceH;
LeftEyeAreaH = temp;
}
}
}
}
myList2.RemoveAll();
///////////////////////////////////
//确认两个眼睛的垂直区域
//////////////////////////////////
//左眼
if(LeftEyeAreaH != CPoint(-1,-1))
{
int *tArray = new int[m_nWndHeight];
int i,j;
for(i = 0; i<m_nWndHeight; i++) tArray[i] = 0;
for(i=nMidFaceV-nSlidWinHeight; i > m_rFaceRegion.top+6*nSlidWinHeight; i--)
for(j=LeftEyeAreaH.x; j<=LeftEyeAreaH.y;j++)
if(m_tResPixelArray[i][j].rgbRed == 255 && m_tResPixelArray[i][j].rgbGreen == 0)
tArray[i] ++;
CList<CPoint,CPoint&> myListA(sizeof(CPoint));
CList<CPoint,CPoint&> myListB(sizeof(CPoint));
int flag = 0;
CPoint tPoint(-1,-1);
for(i = nMidFaceV-nSlidWinHeight; i > m_rFaceRegion.top+6*nSlidWinHeight; i--)
{
if(tArray[i] > 0 && flag ==0)
{
tPoint.x = i;
flag = 1;
}
if(tArray[i] == 0 && flag ==1)
{
tPoint.y = i;
myListA.AddTail(tPoint);
flag = 0;
}
}
delete tArray;
//去掉长度太小的候选者
for(i=0; i<myListA.GetCount();i++)
{
CPoint temp(-1,-1);
temp = myListA.GetAt(myListA.FindIndex(i));
int minVal = (m_rFaceRegion.bottom - m_rFaceRegion.top)/100;
if((temp.x-temp.y)>=minVal)
myListB.AddTail(temp);
}
myListA.RemoveAll();
//合并相邻很紧的区域
bool quit = 1;
while(quit)
{
bool doJoin = false;
for(int i=0; i<myListB.GetCount()-1;i++)
{
CPoint temp1(-1,-1),temp2(-1,-1);
temp1 = myListB.GetAt(myListB.FindIndex(i));
temp2 = myListB.GetAt(myListB.FindIndex(i+1));
if((temp1.y-temp2.x)<=(m_rFaceRegion.bottom - m_rFaceRegion.top)/100)
{
temp1.y = temp2.y;
myListB.RemoveAt(myListB.FindIndex(i));
myListB.RemoveAt(myListB.FindIndex(i));
if(i == 0) myListB.AddHead(temp1);
else myListB.InsertAfter(myListB.FindIndex(i-1),temp1);
doJoin = true;
break;
}
}
if(!doJoin) quit = 0;
}
if(myListB.GetCount()==0)
{
AfxMessageBox("无法确定左眼的位置");
}
else
{
LeftEyeAreaV = myListB.GetHead();
double sumX = 0.0;
double sumY = 0.0;
int sum = 0;
m_LeftEyeLeftCorner.x = 100000;
m_LeftEyeRightCorner.x = -1;
for(i=LeftEyeAreaV.x; i>= LeftEyeAreaV.y;i--)
for(j=LeftEyeAreaH.x; j<=LeftEyeAreaH.y;j++)
if(m_tResPixelArray[i][j].rgbGreen == 0)
{
if(j<m_LeftEyeLeftCorner.x)
{
m_LeftEyeLeftCorner.x = j;
m_LeftEyeLeftCorner.y = i;
}
if(j>m_LeftEyeRightCorner.x)
{
m_LeftEyeRightCorner.x = j;
m_LeftEyeRightCorner.y = i;
}
sumX += j;
sumY += i;
sum++;
}
m_LeftEye.x = (int)(sumX/sum);
m_LeftEye.y = (int)(sumY/sum);
m_bLeftEyeOK = TRUE;
m_bLeftEyeLeftCornerOK = TRUE;
m_bLeftEyeRightCornerOK =TRUE;
}
myListB.RemoveAll();
}
//右眼
if(RightEyeAreaH != CPoint(-1,-1))
{
int *tArray = new int[m_nWndHeight];
int i,j;
for(i = 0; i<m_nWndHeight; i++) tArray[i] = 0;
for(i=nMidFaceV-nSlidWinHeight; i > m_rFaceRegion.top+6*nSlidWinHeight; i--)
for(j=RightEyeAreaH.x; j<=RightEyeAreaH.y;j++)
if(m_tResPixelArray[i][j].rgbRed == 255 && m_tResPixelArray[i][j].rgbGreen == 0)
tArray[i] ++;
CList<CPoint,CPoint&> myListA(sizeof(CPoint));
CList<CPoint,CPoint&> myListB(sizeof(CPoint));
int flag = 0;
CPoint tPoint(-1,-1);
for(i = nMidFaceV-nSlidWinHeight; i > m_rFaceRegion.top+6*nSlidWinHeight; i--)
{
if(tArray[i] > 0 && flag ==0)
{
tPoint.x = i;
flag = 1;
}
if(tArray[i] == 0 && flag ==1)
{
tPoint.y = i;
myListA.AddTail(tPoint);
flag = 0;
}
}
delete tArray;
//去掉长度太小的候选者
for(i=0; i<myListA.GetCount();i++)
{
CPoint temp(-1,-1);
temp = myListA.GetAt(myListA.FindIndex(i));
int minVal = (m_rFaceRegion.bottom - m_rFaceRegion.top)/100;
if((temp.x-temp.y)>=minVal)
myListB.AddTail(temp);
}
myListA.RemoveAll();
//合并相邻很紧的区域
bool quit = 1;
while(quit)
{
bool doJoin = false;
for(int i=0; i<myListB.GetCount()-1;i++)
{
CPoint temp1(-1,-1),temp2(-1,-1);
temp1 = myListB.GetAt(myListB.FindIndex(i));
temp2 = myListB.GetAt(myListB.FindIndex(i+1));
if((temp1.y-temp2.x)<=(m_rFaceRegion.bottom - m_rFaceRegion.top)/50)
{
temp1.y = temp2.y;
myListB.RemoveAt(myListB.FindIndex(i));
myListB.RemoveAt(myListB.FindIndex(i));
if(i == 0) myListB.AddHead(temp1);
else myListB.InsertAfter(myListB.FindIndex(i-1),temp1);
doJoin = true;
break;
}
}
if(!doJoin) quit = 0;
}
if(myListB.GetCount()==0)
{
AfxMessageBox("无法确定右眼的位置");
}
else
{
if(myListB.GetCount()==1)
RightEyeAreaV = myListB.GetHead();
else
{
CPoint tt = myListB.GetHead();
int index = myListB.GetCount();
while(tt.y > LeftEyeAreaV.x && index > 0)
{
index --;
tt = myListB.GetAt(myListB.FindIndex(myListB.GetCount()-index));
}
RightEyeAreaV = tt;
}
double sumX = 0.0;
double sumY = 0.0;
int sum = 0;
m_RightEyeLeftCorner.x = 100000;
m_RightEyeRightCorner.x = -1;
for(i=RightEyeAreaV.x; i>=RightEyeAreaV.y;i--)
for(j=RightEyeAreaH.x; j<=RightEyeAreaH.y;j++)
if(m_tResPixelArray[i][j].rgbGreen == 0)
{
if(j<m_RightEyeLeftCorner.x)
{
m_RightEyeLeftCorner.x = j;
m_RightEyeLeftCorner.y = i;
}
if(j>m_RightEyeRightCorner.x)
{
m_RightEyeRightCorner.x = j;
m_RightEyeRightCorner.y = i;
}
sumX += j;
sumY += i;
sum++;
}
m_RightEye.x = (int)(sumX/sum);
m_RightEye.y = (int)(sumY/sum);
m_bRightEyeOK = TRUE;
m_bRightEyeLeftCornerOK = TRUE;
m_bRightEyeRightCornerOK =TRUE;
}
myListB.RemoveAll();
}
CopyBitMap(m_tResPixelArray,m_tOriPixelArray);
MakeBitMap();
}
////////////////////////////////////////////////////////////////////////////////
// 第一种方法标记脸部区域
////////////////////////////////////////////////////////////////////////////////
void CFaceDetectDlg::OnBtnMarkFace1()
{
if(!method1->m_bBinaryReady)
{
AfxMessageBox("请先计算二值化图!");
return;
}
m_bShowFace = true;
SetCursor(LoadCursor(NULL,IDC_WAIT));
int *temp = new int[m_nWndWidth];
int max = 0;
int pos = -1;
for(int j=0; j<m_nWndWidth; j++)
{
int count = 0;
for(int i=0; i<m_nWndHeight; i++)
{
if(method1->m_pBinaryArray[i][j] == 1) count++;
}
temp[j] = count;
if(count > max)
{
max = count;
pos = j;
}
}
int left,right,l,top,bottom;
for(l=pos; l>=0; l--)
{
if(temp[l]<max*0.2||l==0)
{
left = l;
break;
}
}
for(l=pos; l<m_nWndWidth; l++)
{
if(temp[l]<max*0.3||l==m_nWndWidth-1)
{
right = l;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -