基于FPGA的数字图像处理【3.1】

第6章 直方图操作

6.1 灰度直方图

        灰度直方图描述了一幅图像的灰度级统计信息,主要应用于图像分割、图像增强及图像灰度变换等处理过程。
        从数学上来说,图像直方图描述的是图像各个灰度级的统计特性,它是用图像灰度值的一个函数来统计一幅图像中各个灰度级出现的次数或概率,其数学定义如下所示:

其统计过程也非常简单,对于8位的灰度图像的直方图统计,C语言示例代码如下:

unsigned int pHistCnt[256];
int i,j = 0;
memset(pHistCnt,0,256);
for( i=0; i<m_dwHeight; i++)
for( j=0; j<m_dwWidth;j++)pHistCnt [m_pBitmap[i*m_dwWidth+j]]++;//统计打开图
像中各个灰度像素点的个数

图6-1(b)为图6-1(a)图像的直方图统计结果。

        在实际应用中常常会用到归一化的直方图。假定一幅图像的像素总数为N,灰度级总数为L,其中灰度级为g的像素总数为Ng 。用总像素N除以各个灰度值出现的次数Ng ,即可得到各个灰度级出现的概率,即

        上式记为归一化的灰度直方图,也称为直方图概率密度函数,通常情况下也记为PDF。
        图像的直方图中往往包含很多有效的信息,一个很明显的信息就是图像的亮度和对比度信息。若图像亮度较亮,则图像的直方图统计主要峰值偏向右侧分布;若图像亮度较暗,则图像的直方图统计主要峰值偏向左侧分布;若图像对比度较大,则图像直方图分布应该相对比较均匀;若图像对比度较小,则图像直方图分布应该相对比较集中;如图6-2~图6-4所示。

6.2 直方图均衡化

        直方图均衡化又称为灰度均衡化,是指通过某种灰度映射使输入图像转换为在每一灰度级上都有近似相同的输出图像(即输出的直方图是均匀的)。在经过均衡化处理后的图像中,像素将占有尽可能多的灰度级并且分布均匀。因此,这样的图像将具有较高的对比度和较大的动态范围。直方图均衡可以很好地解决相机过曝光或曝光不足的问题。
        为了便于分析,首先考虑灰度范围为0~1且连续的情况。若将其概率密度函数PDF记为p(x),则有如下定义

设转换前图像的概率密度函数为pr (r),转换后的图像概率密度函数为ps (s),则转换函数,即灰度映射关系为

这 样 , 若 想 使 转 换 后 的 图 像 的 概 率 密 度 函 数 : ps (s) =1,0≤s≤1(即直方图是均匀的),则必须要满足下式:

上式是在灰度值在[0,1]范围内推导出来的,对于灰度在[0,255]的情况,只要乘以最大灰度值Dmax (对于灰度图像就是255)即可。此时灰度均衡的转换公式如下:

其中,DB 为转换后的灰度值,DA 为转换前的灰度值对于离散灰度级,相应的转换公式如下:

上式中,H(i)为第i级灰度的像素个数,A0 为图像的面积,即像素总数。
由上式可以很容易地给出实例代码如下:
 

int i,j;
double result=0;
int temp;
int cnt[256]; //直方图统计结果
memset(cnt,0,256*4); //内存清零
BYTE* pTemp = new BYTE[m_dwHeight*m_dwWidth];
//开辟图像缓存,存放均衡后的图像
for( i=0; i<m_dwHeight; i++)
for( j=0; j<m_dwWidth;j++)
cnt[m_pBitmap[i*m_dwWidth+j]]++; //首先进行直方图统计
for( i=0; i<m_dwHeight; i++)
for( j=0; j<m_dwWidth;j++)
{
result = 0;
for (temp =0; temp <m_pBitmap[i*m_dwWidth+j]; temp ++)
result+=cnt[temp]统计小于当前灰度值的像素点个数
result = (result) * 255 / (m_dwWidth*m_dwHeight);
pTemp[i*m_dwWidth+j]=result;/*统计结果图像*/
}

分别对一个亮度较暗(曝光不足)的图像和亮度较亮(过曝光)的图像进行直方图均衡化处理,处理结果分别如图6-5和图6-6所示。

        可见,经过直方图均衡化处理后,过曝光和曝光不足的问题均得到了解决,图像的对比度得到了很大的提升。不妨从图像的直方图统计图进行分析,上面四幅图的直方图统计结果分别如图6-7和图6-8所示。

        由直方图统计图可见,经过均衡化后的直方图被“拉开”了,之前密集的直方图分布经过均衡化之后变得稀疏而均匀,这样的处理结果也使得处理后的图像更加具有层次感。

