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

📄 dib.cpp

📁 一个简单的基于肤色模型的人脸检测程序。基于DSPTMSP6711;
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	GlobalFree(hTempDIB);

}
void DIB::Dilation(HANDLE hDIB)
{
	LPBITMAPINFOHEADER lpbi;
	int height;
	int width;
	WORD wBytesPerLine;
	LPBYTE lpData;
	LPBYTE lpTemp;
	long lOffset;
	//得到图象的基本信息
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
	height = lpbi->biHeight;
	width = lpbi->biWidth;
	wBytesPerLine = this->BytePerLine(hDIB);
	lpData = this->FindDIBBits(hDIB);
	//申请一块和数据区大小相同的内存
	lpTemp = (LPBYTE) new BYTE[wBytesPerLine * height];
	
	
	long lOffsetJudge;
	for (int i=1; i<height-1; i++)
		for (int j=1; j<width-1; j++)
		{	
			lOffset = this->PixelOffset(i, j, wBytesPerLine);
			//如果当前点为白色,接着循环
			if(*(lpData + lOffset) == 255)
			{
				*(lpTemp + lOffset++) = 255;
				*(lpTemp + lOffset++) = 255;
				*(lpTemp + lOffset++) = 255;
				continue;
			}
			//否则考察上下左右四个点
			else
			{	
				lOffsetJudge = this->PixelOffset(i-1, j, wBytesPerLine);
				//如果上面的点为白色
				if(*(lpData + lOffsetJudge) == 255)
				{	//设置为白色,并继续循环
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					continue;
				}

				//考察下面的点
				lOffsetJudge = this->PixelOffset(i+1,j, wBytesPerLine);
				if(*(lpData + lOffsetJudge) == 255)
				{
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					continue;
				}
				
				//考察左边的点
				lOffsetJudge = this->PixelOffset(i,j-1, wBytesPerLine);
				if(*(lpData + lOffsetJudge) == 255)
				{
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					continue;
				}
				//考察右边的点
				lOffsetJudge = this->PixelOffset(i,j+1, wBytesPerLine);
				if(*(lpData + lOffsetJudge) == 255)
				{
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					*(lpTemp + lOffset++) = 255;
					continue;
				}
				//如果上下左右都是黑色点,则把暂时区域的点设置为黑色
				lOffset = this->PixelOffset(i,j,wBytesPerLine);
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;

			}
				
		}
		//处理图象四周的点,设置为黑色
		for(i=0; i<height; i++)
		{
			lOffset = this->PixelOffset(i, 0, wBytesPerLine);
			{
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
			}
		}

		for(i=0; i<height; i++)
		{
			lOffset = this->PixelOffset(i, width-1, wBytesPerLine);
			{
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
			}
		}

		for(i=0; i<width; i++)
		{
			lOffset = this->PixelOffset(0, i, wBytesPerLine);
			{
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
			}
		}

		for(i=0; i<width; i++)
		{
			lOffset = this->PixelOffset(height-1, i, wBytesPerLine);
			{
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
				*(lpTemp + lOffset++) = 0;
			}
		}
		//把暂时区域的点拷贝到原句柄区域下面
		memcpy(lpData, lpTemp, wBytesPerLine*height);
		delete [] lpTemp;
		GlobalUnlock(hDIB);

}

void DIB::DeleteFasleEye(HANDLE hDIB, CRect facelocation)
{
	LPBYTE lpData;
	LPBITMAPINFOHEADER lpbi;
	int height;
	int width;
	long lOffset;
	WORD wBytesPerLine;

	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
	height = lpbi->biHeight;
	width = lpbi->biWidth;
	lpData = this->FindDIBBits(hDIB);
	wBytesPerLine = this->BytePerLine(hDIB);
	for (int i=0; i<height; i++)
		for (int j=0; j<width; j++)
		{
			lOffset = this->PixelOffset(i, j, wBytesPerLine);
			if(*(lpData + lOffset) == 255)
			{
				if(i<(facelocation.bottom+facelocation.top)/2)
				{
					*(lpData + lOffset++) = 0;
					*(lpData + lOffset++) = 0;
					*(lpData + lOffset++) = 0;
				}
			}
		}
		GlobalUnlock(hDIB);
}

