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

📄 mainfrm.cpp

📁 VC各工程的源码集合
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	for(i=0;i<255;i++)
	{
		PixelNum[i]=0;
	}	
	
	int calNum=0;//连续区域的个数;

	for(i=0;i<(lpbi->biHeight);i++)
		for(j=0;j<(lpbi->biWidth);j++)
		{
			Offset=PixelOffset(i,j,wBytesPerLine);
			if((*(lpb+Offset)==255)&&(*(lpb+Offset+1)==255)&&(*(lpb+Offset+2)==255))//如果当前点的像素颜色是白色,则递归统计该区域内连续白色像素点的个数;
			{
				calNum++;
				RecursiveCal(lpb,i,j,wBytesPerLine,&(PixelNum[calNum]),calNum);
				//如果采集到的人脸面积过大,
				//那么,程序在递归的过程中会造成系统stack溢出,
				//应如何解决?
			
			}
		}
	
	const int AREAPIXEL=1200;//表示人脸的像素个数必须大于AREAPIXEL;

	int face_num=calNum;
/*
	for(i=0;i<calNum;i++)
	{
		//如果像素点个数小于一定数目则把这个标志设置为0
		if(PixelNum[i]<AREAPIXEL)
		{
			PixelNum[i]=0;
			face_num--;
		}
	}
*/
	int max=0,pnum;
	for(i=1;i<=calNum;i++)
	{
		if(PixelNum[i]>max)
		{
			max=PixelNum[i];
			pnum=i;
		}
	}

	for(i=1;i<=calNum;i++)
	{
		if(i!=pnum)
		{
			PixelNum[i]=0;
			face_num--;
		}
	}
	
	if(PixelNum[pnum]<AREAPIXEL)
	{
		PixelNum[pnum]=0;
		face_num--;
	}

	//下面的循环根据标志数组来最终设定图像的颜色;
	for(i=0;i<(lpbi->biHeight);i++)
		for(j=0;j<(lpbi->biWidth);j++)
		{
			Offset=PixelOffset(i,j,wBytesPerLine);
			int num=*(lpb+Offset);
//			int num2=*(lpb+Offset+1);
//			int num3=*(lpb+Offset+2);
			//如果当前点不是黑色点;
			if(num!=0)
			{
				//如果当前点标志数组为0,则设置为黑色;
				if(PixelNum[num]==0)
				{
					*(lpb+Offset)=0;
					*(lpb+Offset+1)=0;
					*(lpb+Offset+2)=0;
				}
				//否则设置为白色;
				else
				{
					*(lpb+Offset)=255;
					*(lpb+Offset+1)=255;
					*(lpb+Offset+2)=255;
				}
			}
		}
/*
//---------------------------------------------------
	m_iscapture=FALSE;
	m_after_skindect=TRUE;

	(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
	InvalidateRect(NULL,FALSE);
	AfxMessageBox("已去掉非人脸区域!",MB_OK,0);
*/	
//--------------------------------------------------
	return(face_num);
}

//递归统计该区域连续的白色点像素点个数;
void CMainFrame::RecursiveCal(unsigned char *  lpData,int y,int x,DWORD wBytesPerLine,int * pixelNum,int num) 
{
	LPBITMAPINFOHEADER lpbi;
	lpbi=&m_bitmapheader; 
	
	long Offset=PixelOffset(y,x,wBytesPerLine);
	//如果当前点为白色点;
	if((*(lpData+Offset)==255)&&(*(lpData+Offset+1)==255)&&(*(lpData+Offset+2)==255))
	{
		//把当前点大小设置为序号值;
		*(lpData+Offset++)=num;
		*(lpData+Offset++)=num;
		*(lpData+Offset++)=num;
		//像素个数加1
		(*pixelNum)++;

		int tempx;
		int tempy;
		//递归当前点下面的点;
		tempy=y-1;
		tempx=x;
		if((y-1)>=0)
			RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
		
		//递归当前点上面的点;
		tempy=y+1;
		tempx=x;
		if((y+1)<=lpbi->biHeight)
			RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
		
		//递归当前点左边的点;
		tempy=y;
		tempx=x-1;
		if((x-1)>=0)
			RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
		
		//递归当前点右边的点;
		tempy=y;
		tempx=x+1;
		if((x+1)<=lpbi->biWidth)
			RecursiveCal(lpData,tempy,tempx,wBytesPerLine,pixelNum,num);
	}
}




