⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 facedetectdlg.cpp

📁 人脸检测定位的示例代码.rar VC++源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		}
	}
	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 + -