void DIB::DeleteScatePoint(HANDLE hDIB)
{	
	LPBITMAPINFOHEADER lpbi;
	int height;
	int width;
	LPBYTE lpData;
	WORD wBytesPerLine;
	long lOffset;
	
	//得到图象的基本信息
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
	height = lpbi->biHeight;
	width  = lpbi->biWidth;
	wBytesPerLine = this->BytePerLine(hDIB);
	lpData = this->FindDIBBits(hDIB);
	
	for (int i=0; i<height; i++)
		for(int j=0; j<width; j++)
		{	
			//得到偏移
			lOffset = this->PixelOffset(i, j, wBytesPerLine);
			//如果当前点为白色点
			if(*(lpData + lOffset) == 255)
			{	
				//设定判断数组
				for(int ii = 0;ii<ImgRange;ii++)
					for (int jj=0; jj<ImgRange; jj++)
						this->lab[ii][jj] = false;
					//设定判断长度
					this->lenth=0;
					//判断是否为离散点
				bool judge = this->IsScaterPoint(j, i, width,height,lpData,wBytesPerLine,3,this->lab);
				if(!judge)
				{	
					//是离散点则把该点设置为黑色
					*(lpData + lOffset++) = 0;
					*(lpData + lOffset++) = 0;
					*(lpData + lOffset++) = 0;
				}
			}
		}
	GlobalUnlock(hDIB);
}

void  DIB::  MouseMap(LPBYTE lpRgb, const LPBYTE lpYcc,  WORD wBytesPerLine, CRect faceLocation)
{	
	//下面的循环在人脸的区域内实现嘴巴的匹配
	for (int i=faceLocation.top; i<faceLocation.bottom; i++)
		for (int j=faceLocation.left; j<faceLocation.right; j++)
		{	
			//得到偏移
			long lOffset = this->PixelOffset(i, j, wBytesPerLine);
			//得到cr,cb的数值
			int cr = *(lpYcc+lOffset+1);
			int cb = *(lpYcc+lOffset+2);
			//标志
			bool lab;
			int mapm;
			//根据cr的数值设定标志
			cr = cr-143;
			if(cr <-5 || cr>5)
			{
				cr = 0;
				
			}
		
			cr *=cr;
			
			if(cr>16)
				 lab = true;
			else
				lab = false;
			//根据cb的时值设定标志
			cb= cb-120;
			if(cb<-5 || cb >5)
				
			{
				cb = 0;
				if(lab = true)
					lab = false;
			}
			//如果cr,cb两项数值都在设定的范围之内,则设定颜色位白色,否则黑色
			if(lab)
				mapm = 255;
			else
				mapm = 0;
			 
			*(lpRgb + lOffset++) = mapm;
			*(lpRgb + lOffset++) = mapm;
			*(lpRgb + lOffset++) = mapm;

			
		}
}

void DIB::MouthCenter(HANDLE hDIB, CRect faceLocation, CPoint &mouthLocation)
{
	LPBITMAPINFOHEADER lpbi;
	int height;
	int width;
	long lOffset;
	WORD wBytesPerLine;
	LPBYTE lpData;
	
	//得到图象的基本信息
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
	height = lpbi->biHeight;
	width  = lpbi->biWidth;
	wBytesPerLine = this->BytePerLine(hDIB);
	lpData = this->FindDIBBits(hDIB);
	
	//下面的三个变量用来累计嘴巴区域的象素的x,y和象素点数
	int xnum = 0 ;
	int ynum = 0 ;
	int count = 0;
	for (int i=faceLocation.top; i<faceLocation.bottom; i++)
		for (int j=faceLocation.left; j<faceLocation.right; j++)
		{
			lOffset = this->PixelOffset(i, j, wBytesPerLine);
			//白色点
			if(*(lpData + lOffset) == 255)
			{	
				//x值加
				xnum +=j;
				//y值加
				ynum +=i;
				//点数加
				count++;
			}
		}
		//得到中心点位置
	mouthLocation.x = xnum/count;
	mouthLocation.y = ynum/count;
	
	//把中心点设置位绿色
	lOffset = this->PixelOffset(mouthLocation.y, mouthLocation.x, wBytesPerLine);
	*(lpData + lOffset++) =0;
	*(lpData + lOffset++) =255;
	*(lpData + lOffset++) =0;

	GlobalUnlock(hDIB);
}