//---------------------------------------------------------
void CMainFrame::OnFace() 
{
	// TODO: Add your command handler code here

	if(m_enable_skindect)
	{
//		RGB_Copydata();

//		rgb_histogram();

		RGBToYCrCb();//对得到的视频帧信息进行色彩空间(RGB->YCrCb)的转换,转换后的数据信息存放在m_ycc_buffer[30000]中;
//---------------------------------------------------
		m_iscapture=FALSE;
		m_after_skindect=TRUE;

		(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
		InvalidateRect(NULL,FALSE);

		AfxMessageBox("已转换色彩!",MB_OK,0);
//---------------------------------------------------

//		ycc_histogram();

//		(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
//		InvalidateRect(NULL,FALSE);

		Skin_detection();//YCrCb空间肤色检测操作;

//		RGB_Copydata();
//		RGB_Skin_detection();
		dilation();//在视频帧的数据信息中对肤色像素进行膨胀、腐蚀操作;
		erosion();

//---------------------------------------------------
		m_iscapture=FALSE;
		m_after_skindect=TRUE;

		(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
		InvalidateRect(NULL,FALSE);
		AfxMessageBox("已检测好肤色!",MB_OK,0);
	
//---------------------------------------------------

	


		int FaceNum=ErasionFalseArea();
		//去掉非人脸区域,记录下人脸区域的个数;
/*
//---------------------------------------------------
		m_iscapture=FALSE;
		m_after_skindect=TRUE;

		(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
		InvalidateRect(NULL,FALSE);
		AfxMessageBox("已去掉非人脸区域!",MB_OK,0);
	
//--------------------------------------------------
*/
		if(FaceNum==0)
		{
			AfxMessageBox("采集的视频帧中没有人脸,请重新采集!",MB_OK,0);
		}
		else
		{
			AfxMessageBox("可以定位人脸了!",MB_OK,0);
//---------------------------------------------------
			m_iscapture=FALSE;
			m_after_skindect=TRUE;

			(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
			InvalidateRect(NULL,FALSE);

	
//---------------------------------------------------
//			CWnd * p_CWnd=AfxGetMainWnd();
//			CMenu * p_CMenu=p_CWnd->GetMenu();
//			CMenu * p_Sub_CMenu=p_CMenu->GetSubMenu(5);
//			p_Sub_CMenu->EnableMenuItem(ID_FACE, MF_ENABLED);
		}
	
//		dilation();//在视频帧的数据信息中对肤色像素进行膨胀、腐蚀操作;
//		erosion();
		m_enable_skindect=FALSE;
		m_enable_facelac=TRUE;
	}
	else
	{
		AfxMessageBox("请先采集视频帧!",MB_OK,0);	
	}
	return;
	//如果人脸区域的个数为0,则出现"采集的视频帧中没有人脸,请重新采集"的提示框;
	//否则,把"人脸定位"菜单项置为可用菜单项,并出现"可定位人脸"的提示框。

}

void CMainFrame::scan()
{
	int i,j;
	int BlackPixelNum=0;
	int flagy=0;
	//标记是否出现下边界,0表示没有出现下边界,1表示出现了下边界;
	int flagx=0; 
	//标记是否出现左边界,0表示没有出现左边界,1表示出现了左边界;
	long Offset;
	unsigned char * lpb;
	lpb=m_ycc_buffer;
//	lpb=m_rgb_buffer;

	LPBITMAPINFOHEADER lpbi;
	lpbi=&m_bitmapheader; 
	//lpbi_ycc是指向"存放'以YCrCb色彩空间表达的数据信息'的信息头信息"的指针;
//	lpbi=&m_rgb_bitmapheader;
	
	DWORD wBytesPerLine=BytePerLine(lpbi);
	//得到每行像素所占用的字节数;
		
	//从下往上扫描图像
	for(i=0;i<lpbi->biHeight;i++)
	{
		if(flagy==0)
		{
			for(j=0;j<lpbi->biWidth;j++)
			{
				Offset=PixelOffset(i,j,wBytesPerLine); 
				//得到像素点数据在整个数据区中的偏移;
				if((*(lpb+Offset)==255)&&(*(lpb+Offset+1)==255)&&(*(lpb+Offset+2)==255))
				{
					m_y1=i;
					//记下人脸的下边界;
					flagy=1;
					break;
				}
			}
			continue;
		}
		else
		{
			for(j=0;j<lpbi->biWidth;j++)
			{
				Offset=PixelOffset(i,j,wBytesPerLine); 
				//得到像素点数据在整个数据区中的偏移;
				if((*(lpb+Offset)==0)&&(*(lpb+Offset+1)==0)&&(*(lpb+Offset+2)==0))
				{
					++BlackPixelNum;//记录当前行的黑色像素的个数;
				}
			}
			if(BlackPixelNum==lpbi->biWidth)
			{
				m_y2=i; //记下人脸的上边界;
				break;
			}
			else 
			{
				BlackPixelNum=0;
				continue;//否则扫描下一行;
			}
		}
	}
	if(m_y2==-1)
		m_y2=lpbi->biHeight-1;

	//从左往右扫描图像;
	BlackPixelNum=0;
	for(i=0;i<lpbi->biWidth;i++)
	{
		if(flagx==0)
		{
			for(j=0;j<lpbi->biHeight;j++)
			{
				Offset=PixelOffset(j,i,wBytesPerLine);
				//得到像素点数据在整个数据区中的偏移;
				if(*(lpb+Offset)==255)
					{
						m_x1=i;
						//记下人脸的左边界;
						flagx=1;
						break;
					}
			}
			continue;
		}
		else
		{
			for(j=0;j<lpbi->biHeight;j++)
			{
				Offset=PixelOffset(j,i,wBytesPerLine); 
				//得到像素点数据在整个数据区中的偏移;
				if(*(lpb+Offset)==0)
				{
				++BlackPixelNum;//记录当前行的黑色像素的个数;
				}
			}
			if(BlackPixelNum==lpbi->biHeight)
			{
				m_x2=i; //记下人脸的右边界;
				break;
			}
			else 
			{
				BlackPixelNum=0;
				continue;//否则扫描下一列;
			}
		}
	}
	if(m_x2==-1)
		m_x2=lpbi->biWidth-1;
}

void CMainFrame::OnFacelocation() 
{
	// TODO: Add your command handler code here
	//大致定位人脸区域;

	int i,j;
//	int BlackPixelNum=0;
//	int flagy=0;
	//标记是否出现下边界,0表示没有出现下边界,1表示出现了下边界;
//	int flagx=0; 
	//标记是否出现左边界,0表示没有出现左边界,1表示出现了左边界;
	long Offset;
	unsigned char * lpb;
	lpb=m_ycc_buffer;
//	lpb=m_rgb_buffer;

	LPBITMAPINFOHEADER lpbi;
	lpbi=&m_bitmapheader; 
	//lpbi_ycc是指向"存放'以YCrCb色彩空间表达的数据信息'的信息头信息"的指针;
//	lpbi=&m_rgb_bitmapheader;
	
	DWORD wBytesPerLine=BytePerLine(lpbi);
	//得到每行像素所占用的字节数;

//	m_y1=1;
//	m_y2=143;
//	m_x1=1;
//	m_x2=175;
	const int AREAPIXEL=1200;//表示人脸的像素个数必须大于AREAPIXEL;
	int square=0;	
	if(m_enable_facelac)
	{
		while(square<AREAPIXEL)
		{
			m_x1=-1;
			m_x2=-1;
			m_y1=-1;
			m_y2=-1;

			scan();
			square=(m_x2-m_x1)*(m_y2-m_y1);
			
			if(square<AREAPIXEL)
			{
				for(i=m_y1;i<=(m_y2);i++)
					for(j=m_x1;j<=(m_x2);j++)
					{
						Offset=PixelOffset(i,j,wBytesPerLine);
						*(lpb+Offset)=0;
						*(lpb+Offset+1)=0;
						*(lpb+Offset+2)=0;
					}
			}
			
			
		}
		
		lpb=((CMainFrame*)AfxGetMainWnd())->m_dibinfo.buffer
		+((CMainFrame*)AfxGetMainWnd())->m_dibinfo.VideoFormatSize;
		//用矩形定位人脸,矩形边线呈绿色
		//画人脸的下边界
		i=m_y1;
		for(j=m_x1;j<=m_x2;j++)
		{
			Offset=PixelOffset(i,j,wBytesPerLine); 
			//得到像素点数据在整个数据区中的偏移;
			*(lpb+Offset)=0;
			*(lpb+Offset+1)=255;
			*(lpb+Offset+2)=0;
		}
		//画人脸的上边界;
		i=m_y2;
		for(j=m_x1;j<=m_x2;j++)
		{
			Offset=PixelOffset(i,j,wBytesPerLine); 
			//得到像素点数据在整个数据区中的偏移;
			*(lpb+Offset)=0;
			*(lpb+Offset+1)=255;
			*(lpb+Offset+2)=0;
		}
	//画人脸的左边界;
		j=m_x1;
		for(i=m_y1;i<=m_y2;i++)
		{
			Offset=PixelOffset(i,j,wBytesPerLine); 
			//得到像素点数据在整个数据区中的偏移;
			*(lpb+Offset)=0;
			*(lpb+Offset+1)=255;
			*(lpb+Offset+2)=0;
		}
		//画人脸的右边界;
		j=m_x2;
		for(i=m_y1;i<=m_y2;i++)
		{
			Offset=PixelOffset(i,j,wBytesPerLine); 
			//得到像素点数据在整个数据区中的偏移;
			*(lpb+Offset)=0;
			*(lpb+Offset+1)=255;
			*(lpb+Offset+2)=0;
		}
	
		m_iscapture=TRUE;
		m_after_skindect=FALSE;
		(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
		InvalidateRect(NULL,FALSE);
	}
	else
	{
		AfxMessageBox("请先确定人脸存在再定位!",MB_OK,0);	
	}
	m_enable_facelac=FALSE;
}


void CMainFrame::OnVideofacelac() 
{
	// TODO: Add your command handler code here
	if(videoflag==FALSE)
		videoflag=TRUE;
	else
		videoflag=FALSE;
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -