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

📄 edgecontour.cpp

📁 visual c++数字图像处理源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

	// 返回
	return TRUE;

}

/*************************************************************************
 *
 * 函数名称:
 *   Fill2DIB()
 *
 * 参数:
 *   LPSTR lpDIBBits    - 指向源DIB图像指针
 *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
 *   LONG  lHeight      - 源图像高度(象素数)
 * 返回值:
 *   BOOL               - 种子填充成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 * 该函数用于对图像进行种子填充运算。
 * 
 * 要求目标图像为只有0和255两个灰度值的灰度图像。
 ************************************************************************/

BOOL WINAPI Fill2DIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
	
	// 指向源图像的指针
	LPSTR	lpSrc;

	//循环变量
	long i;

	//像素值
	unsigned char pixel;

	//左右边界像素位置
	int xl,xr;

	//是否已填充至边界
	BOOL bFilll,bFillr;

	//种子堆栈及指针
	Seed Seeds[10];
	int StackPoint;

	//当前像素位置
	int iCurrentPixelx,iCurrentPixely;
	int iBufferPixelx,iBufferPixely;

	//初始化种子
	Seeds[1].Height = lHeight / 2;
	Seeds[1].Width = lWidth / 2;
	StackPoint = 1;

	while( StackPoint != 0)
	{
		//取出种子
		iCurrentPixelx = Seeds[StackPoint].Width;
		iCurrentPixely = Seeds[StackPoint].Height;
		StackPoint--;
//		if(Seed2.Height== 75)
//		{
//			return true;
//			i++;
//		}
		bFilll = true;
		bFillr = true;
		//填充种子所在的行
		//保存种子像素的位置
		iBufferPixelx = iCurrentPixelx;
		iBufferPixely = iCurrentPixely;
		//先向左填充
		while(bFilll)
		{
			lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;

			//目标图像中含有0和255外的其它灰度值
			if(pixel != 255 && pixel != 0)
				return FALSE;
			//遇到边界
			if(pixel == 0)
			{
				bFilll = false;
				xl=iCurrentPixelx+1;
			}
			else
			{
				*lpSrc = (unsigned char)0;
				iCurrentPixelx--;
				//防止越界
				if(iCurrentPixelx<0)
				{	
					bFilll = false;
					iCurrentPixelx = 0;
					xl = 0; 
				}
			}		
		}
		//再向右填充
		//取回种子像素的位置
		iCurrentPixelx = iBufferPixelx+1;
		if(iCurrentPixelx>lWidth)
		{	
			bFillr = false;
			iCurrentPixelx = lWidth;
			xr = lWidth; 
		}
		iCurrentPixely = iBufferPixely;
		while(bFillr)
		{
			lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;

			//目标图像中含有0和255外的其它灰度值
			if(pixel != 255 && pixel != 0)
				return FALSE;
			//遇到边界
			if(pixel == 0)
			{
				bFillr = false;
				xr=iCurrentPixelx-1;
			}
			else
			{
				*lpSrc = (unsigned char)0;
				iCurrentPixelx++;
				//防止越界
				if(iCurrentPixelx>lWidth)
				{	
					bFillr = false;
					iCurrentPixelx = lWidth;
					xr = lWidth; 
				}
			}		
		}
		//上、下两条扫描线是否全为边界象素或已填充过
		//先看上面的扫描线
		iCurrentPixely--;
		if(iCurrentPixely < 0)
		{
			iCurrentPixely = 0;
		}
		for (i = xr; i>= xl;i--)
		{
			lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;

			//有未填充的像素,将新的种子压入堆栈
			if (pixel == 255)
			{
				StackPoint++;
				Seeds[StackPoint].Height = iCurrentPixely;
				Seeds[StackPoint].Width = i;
				break;
			}				
		}
		//再看下面的扫描线
		iCurrentPixely+=2;
		if(iCurrentPixely > lHeight)
		{
			iCurrentPixely = lHeight;
		}
		for (i = xr; i>= xl;i--)
		{
			lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;

			//有未填充的像素,将新的种子压入堆栈
			if (pixel == 255)
			{
				StackPoint++;
				Seeds[StackPoint].Height = iCurrentPixely;
				Seeds[StackPoint].Width = i;
				break;
			}				
		}


	}

	// 返回
	return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   FillDIB()
 *
 * 参数:
 *   LPSTR lpDIBBits    - 指向源DIB图像指针
 *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
 *   LONG  lHeight      - 源图像高度(象素数)
 * 返回值:
 *   BOOL               - 种子填充成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 * 该函数用于对图像进行种子填充运算。
 * 
 * 要求目标图像为只有0和255两个灰度值的灰度图像。
 ************************************************************************/

