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

📄 facedetectdlg.cpp

📁 本程序中列举了数字图象模式识别领域中的常用程序,可以在其基础上进行图象处理.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	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 + -