【图像处理】基本图像处理算法原理与实现三:灰度化与二值化

                                        灰度化与二值化

1、灰度化

对于单通道灰度图像,其某个位置处的像素点灰度值可由同位置处的三通道RGB值计算得到,公式如下:

实现代码:

/*****************************************************************************
函数名		:	ImgRGBToGray
功能		:	RGB彩色转灰度图像
算法实现	:	<可选项>
参数说明	:	tSrcImg 原图像[in]
				ptDstImg 目标图像[out]
返回值说明	:	无
其他说明	:	无
******************************************************************************/
void ImgRGBToGray(MyImage tSrcImg, MyImage *ptDstImg)
{
	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++)
		{
			l32 l32DstImgPixelPos = l32DstImgHeightIdx * l32DstImgWidth + l32DstImgWidthIdx;
			l32 l32SrcImgPixelBPos = l32DstImgHeightIdx * l32DstImgWidth * 3 + \
				l32DstImgWidthIdx * 3 + 0;
			l32 l32SrcImgPixelGPos = l32DstImgHeightIdx * l32DstImgWidth * 3 + \
				l32DstImgWidthIdx * 3 + 1;
			l32 l32SrcImgPixelRPos = l32DstImgHeightIdx * l32DstImgWidth * 3 + \
				l32DstImgWidthIdx * 3 + 2;
			ptDstImg->pu8Data[l32DstImgPixelPos] = tSrcImg.pu8Data[l32SrcImgPixelBPos] * 0.114 + tSrcImg.pu8Data[l32SrcImgPixelGPos] * 0.587 \
				+ tSrcImg.pu8Data[l32SrcImgPixelRPos] * 0.229;
		}
	}
}

二、二值化

在灰度图像中,对于一确定的阈值T有:

实现代码:

/*****************************************************************************
函数名		:	ImgGrayToBina
功能		:	灰度图像二值化
算法实现	:	<可选项>
参数说明	:	tSrcImg 原图像[in]
				ptDstImg 目标图像[out]
				u8Thresh 阈值
返回值说明	:	无
其他说明	:	无
******************************************************************************/
void ImgGrayToBina(MyImage tSrcImg, MyImage *ptDstImg, u8 u8Thresh)
{
	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++)
		{
			l32 l32DstImgPixelPos = l32DstImgHeightIdx * l32DstImgWidth + l32DstImgWidthIdx; //目标图像像素在内存中的位置
			l32 l32SrcImgPixelPos = l32DstImgPixelPos;
			if (tSrcImg.pu8Data[l32SrcImgPixelPos] > u8Thresh)
			{
				ptDstImg->pu8Data[l32DstImgPixelPos] = 255;
			}
			else
			{
				ptDstImg->pu8Data[l32DstImgPixelPos] = 0;
			}
		}
	}
}

三、OSTU最佳阈值(大津法)

对于一幅灰度图像,假设阈值t将其划分为前景和背景两部分A和B。设A为前景,B为背景,前景像素数占总像素数的比例PA,背景像素数占总像素数比例PB,前景与背景的平均灰度值分别为MA和MB,总平均灰度值为M。那么Nobuyuki Otsu 给出的类间方差定义为:

而最佳阈值t即为使得方差ICV最大的阈值T。

程序设计思路:

遍历原灰度图像中的每个像素点,计算平均灰度值M与灰度直方图H,H用256个元素的数组表示,其中H[i]表示灰度值为i的像素点个数。然后,遍历每个灰度值0~255,分别计算PA、MA、PB、MB并计算ICV,找出使得ICV最大的阈值T。

 实现代码:

/*****************************************************************************
函数名		:	ImgGetThreshOstu
功能		:	OSTU阈值计算
算法实现	:	<可选项>
参数说明	:	tSrcImg 原图像[in]
返回值说明	:	u8BestThresh 自适应阈值[out]
其他说明	:	无
******************************************************************************/
u8 ImgGetThreshOstu(MyImage tSrcImg)
{
	l32 l32SrcImgHeight = tSrcImg.l32ImgH;
	l32 l32SrcImgWidth = tSrcImg.l32ImgW;

	l32 l32TotalPixelNums = l32SrcImgHeight * l32SrcImgWidth;
	l32 l32TotalPixelValue = 0;//总灰度值
	f32 f32MeanPixelValue;//灰度均值
	l32 al32GrayValueCnt[256] = { 0 };//统计灰度值数
	for (l32 l32SrcImgHeightIdx = 0; l32SrcImgHeightIdx < l32SrcImgHeight; l32SrcImgHeightIdx++)
	{
		for (l32 l32SrcImgWidthIdx = 0; l32SrcImgWidthIdx < l32SrcImgWidth; l32SrcImgWidthIdx++)
		{
			l32 l32SrcImgPixelPos = l32SrcImgHeightIdx * l32SrcImgWidth + l32SrcImgWidthIdx; //第一个通道像素在内存中的位置
			l32TotalPixelValue += tSrcImg.pu8Data[l32SrcImgPixelPos];//统计总灰度值
			al32GrayValueCnt[tSrcImg.pu8Data[l32SrcImgPixelPos]] ++;
		}
	}
	f32MeanPixelValue = f32(l32TotalPixelValue) / l32TotalPixelNums;

	f32 f32MaxICV = 0;
	u8 u8BestThresh = 0;
	for (l32 l32ThreshValue = 1; l32ThreshValue <= 255; l32ThreshValue++)
	{
		l32 l32TotalPixelNumsA = 0, l32TotalPixelNumsB = 0;
		l32 l32TotalPixelValueA = 0, l32TotalPixelValueB = 0;
		f32 f32PA, f32PB;
		f32 f32MA, f32MB;
		f32 f32ICV;
		for (u8 u8GrayValueIdx = 0; u8GrayValueIdx < l32ThreshValue; u8GrayValueIdx++)
		{
			l32TotalPixelNumsA += al32GrayValueCnt[u8GrayValueIdx];
			l32TotalPixelValueA += u8GrayValueIdx*al32GrayValueCnt[u8GrayValueIdx];
		}
		f32PA = f32(l32TotalPixelNumsA) / l32TotalPixelNums;
		f32PB = 1.0 - f32PA;

		l32TotalPixelNumsB = l32TotalPixelNums - l32TotalPixelNumsA;
		l32TotalPixelValueB = l32TotalPixelValue - l32TotalPixelValueA;
		f32MA = f32(l32TotalPixelValueA) / l32TotalPixelNumsA;
		f32MB = f32(l32TotalPixelValueB) / l32TotalPixelNumsB;

		f32ICV = f32PA * (f32MA - f32MeanPixelValue) * (f32MA - f32MeanPixelValue) + f32PB * (f32MB - f32MeanPixelValue) * (f32MB - f32MeanPixelValue);
		//f32ICV = f32PA * f32PB * (f32MA - f32PB) * (f32MA - f32MB);
		if (f32ICV > f32MaxICV)
		{
			f32MaxICV = f32ICV;
			u8BestThresh = u8(l32ThreshValue);
		}
			
	}

	return u8BestThresh;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值