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

📄 zxdib.cpp

📁 利用web camera对目标进行特征跟踪的程序 对于初学机器视觉的有些帮助
💻 CPP
📖 第 1 页 / 共 5 页
字号:
						pBitmap[position_l] = 0;
					position_l ++;
				}
			}
			//修改当前大区域为已有的区域编号:
			else if(!modify)
				{
					color_area++;  //总区域数加一
					colorarray[color_area] = 1; //相应的区域标志设为1
					position_l=0;  //修改大区域像素灰度为它的区域编号
					for(m=0; m<dwHeight; m++)
					for(n=0; n<dwWidth; n++)
					{
						if(pBitmap[position_l] == 250)
							pBitmap[position_l] = (BYTE) color_area;
						position_l ++;
					}
				}
		}
		position++;
	}

	return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//种子填充算法:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::SeedGrow(DWORD i,DWORD j,BYTE *pBitmap, DWORD& dwHeight, DWORD& dwWidth, DWORD& Number,BYTE& flag,BYTE& egg,WORD& Delete,BYTE* colorarray)
{  
	//边界条件
	if(i>=dwHeight) return true;
	if(i<0) return true;
	if(j<0) return true;
	if(j>=dwWidth)  return true;
	
	DWORD position = i*dwWidth+j;
	
	if(Delete)   //??改变量的设置是为了一旦检测出本区域过小时就予以删除时,共享此该代码??may not be so
	{
		if(colorarray[pBitmap[position]])  //如果该点为已经扫描过的点,则加上标志,用于两个区域的合并:
			colorarray[pBitmap[position]] = 2;
	}
	if(pBitmap[position] != flag)  //如果不是目标
		return true;
	if(Number>6000) return true; //设置递归最大层数
	pBitmap[position] = egg;     //修改为中间色
	Number++;                    //该区域像素个数加一
   
	//下面使用了四邻域种子填充算法:
	SeedGrow(i+1, j,   pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
//	SeedGrow(i+1, j+1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
	SeedGrow(i  , j+1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
//	SeedGrow(i-1, j+1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
	SeedGrow(i-1, j  , pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
//	SeedGrow(i-1, j-1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
	SeedGrow(i  , j-1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
//	SeedGrow(i+1, j-1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);

	return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  用小矩形去腐蚀输入图像
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::Uncover2ValueImageByRect(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth,DWORD dwRectHeight,DWORD dwRectWidth)
{
 	DWORD i,j,k,l;
	DWORD temp;
	BYTE* pResult=NULL;
	DWORD upgate = (DWORD)(dwRectHeight*dwRectWidth*0.80);
	DWORD downgate = (DWORD)(dwRectHeight*dwRectWidth*0.30);
	pResult = (BYTE*) new BYTE[dwHeight*dwWidth];
	
	for(j=0; j<dwHeight-dwRectHeight; j++)
	for(i=0; i<dwWidth-dwRectWidth; i++)
	{
		temp = 0;
		for(k=0; k<dwRectHeight; k++)
		for(l=0; l<dwRectWidth; l++)
		{
			if(!pBitmap[(j+k)*dwWidth+l+i])
			temp ++;
		}
		if(temp>upgate)   //大于给定上门限时
			for(k=0; k<dwRectHeight; k++)
			for(l=0; l<dwRectWidth; l++)
				pResult[(j+k)*dwWidth+l+i]=0;
		else if(temp<downgate) //小于给定下门限时
			for(k=0; k<dwRectHeight; k++)
			for(l=0; l<dwRectWidth; l++)
				pResult[(j+k)*dwWidth+l+i]=255; 
		else //二值化的需要
			for(k=0; k<dwRectHeight; k++)
			for(l=0; l<dwRectWidth; l++)
				pResult[(j+k)*dwWidth+l+i]= pResult[(j+k)*dwWidth+l+i]?255:0;
	}

	for(i=0;i<dwHeight; i++)
	for(j=0;j<dwWidth; j++)
		pBitmap[i*dwWidth+j] = pResult[i*dwWidth+j];

	delete pResult;
	return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  通过彩色进行目标的粗定位
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CoarsePositionByColorSegment(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, RECT &rect)
{
	// TODO: Add your command handler code here
	BYTE * pResult=NULL;
	BYTE* pTemp=NULL;
	DWORD position,i,j;
	DWORD dwRectWidth,dwRectHeight;

	if(!ColorBasedSegment(pBitmap,dwHeight,dwWidth,pResult))
		{   delete pResult;	return false;}
	if(!GetRidOfSmallBlock(pResult,dwHeight,dwWidth,255,600))
		{	delete pResult;	return false;}
	if(!ProjectAndFindTargetRegion(pResult,dwHeight,dwWidth,rect))
		{	delete pResult;	return false;}

	if(rect.right - rect.left == dwWidth-1 || rect.bottom - rect.top == dwHeight-1)
		{	delete pResult;	return false;}
	
	dwRectWidth = rect.right-rect.left;
	dwRectHeight = rect.bottom-rect.top;
	pTemp =(BYTE*) new BYTE[dwRectWidth*dwRectHeight];
	
	position=0;
	for(i=rect.top;i<rect.bottom;i++)
	for(j=rect.left;j<rect.right;j++)
	{
		pTemp[position] = pResult[i*dwWidth+j];
		position++;
	}
	RECT rect1;
	if(dwRectHeight>80)
	{
		ProjectAndFindTargetRegion(pTemp,80,dwRectWidth,rect1);
		rect.left = rect1.left + rect.left;
		rect.right = rect.left + rect1.right-rect1.left;
	//	rect.bottom = rect1.bottom + rect.top;
	}

	delete pTemp;
	delete pResult;
	
	if(rect.right-rect.left <20 || rect.bottom - rect.top< 20) 
		return false;
	
	return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// pBitmap为灰度图象,flag为目标的灰度值
// 主要思想为:设置了一个迭代深度,将超过深度个像素点的的区域标志为一个小的数字,然后在以后的搜索终若遇
// 到某个区域和该区域相邻,则将两个区域合并之。考虑像“手”一样的情况,有可能和多个已知的区域合并。
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::SelectBiggestBlock(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth,BYTE flag,DWORD dwMinBlockSize)
{
	DWORD temp = 0;
	BYTE colorarray[1000];  //用于合并的标志数组,从第1个(非第0个)开始有效
	WORD color_area = 0;    //标志已经有个多少个大区域
	DWORD i,j,k,temp_color,m,n;
	DWORD Number;
	WORD  Delete;
	BYTE egg;               //中间颜色值
	bool modify;            //修改标志
	
	for(i=0;i<260; i++)
		colorarray[i] = 0;
	
	DWORD position=0;
	DWORD position_l;
	for( i=0;i<dwHeight; i++)
	for(j=0; j<dwWidth; j++)
	{
		if(pBitmap[position]==flag) //对每一个点都要检查是否是目标点
		{
			Number=0;    //设置个数为0
			egg = 250;   //设置中间颜色为250
			Delete = color_area+1; //
			//使用种子填充法找到改点的所属的整个区域:标志为egg
			SeedGrow(i,j,pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
			modify = false;
			k=1;
			temp_color=0;
			//首先将刚刚找到的新区域修改为最开始找到的那个大区域编号
			for(k=1; (k<=color_area) && (!modify); k++) //一旦有改变就算完成任务:
			{  
				if( colorarray[k]==2 )
				{
					modify = true;
					temp_color = k;
					colorarray[k]=1;
					position_l=0;
					//扫描整个图像将标志为egg的改为k
					for(m=0; m<dwHeight; m++)
					for(n=0; n<dwWidth; n++)
					{
						if(pBitmap[position_l] == egg)
							pBitmap[position_l] = (BYTE) k;
						position_l++;
					}
				}
			}
			//寻找看看是否还和其它的大区域相邻:
			while((k<=color_area) && (colorarray[k]!=2))
				k++;
			//处理多区域杂交的情况
			if (k<=color_area)  
			{
				position_l=0;
				//扫描整个图像进行如下处理:
				for(m=0; m<dwHeight; m++)
				for(n=0; n<dwWidth; n++)
				{   
					k = temp_color;
					while ((k<=color_area)&&(pBitmap[position_l]))
					{
						if(colorarray[k] == 2)
						{
							if(pBitmap[position_l] == k)
								pBitmap[position_l] = (BYTE) temp_color;
						}
						k++;
					}
					position_l++;
				}
				k=temp_color; //将已经合并了的区域改掉,为0
				while (k<=color_area)
				{
					if( colorarray[k] ==2 ) 
						colorarray[k] = 0;
					k++;
				}
			}
			//如果不牵涉到合并,那么可以确定该区域是一个封闭的完整区域,
			//根据其面积大小是否大于给定的门限来确定是否删除之
			if((!modify)&&(Number<dwMinBlockSize))
			{ //若该区域大小小于给定的阈值,则将其删掉:
				DWORD position_l = 0;
				for(DWORD m=0; m<dwHeight; m++)
				for(DWORD n=0; n<dwWidth; n++)
				{
					if(pBitmap[position_l] == 250)
						pBitmap[position_l] = 0;
					position_l ++;
				}
			}
			//修改当前大区域为已有的区域编号:
			else if(!modify)
				{
					color_area++;  //总区域数加一
					colorarray[color_area] = 1; //相应的区域标志设为1
					position_l=0;  //修改大区域像素灰度为它的区域编号
					for(m=0; m<dwHeight; m++)
					for(n=0; n<dwWidth; n++)
					{
						if(pBitmap[position_l] == 250)
							pBitmap[position_l] = (BYTE) color_area;
						position_l ++;
					}
				}
		}
		position++;
	}


	return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//在图像中截取一片区域(8位或24位)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CutRegionFromPicture(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult, DWORD x_from, DWORD y_from, DWORD x_to, DWORD y_to, WORD flag)
{
	DWORD i,j;
	if(x_from<0 || x_to >=dwWidth || y_from<0 || y_to >=dwHeight || x_from>x_to || y_from>y_to)
		return false;
	
	if(pResult) delete pResult;
	pResult = (BYTE*) new BYTE[(x_to-x_from)*(y_to-y_from)*flag/8];

	DWORD position=0;
	if(flag==8)
	{
		for(i=y_from; i<y_to; i++)
		for(j=x_from; j<x_to; j++)
		{
			pResult[position] = pBitmap[i*dwWidth+j];
			position++;
		}
	}
	else
	if(flag==24)
	{
		for(i=y_from; i<y_to; i++)
		for(j=x_from; j<x_to; j++)
		{
			pResult[position] = pBitmap[(i*dwWidth+j)*3];
			position++;
			pResult[position] = pBitmap[(i*dwWidth+j)*3+1];
			position++;
			pResult[position] = pBitmap[(i*dwWidth+j)*3+2];
			position++;
		}
	}
	return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//在图像中截取一片区域(8位或24位)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CutRegionFromPicture(double *pBitmap, DWORD dwHeight, DWORD dwWidth, double *&pResult, DWORD x_from, DWORD y_from, DWORD x_to, DWORD y_to, WORD flag)
{
	DWORD i,j;
	if(x_from<0 || x_to >=dwWidth || y_from<0 || y_to >=dwHeight || x_from>x_to || y_from>y_to)
		return false;
	
	if(pResult) delete pResult;
	pResult = (double*) new double[(x_to-x_from)*(y_to-y_from)*flag/8];

	DWORD position=0;
	if(flag==8)
	{
		for(i=y_from; i<y_to; i++)
		for(j=x_from; j<x_to; j++)
		{
			pResult[position] = pBitmap[i*dwWidth+j];
			position++;
		}
	}
	else
	if(flag==24)
	{
		for(i=y_from; i<y_to; i++)
		for(j=x_from; j<x_to; j++)
		{
			pResult[position] = pBitmap[(i*dwWidth+j)*3];
			position++;
			pResult[position] = pBitmap[(i*dwWidth+j)*3+1];
			position++;
			pResult[position] = pBitmap[(i*dwWidth+j)*3+2];
			position++;
		}
	}
	return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  将24位彩色图转换为灰度图:
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::Translate24To8Color(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult)
{
	DWORD i,j;
	DWORD temp;
	if(pResult) delete pResult;
	pResult = new BYTE[dwHeight*dwWidth];

	for(i=0;i<dwHeight;i++)
	for(j=0;j<dwWidth; j++)
	{
		temp = pBitmap[(i*dwWidth+j)*3]+pBitmap[(i*dwWidth+j)*3+1]+pBitmap[(i*dwWidth+j)*3+2];
		temp /= 3;
		pResult[i*dwWidth+j] = (BYTE) temp;
	}
	return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 利用两种方法一起来进行粗定位:
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CoarsePositionByColorAndVariance(BYTE **pBKImage, DWORD dwHeight, DWORD dwWidth, int nBKnumber,BYTE *pBitmap, WORD flag, RECT &rect)
{
    //计算通过均值和方差计算出来的rect
	if(!CoarsePositionByMeanAndVariance(pBKImage,dwHeight,dwWidth,nBKnumber,pBitmap,rect,flag))
		return false;

	//将rect内的内容抠出来:
	BYTE * pResult=NULL;
	CutRegionFromPicture(pBitmap,dwHeight,dwWidth,pResult,rect.left,rect.top,rect.right,rect.bottom,flag);

	//计算在扣出的图像中目标的rect1:
	RECT rect1;
	if(!CoarsePositionByColorSegment(pResult,rect.bottom-rect.top,rect.right-rect.left,rect1))
		return false;

	//修改原来的rect得到结果:
	rect.left += rect1.left;
	rect.right = rect.left + rect1.right - rect1.left;
	rect.top += rect1.top;
	rect.bottom = rect.top + rect1.bottom - rect1.top;

	rect.bottom += (rect.bottom - rect.top)/4;
	if(rect.bottom> dwHeight) rect.bottom = dwHeight;

	delete pResult;
	return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// 得到色调空间:
//
/////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::GetHSIFromRGB(BYTE *pColorBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult)
{
	if(pResult) delete pResult;
	pResult = new BYTE[dwHeight*dwWidth*3];

	double r,g,b;
	double x;
	DWORD i,j;
	double S,H,I;

	DWORD position=0;
	for(i=0; i<dwHeight; i++)
	for(j=0; j<dwWidth; j++)
	{ 
		b = (double)(pColorBitmap[position])/255.0;
		g = (double)(pColorBitmap[position+1])/255.0;
		r = (double)(pColorBitmap[position+2])/255.0;
		
		I = (r+g+b)/3;
		x = r;
		if( x>g ) x = g;
		if( x>b ) x = b;
		if(I<0.000001)
			S = 0;
		else
			S = 1-x/I;
		if(S<0.000001)
			H = 0;
		else
		{
			x = (r-g+r-b)/(2*sqrt((r-g)*(r-g)+(r-b)*(g-b)));
			if(x>=1.0) 
				H = 0;
			else 
			  H = (acos(x)/3.1415926)*180; 
		}
		if(g<b) H=360-H;

		H = H*255;
		H /= 360;
		pResult[position] = (BYTE) H;
		pResult[position+1] = S*255;
		pResult[position+2] = I*255;

		position += 3;
	}

	return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//利用HSI空间中的S分量进行分割
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::VarianceByRGB2thColor(BYTE *pColorBitmap, DWORD dwHeight, DWORD dwWidth,BYTE* pBKImage, BYTE *&pResultImage)
{
   	DWORD i,j;
	int counter;

	if(pResultImage) delete pResultImage;
	pResultImage = new BYTE [dwHeight*dwWidth];

	for(i=0;i<dwHeight; i++)

⌨️ 快捷键说明

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