6.3 直方图规定化

        直方图均衡化可以自动确定灰度变换函数,从而获得具有均匀直方图的输出图像。它主要用于增强动态范围较小的图像对比度,丰富图像的灰度级。这种方法的优点是操作简单,且结果可以预知,当图像需要自动增强时是一种不错的选择。
        在某种情况下,我们可能需要人为地控制直方图的形状,即我们希望获得具有指定直方图输出的图像,这样就可以有选择地增强某个灰度范围内的对比度或者使图像灰度值满足某种特定的分布。这种用于产生具有特定直方图的图像的方法称为直方图规定化。
        直方图规定化是在运用均衡化原理的基础上,通过建立原始图像和期望图像(待匹配直方图的图像)之间的关系,使原始图像的直方图匹配特定的形状,从而弥补了直方图均衡化不具备交互作用的特性。
        其匹配原理是首先对原始的图像进行均衡化,转换公式如下:

于是可以按照如下的步骤来由输入图像得到一个具有规定概率密度的图像:
(1)求得变换关系f(r)。
(2)求得变换关系g(z)。
(3)令f(r)=g(z)求得变换关系g-1 (s)。
(4)对输入图像进行 变换,从而得到输出图像。
        当然,在计算过程中,利用的是其离散形式,这样就不必去关心函数f(r),g(z)及反变换函数g-1 (s)的具体解析形式,而可以直接将它们作为映射表进行处理了。其中,f(r)为图像均衡化的离散灰度级映射关系,g(z)为标准图像均衡化后的离散灰度级映射关系,而g-1(s)则是标准图像均衡化的逆映射关系,它给出了从经过均衡化处理的标准化图像到源标准图像的离散灰度映射,相当于均衡化处理的逆过程。