void DIB::EyeCenter(HANDLE hDIB, CRect faceLocation, CPoint &eye1, CPoint &eye2)
{
	LPBITMAPINFOHEADER lpbi;
	LPBYTE lpData;
	long lOffset;
	WORD wBytesPerLine;
	int height;
	int width;
	int pixelnum =0;
	int num =0;
	//得到图象基本信息
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
	height = lpbi->biHeight;
	width  = lpbi->biWidth;
	lpData = this->FindDIBBits(hDIB);
	wBytesPerLine  = this->BytePerLine(hDIB);
	//考察人脸区域
	for(int i=faceLocation.top; i<faceLocation.bottom; i++)
		for (int j=faceLocation.left; j<faceLocation.right; j++)
		{
			lOffset = this->PixelOffset(i, j, wBytesPerLine);
			//白色点
			if(*(lpData + lOffset) == 255)
				//递归统计象素并修改象素值
				this->RecursiveCal(lpData,i,j,wBytesPerLine,pixelnum,++num);
		}
		//初始化眼睛的坐标
		eye1.x =0;
		eye1.y =0;
		eye2.x =0;
		eye2.y =0;
		//初始化象素点个数
		int eye1count=0;
		int eye2count =0;
		for (i=faceLocation.top; i<faceLocation.bottom; i++)
			for (int j=faceLocation.left; j<faceLocation.right; j++)
			{
				lOffset = this->PixelOffset(i, j, wBytesPerLine);
				//如果象素点的数值为1
				if(*(lpData + lOffset) == 1)
				{	
					//眼睛1的横坐标和纵坐标加上当前点的坐标值
					eye1.x +=j;
					eye1.y +=i;
					eye1count++;
					//把当前点改成白色
					*(lpData + lOffset++) = 255;
					*(lpData + lOffset++) = 255;
					*(lpData + lOffset++) = 255;

				}
				//如果当前象素的数值为2
				else if(*(lpData + lOffset) == 2)
				{	
					//眼睛2的横坐标和纵坐标加上当前点的坐标值
					eye2.x +=j;
					eye2.y +=i;
					//象素点个数加一
					eye2count++;
					//把当前点设置为白色
					*(lpData + lOffset++) = 255;
					*(lpData + lOffset++) = 255;
					*(lpData + lOffset++) = 255;
				}
			}
			//计算眼睛的中心点坐标
			eye1.x /=eye1count;
			eye1.y /=eye1count;
			eye2.x /=eye2count;
			eye2.y /=eye2count;
			//把中心点设置为绿色
			lOffset = this->PixelOffset(eye1.y, eye1.x ,wBytesPerLine);
			*(lpData + lOffset++) = 0;
			*(lpData + lOffset++) = 255;
			*(lpData + lOffset++) = 0;

			lOffset = this->PixelOffset(eye2.y, eye2.x ,wBytesPerLine);
			*(lpData + lOffset++) = 0;
			*(lpData + lOffset++) = 255;
			*(lpData + lOffset++) = 0;
	GlobalUnlock(hDIB);
}