BOOL WINAPI FillDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
	
	// 指向源图像的指针
	LPSTR	lpSrc;

	//像素值
	unsigned char pixel;

	//种子堆栈及指针
	Seed *Seeds;
	int StackPoint;

	//当前像素位置
	int iCurrentPixelx,iCurrentPixely;

	//初始化种子
	Seeds = new Seed[lWidth*lHeight];
	Seeds[1].Height = lHeight / 2;
	Seeds[1].Width = lWidth / 2;
	StackPoint = 1;

	while( StackPoint != 0)
	{
		//取出种子
		iCurrentPixelx = Seeds[StackPoint].Width;
		iCurrentPixely = Seeds[StackPoint].Height;
		StackPoint--;

		lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
		//取得当前指针处的像素值,注意要转换为unsigned char型
		pixel = (unsigned char)*lpSrc;

		//目标图像中含有0和255外的其它灰度值
		if(pixel != 255 && pixel != 0)
			return FALSE;

		//将当前点涂黑
		*lpSrc = (unsigned char)0;

		//判断左面的点,如果为白,则压入堆栈
		//注意防止越界
		if(iCurrentPixelx > 0)
		{
			lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx - 1;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;
			if (pixel == 255)
			{
				StackPoint++;
				Seeds[StackPoint].Height = iCurrentPixely;
				Seeds[StackPoint].Width = iCurrentPixelx - 1;
			}
			//目标图像中含有0和255外的其它灰度值
			if(pixel != 255 && pixel != 0)
				return FALSE;
		}

		//判断上面的点,如果为白,则压入堆栈
		//注意防止越界
		if(iCurrentPixely < lHeight - 1)
		{
			lpSrc = (char *)lpDIBBits + lWidth * (iCurrentPixely + 1) + iCurrentPixelx;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;
			if (pixel == 255)
			{
				StackPoint++;
				Seeds[StackPoint].Height = iCurrentPixely + 1;
				Seeds[StackPoint].Width = iCurrentPixelx;
			}
			//目标图像中含有0和255外的其它灰度值
			if(pixel != 255 && pixel != 0)
				return FALSE;
		}

		//判断右面的点,如果为白,则压入堆栈
		//注意防止越界
		if(iCurrentPixelx < lWidth - 1)
		{
			lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx + 1;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;
			if (pixel == 255)
			{
				StackPoint++;
				Seeds[StackPoint].Height = iCurrentPixely;
				Seeds[StackPoint].Width = iCurrentPixelx + 1;
			}
			//目标图像中含有0和255外的其它灰度值
			if(pixel != 255 && pixel != 0)
				return FALSE;
		}

		//判断下面的点,如果为白,则压入堆栈
		//注意防止越界
		if(iCurrentPixely > 0)
		{
			lpSrc = (char *)lpDIBBits + lWidth * (iCurrentPixely - 1) + iCurrentPixelx;
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;
			if (pixel == 255)
			{
				StackPoint++;
				Seeds[StackPoint].Height = iCurrentPixely - 1;
				Seeds[StackPoint].Width = iCurrentPixelx;
			}
			//目标图像中含有0和255外的其它灰度值
			if(pixel != 255 && pixel != 0)
				return FALSE;
		}
	}

	//释放堆栈
	delete Seeds;
	// 返回
	return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   ContourDIB()
 *
 * 参数:
 *   LPSTR lpDIBBits    - 指向源DIB图像指针
 *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
 *   LONG  lHeight      - 源图像高度(象素数)
 * 返回值:
 *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 * 该函数用于对图像进行轮廓提取运算。
 * 
 * 要求目标图像为只有0和255两个灰度值的灰度图像。
 ************************************************************************/

BOOL WINAPI ContourDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
	
	// 指向源图像的指针
	LPSTR	lpSrc;
	
	// 指向缓存图像的指针
	LPSTR	lpDst;
	
	// 指向缓存DIB图像的指针
	LPSTR	lpNewDIBBits;
	HLOCAL	hNewDIBBits;

	//循环变量
	long i;
	long j;
	unsigned char n,e,s,w,ne,se,nw,sw;

	//像素值
	unsigned char pixel;

	// 暂时分配内存,以保存新图像
	hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);

	if (hNewDIBBits == NULL)
	{
		// 分配内存失败
		return FALSE;
	}
	
	// 锁定内存
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits);

	// 初始化新分配的内存,设定初始值为255
	lpDst = (char *)lpNewDIBBits;
	memset(lpDst, (BYTE)255, lWidth * lHeight);
	for(j = 1; j <lHeight-1; j++)
	{
		for(i = 1;i <lWidth-1; i++)
		{
			
			// 指向源图像倒数第j行,第i个象素的指针			
			lpSrc = (char *)lpDIBBits + lWidth * j + i;
			
			// 指向目标图像倒数第j行,第i个象素的指针			
			lpDst = (char *)lpNewDIBBits + lWidth * j + i;
			
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;

			//目标图像中含有0和255外的其它灰度值
//			if(pixel != 255 && pixel != 0)
//				return FALSE;
			if(pixel == 0)
			{
				*lpDst = (unsigned char)0;
				nw = (unsigned char)*(lpSrc + lWidth -1);
				n  = (unsigned char)*(lpSrc + lWidth );
				ne = (unsigned char)*(lpSrc + lWidth +1);
				w = (unsigned char)*(lpSrc -1);
				e = (unsigned char)*(lpSrc +1);
				sw = (unsigned char)*(lpSrc - lWidth -1);
				s  = (unsigned char)*(lpSrc - lWidth );
				se = (unsigned char)*(lpSrc - lWidth +1);
				//如果相邻的八个点都是黑点
				if(nw+n+ne+w+e+sw+s+se==0)
				{
					*lpDst = (unsigned char)255;
				}
			}
		}
	}

	// 复制腐蚀后的图像
	memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);

	// 释放内存
	LocalUnlock(hNewDIBBits);
	LocalFree(hNewDIBBits);

	// 返回
	return TRUE;
}

