【图像处理】基本图像处理算法原理与实现五:形态学

                                        形态学运算

1、腐蚀与膨胀

腐蚀与膨胀是针对二值化图像而言的。

腐蚀:使用(2k+1)*(2k+1)的模板S对图像A进行腐蚀,当S移动至A中某点z时,如果S能完全包含在A中(设S为所有值都是255的模板,而A的(2k+1)*(2k+1)邻域以及z点值也都是255,那么就说S能完全包含在A中),那么由这样的点z构成的图像即为S对A的腐蚀图像。

膨胀:使用(2k+1)*(2k+1)的模板S'对图像A进行膨胀,当S'移动至A中某点z时,如果S'与A的(2k+1)*(2k+1)邻域以及z点值有重叠,那么由这样的点z构成的图像即为S'对A的膨胀图像。

实现代码:

/*****************************************************************************
函数名		:	ImgErodeDilate
功能		:	腐蚀膨胀
算法实现	:	<可选项>
参数说明	:	tSrcImg 原图像[in]
				ptDstImg 目标图像[out]
				u8TempH 窗体区域高[in]
				u8TempW 窗体区域宽[in]
				u8OpMode 运算模式[in]
返回值说明	:	无
其他说明	:	无
******************************************************************************/
void ImgErodeDilate(MyImage tSrcImg, MyImage *ptDstImg, u8 u8AreaH, u8 u8AreaW, u8 u8OpMode)
{
	/*原图像高、宽、通道数*/
	l32 l32SrcImgHeight = tSrcImg.l32ImgH;
	l32 l32SrcImgWidth = tSrcImg.l32ImgW;

	/*目标图像高、宽(等于原图像)*/
	l32 l32DstImgHeight = l32SrcImgHeight;
	l32 l32DstImgWidth = l32SrcImgWidth;

	MyImageInit(ptDstImg, l32DstImgHeight, l32DstImgWidth, 1);
	for (l32 l32DstImgHeightIdx = 0; l32DstImgHeightIdx < l32DstImgHeight; l32DstImgHeightIdx++)
	{
		for (l32 l32DstImgWidthIdx = 0; l32DstImgWidthIdx < l32DstImgWidth; l32DstImgWidthIdx++)
		{
			u8 u8IsErode = 1;
			u8 u8IsDilate = 0;
			l32 l32DstImgPixelPos = l32DstImgHeightIdx * l32DstImgWidth + l32DstImgWidthIdx; //目标图像像素在内存中的位置
			for (u8 u8MatHeightIdx = 0; u8MatHeightIdx < u8AreaH; u8MatHeightIdx++)
			{
				for (u8 u8MatWidthIdx = 0; u8MatWidthIdx < u8AreaW; u8MatWidthIdx++)
				{
					l32 l32SrcImgHeightIdx = l32DstImgHeightIdx + u8MatHeightIdx - u8(u8AreaH / 2);
					l32 l32SrcImgWidthIdx = l32DstImgWidthIdx + u8MatWidthIdx - u8(u8AreaW / 2);
					l32 l32SrcImgPixelPos = l32SrcImgHeightIdx * l32SrcImgWidth + l32SrcImgWidthIdx; //原图像像素在内存中的位置
					
					if (l32SrcImgHeightIdx >= 0 && l32SrcImgHeightIdx < l32SrcImgHeight && l32SrcImgWidthIdx >= 0 && l32SrcImgWidthIdx < l32SrcImgWidth)
					{
						switch (u8OpMode)
						{
							case MORP_ERODE:
								if (tSrcImg.pu8Data[l32SrcImgPixelPos] != 255)
									u8IsErode = 0;
								break;
							case MORP_DILATE:
								if (tSrcImg.pu8Data[l32SrcImgPixelPos] == 255)
									u8IsDilate = 1;
								break;
							default:break;
						}
					}
				}
			}

			switch (u8OpMode)
			{
				case MORP_ERODE:
					if (u8IsErode)
						ptDstImg->pu8Data[l32DstImgPixelPos] = 255;
					break;
				case MORP_DILATE:
					if (u8IsDilate)
						ptDstImg->pu8Data[l32DstImgPixelPos] = 255;
					break;
				default:break;
			}
		}
	}
}

2、开运算与闭运算

开运算是先腐蚀再膨胀,而闭运算是先膨胀再腐蚀。

实现代码:

/*****************************************************************************
函数名		:	ImgOpenClose
功能		:	开闭运算
算法实现	:	<可选项>
参数说明	:	tSrcImg 原图像[in]
				ptDstImg 目标图像[out]
				u8TempH 窗体区域高[in]
				u8TempW 窗体区域宽[in]
				u8OpMode 运算模式[in]
返回值说明	:	无
其他说明	:	无
******************************************************************************/
void ImgOpenClose(MyImage tSrcImg, MyImage *ptDstImg, u8 u8AreaH, u8 u8AreaW, u8 u8OpMode)
{
	MyImage tImgErode, tImgDilate;
	switch (u8OpMode)
	{
		case MORP_OPEN:
			ImgErodeDilate(tSrcImg, &tImgErode, u8AreaH, u8AreaW, MORP_ERODE);
			ImgErodeDilate(tImgErode, ptDstImg, u8AreaH, u8AreaW, MORP_DILATE);
			break;
		case MORP_CLOSE:
			ImgErodeDilate(tSrcImg, &tImgDilate, u8AreaH, u8AreaW, MORP_DILATE);
			ImgErodeDilate(tImgDilate, ptDstImg, u8AreaH, u8AreaW, MORP_ERODE);
		default:break;
	}
}

3、细化

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值