void DIB::EllipseFace(HANDLE hDIB, CPoint mouth, CPoint eye1, CPoint eye2)
{
	LPBYTE lpData;
	LPBITMAPINFOHEADER lpbi;
	int width;
	int height;
	WORD wBytesPerLine;
	long lOffset;
	//得到图象的基本信息
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
	height = lpbi->biHeight;
	width  = lpbi->biWidth;
	lpData = this->FindDIBBits(hDIB);
	wBytesPerLine = this->BytePerLine(hDIB);
	
	//用dda算法画三角形
	this->DdaLine(mouth,eye1,lpData,wBytesPerLine);
	this->DdaLine(mouth,eye2,lpData,wBytesPerLine);
	this->DdaLine(eye1,eye2,lpData,wBytesPerLine);
	
	//椭圆的中心点和两个焦点坐标
	int ellipsecenter_x;
	int ellipsecenter_y;
	int ellipseFocusTop_x;
	int ellipseFocusTop_y;
	int ellipseFocusBottom_x;
	int ellipseFocusBottom_y;
	
	//根据眼睛和嘴巴的坐标计算椭圆的中心点坐标
	ellipsecenter_x = (eye1.x + eye2.x + mouth.x )/3;
	ellipsecenter_y = (eye1.y + eye2.y)/2 -abs(eye2.x - eye1.x)/2;

	//上面的焦点
	ellipseFocusTop_x = ellipsecenter_x;
	ellipseFocusBottom_x = ellipsecenter_x;

	//下面的焦点
	ellipseFocusTop_y =  ellipsecenter_y + (eye1.y +eye2.y)/2 -mouth.y;
	ellipseFocusBottom_y = ellipsecenter_y - ((eye1.y +eye2.y)/2 -mouth.y)+2;

	//长轴
	int a = (eye1.x-eye2.x)*2-2;
	
	for (int i=0; i<height; i++)
		for (int j=0; j<width; j++)
		{	
			//得到一个点到两个焦点的距离和
			int lenth = sqrt(pow(j-ellipseFocusTop_x,2)+pow(i-ellipseFocusTop_y,2))
				+sqrt(pow(j-ellipseFocusBottom_x,2)+ pow(i-ellipseFocusBottom_y,2));
			//判断距离和与长轴的关系
			if(lenth<2*a+2 && lenth >2*a-2)
			{	
				//把点设置为绿色
				lOffset = this->PixelOffset(i, j, wBytesPerLine);
				*(lpData + lOffset++) = 0;
				*(lpData + lOffset++) = 255;
				*(lpData + lOffset++) = 0;
			}
		}


	GlobalUnlock(hDIB);
}


void DIB::DdaLine(CPoint from, CPoint end, LPBYTE lpData, WORD wBytesPerLine)
{	
	//x,y的增量
	float delta_x;
	float delta_y;
	//x,y的坐标
	float x;
	float y;
	//x,y上的差值
	int dx;
	int dy;
	//总的步长
	int steps;
	int k;
	//得到x,y的差值
	dx = end.x - from.x;
	dy = end.y - from.y;
	//判断x,y上的差值大小,确定步长
	if(abs(dx) > abs(dy))
	{
		steps = abs(dx);
	}
	else
	{
		steps = abs(dy);
	}

	//得到每次增量的大小
	delta_x = (float)dx / (float)steps;
	delta_y = (float)dy / (float)steps;
	//设定x,y的起点
	x = (float)from.x;
	y = (float)from.y;

	//设定初始点的颜色为绿色
	long lOffset = this->PixelOffset(y, x, wBytesPerLine);
	*(lpData + lOffset++) = 0;
	*(lpData + lOffset++) = 255;
	*(lpData + lOffset++) = 0;

	//根据计算得到的步长,把直线上的点填充成绿色
	for (k=1;k<=steps; k++)
	{	
		//x,y分别加上各自的增量
		x+=delta_x;
		y+=delta_y;
		//设置点的颜色
		lOffset = this->PixelOffset(y, x, wBytesPerLine);
		*(lpData + lOffset++) = 0;
		*(lpData + lOffset++) = 255;
		*(lpData + lOffset++) = 0;

	}
	

}

⌨️ 快捷键说明

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