void CImgPrcView::OnHistRegulations()
{
int i,j,m,k = 0;
if (!m_pBitmap)return; //如果没有打开图像则返回
FreeInterResultImage(); //释放之前的显示缓存
CString str1 =
"C:\\Users\\jayash\\Desktop\\sim\\image_source\\
hist_test2.bmp"; BYTE* pTemp = new
BYTE[m_dwHeight*m_dwWidth];
//存放均衡后的图像
BYTE* pStand = new BYTE[m_dwHeight*m_dwWidth];//存放均
衡后的图像
CZXDib m_dib;
m_dib.LoadVectorFromBMPFile(str1,pStand,m_dwHeight,m_dw
Width,
m_flag);int Hist[256];
memset(Hist,0,256 * 4);
for (i = 0; i<m_dwHeight; i++)
for (j = 0; j < m_dwWidth; j++)
Hist[pStand[i*m_dwWidth + j]]++;
int pdTran[256];
memset(pdTran,-1,256 * 4);
for (i = 0; i < 256; i++)
{
double sum = 0;
for (j = 0; j < i; j++)
{
sum += Hist[j];
}
*(pdTran + (int)(0.5 + 255 * sum/
(m_dwHeight*m_dwWidth))) = i;
}
i = j = 0;
while (i < 255)
{
if (pdTran[i + 1]!= -1)
{
i++;
continue;
}
j = 1;
while ((pdTran[i + j]== -1) && (i + j <= 255)){
pdTran[i + j]= pdTran[i];
j++;
}
}
for (i = 0; i < m_dwHeight; i++)
for (j = 0; j < m_dwWidth; j++)
{
double sum = 0;
for (k = 0; k < m_pBitmap[i*m_dwWidth + j]; k++)
{
sum += Hist[k];
}
int result = pdTran[(int)(255 * sum /
(m_dwWidth*m_dwHeight))];
if (result > 255)result = 255;
if (result < 0)result = 0;
pTemp[i*m_dwWidth + j]= result;
}
AddInterResultImage(pTemp,m_dwHeight,m_dwWidth,8," 直 方
图规定");
Invalidate(FALSE);
UpdateWindow();
//delete[]pTemp;
}

        以图6-9(a)作为规定的标准图像,图6-9(b)为其直方图统计图。对图6-10(a)按照图6-9进行直方图规定,规定结果如图6-10(b)所示,其规定前后的直方图通分别如图6-11(a)和图6-11(b)所示。

        注意,对比标准图像和规定后图像的直方图统计图,如图6-9(a)和图6-11(b)所示,经过处理后,原图像的直方图统计分布区间及特性与标准图像非常接近了。我们从规定后图像与标准图像的对比结果也可得到整个结论。

6.4 直方图拉伸

        在视频处理中,为了能够实时调节图像的对比度,通常需要对直方图进行拉伸处理。直方图拉伸是指将图像灰度直方图较窄的灰度级区间向两端拉伸,增强整幅图像像素的灰度级对比度,达到增强图像的效果。
        常用的直方图拉伸方法有线性拉伸、3段式分段线性拉伸和非线性拉伸等。这里我们介绍FPGA中常见的线性拉伸。
        线性拉伸也即灰度拉伸,属于线性点运算的一种。它扩展图像的直方图,使其充满整个灰度级范围内。
        设f(x,y)为输入图像,它的最小灰度级A和最大灰度级B的定义如下:

其代码实现也非常简单,如下所示:
int i,j = 0;
int min,max = m_pBitmap [0];
for (i = 0; i<m_dwHeight; i++)
for (j = 0; j < m_dwWidth; j++)
{
if(m_pBitmap [i*m_dwWidth + j]>max)max = m_pBitmap
[i*m_dwWidth + j];
if(m_pBitmap [i*m_dwWidth + j]<min)min = m_pBitmap
[i*m_dwWidth + j];
}
BYTE* pTemp = new BYTE[m_dwHeight*m_dwWidth];//存放拉伸
后的图像
if(max == min)return;
for (i = 0; i<m_dwHeight; i++)for (j = 0; j < m_dwWidth; j++)
{
pTemp[i*m_dwWidth + j]= 255*(m_pBitmap [i*m_dwWidth +
j]-min)/
((double)(max-min));
}
AddInterResultImage(pTemp,m_dwHeight,m_dwWidth,8," 线 性
灰度变换");

对于图6-12(a)的图像进行上述直方图线性拉伸后的结果如图6-12(b)所示。

拉伸变换前后的直方图统计分别如图6-13(a)和图6-13(b)所示。

        可见,线性拉伸达到了类似于直方图均衡化的功能,将比较集中的直方图拉伸到整个灰度分布区域。但是,在实际应用中,并不会采用上述的拉伸方式,主要是基于噪声考虑。我们试着考虑在图6-12(a)叠加几个纯黑点(0)和纯白点(255)噪声。线性拉伸后的效果如图6-14所示。

        可见,由于椒盐噪声的影响,上述线性拉伸方式并不能得到我们预期的目的,而在实际的图像处理任务中,这样的噪声是非常常见的。
        为了解决这个问题,一种比较常用的处理办法是基于直方图统计的线性拉伸。此种方法不是单单地用整幅图像的最高灰度值和最低灰度值来计算拉伸系数A和B,而是基于直方图统计信息来进行计算。计算步骤如下:
(1)首先进行直方图统计计算,规定灰度值为i的统计结果为H(i)。
(2)计算直方图统计累加和Sum(k),定义如下:

由定义可知,该拉伸运算直接截取直方图“有效”区间进行拉伸,可大大减小噪声干扰。
实例代码如下:
 

int LowCnt = 100;
int HighCnt = 100;
BYTE* pTemp1 = new BYTE[m_dwHeight*m_dwWidth];//存放拉
伸后的图像
DWORD *Hist = new DWORD[256];
memset(Hist,0,256*sizeof(DWORD));
DWORD LowIndex = 0,HighIndex = 0;
DWORD hist_cnt = 0;
for (i = 0; i < m_dwHeight*m_dwWidth; i++)
{
Hist[m_pBitmap[i]]++;/*直方图统计*/
}
int find_min = 0,find_max = 0;
for (i = 0; i < 256; i++)
{
hist_cnt += Hist[i];
if ((hist_cnt >= LowCnt) && (!find_min))
{
LowIndex = i;
find_min = true;
}
if((hist_cnt>=m_dwHeight*m_dwWidth-HighCnt)&&
(!find_max))
{
HighIndex = i;
find_max = true;}
}
if (HighIndex == LowIndex)return;
for (i = 0; i < m_dwHeight*m_dwWidth; i++)
{
if (m_pBitmap[i]<= LowIndex) pTemp1[i]= 0;
else if (m_pBitmap[i]>= HighIndex) pTemp1[i]= 255;
else pTemp1[i]= (m_pBitmap[i]- LowIndex)*255.0 /
(HighIndex
- LowIndex);}
AddInterResultImage(pTemp1,m_dwHeight,m_dwWidth,8,"直方
图拉伸");

再次对图6-14(a)图像进行直方图统计拉伸,截断前后100个统计结果,效果如图6-15所示。

可见,此时的拉伸效果已经非常好了,数目比较少的噪声得到了有效的抑制,得到了预期的拉伸目的。需要注意的是两个高低阈值的设置,如果设置太大,就会造成图像细节的丢失。

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BinaryStarXin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值