/*************************************************************************
 *
 * 函数名称:
 *   TraceDIB()
 *
 * 参数:
 *   LPSTR lpDIBBits    - 指向源DIB图像指针
 *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
 *   LONG  lHeight      - 源图像高度(象素数)
 * 返回值:
 *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 * 该函数用于对图像进行轮廓跟踪运算。
 * 
 * 要求目标图像为只有0和255两个灰度值的灰度图像。
 ************************************************************************/

BOOL WINAPI TraceDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
	
	// 指向源图像的指针
	LPSTR	lpSrc;
	
	// 指向缓存图像的指针
	LPSTR	lpDst;
	
	// 指向缓存DIB图像的指针
	LPSTR	lpNewDIBBits;
	HLOCAL	hNewDIBBits;

	// 图像每行的字节数
	LONG lLineBytes;
	
	//循环变量
	long i;
	long j;

	//像素值
	unsigned char pixel;

	//是否找到起始点及回到起始点
	bool bFindStartPoint;

	//是否扫描到一个边界点
	bool bFindPoint;

	//起始边界点与当前边界点
	Point StartPoint,CurrentPoint;

	//八个方向和起始扫描方向
	int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
	int BeginDirect;

	// 计算图像每行的字节数
	lLineBytes = WIDTHBYTES(lWidth * 8);

	// 暂时分配内存,以保存新图像
	hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);

	if (hNewDIBBits == NULL)
	{
		// 分配内存失败
		return FALSE;
	}
	
	// 锁定内存
	lpNewDIBBits = (char * )LocalLock(hNewDIBBits);

	// 初始化新分配的内存,设定初始值为255
	lpDst = (char *)lpNewDIBBits;
	memset(lpDst, (BYTE)255, lLineBytes * lHeight);

	//先找到最左上方的边界点
	bFindStartPoint = false;
	for (j = 0;j < lHeight && !bFindStartPoint;j++)
	{
		for(i = 0;i < lWidth && !bFindStartPoint;i++)
		{
			// 指向源图像倒数第j行,第i个象素的指针			
			lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
			
			//取得当前指针处的像素值,注意要转换为unsigned char型
			pixel = (unsigned char)*lpSrc;
			
			if(pixel == 0)
			{
				bFindStartPoint = true;

				StartPoint.Height = j;
				StartPoint.Width = i;

				// 指向目标图像倒数第j行,第i个象素的指针			
				lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;	
				*lpDst = (unsigned char)0;
			}		
		}
	}

	//由于起始点是在左下方,故起始扫描沿左上方向
	BeginDirect = 0;
	//跟踪边界
	bFindStartPoint = false;
	//从初始点开始扫描
	CurrentPoint.Height = StartPoint.Height;
	CurrentPoint.Width = StartPoint.Width;
	while(!bFindStartPoint)
	{
		bFindPoint = false;
		while(!bFindPoint)
		{
			//沿扫描方向查看一个像素
			lpSrc = (char *)lpDIBBits + lLineBytes * ( CurrentPoint.Height + Direction[BeginDirect][1])
				+ (CurrentPoint.Width + Direction[BeginDirect][0]);
			pixel = (unsigned char)*lpSrc;
			if(pixel == 0)
			{
				bFindPoint = true;
				CurrentPoint.Height = CurrentPoint.Height + Direction[BeginDirect][1];
				CurrentPoint.Width = CurrentPoint.Width + Direction[BeginDirect][0];
				if(CurrentPoint.Height == StartPoint.Height && CurrentPoint.Width == StartPoint.Width)
				{
					bFindStartPoint = true;
				}
				lpDst = (char *)lpNewDIBBits + lLineBytes * CurrentPoint.Height + CurrentPoint.Width;
				*lpDst = (unsigned char)0;
				//扫描的方向逆时针旋转两格
				BeginDirect--;
				if(BeginDirect == -1)
					BeginDirect = 7;
				BeginDirect--;
				if(BeginDirect == -1)
					BeginDirect = 7;
			}
			else
			{
				//扫描方向顺时针旋转一格
				BeginDirect++;
				if(BeginDirect == 8)
					BeginDirect = 0;

			}

		}
	}

	// 复制腐蚀后的图像
	memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);

	// 释放内存
	LocalUnlock(hNewDIBBits);
	LocalFree(hNewDIBBits);

	// 返回
	return TRUE;
}


⌨️ 快捷键说明

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