实验原理
直方图均衡是直方图变换的一种方法,通过直方图均衡可以增加像素灰度值的动态范围,从而达到增强图像对比度(清晰度)的效果。1
目标:要找到一种变换
t
=
E
H
(
s
)
t=E_{H}(s)
t=EH(s)使直方图变平直,为使变换后的灰度仍保持从黑到白的单一变化顺序,且变换范围与原先一致,以避免整体变亮或变暗。必须规定:
(1)在
0
⩽
s
⩽
1
0\leqslant s \leqslant1
0⩽s⩽1,
E
H
(
s
)
E_{H}(s)
EH(s)是单调递增函数,且
0
⩽
E
H
(
s
)
⩽
1
0\leqslant E_{H}(s) \leqslant1
0⩽EH(s)⩽1
(2)反变换
s
=
E
H
−
1
(
t
)
s=E{^{-1}_H}(t)
s=EH−1(t)也是单调递增函数,
0
⩽
s
⩽
1
0\leqslant s \leqslant1
0⩽s⩽1
实验步骤
Step1:归一化直方图:设一幅图像的像素总数为n,共有L个灰度级, n k n_k nk为第k个灰度级出现的次数。
计算每个灰度值出现的概率 p ( s k ) = n i n p(s_k)=\frac{n_i}{n} p(sk)=nni
Step2: 积累直方图: t k = E H ( s ) = ∑ t = 0 k P ( S i ) = ∑ i = 0 k n i n t_k=E_{H}(s)=\sum_{t=0}^k P(S_i) =\sum_{i=0}^k \frac{n_i}{n} tk=EH(s)=∑t=0kP(Si)=∑i=0knni
(1)
t
k
t_k
tk是k的单值单增函数
(2)灰度取值范围一致,0≤k≤1
(3)将s的分布转换为t的均匀分布
计算累积概率
t
k
=
E
H
(
s
)
=
∑
t
=
0
k
P
(
S
i
)
t_k=E_{H}(s)=\sum_{t=0}^k P(S_i)
tk=EH(s)=∑t=0kP(Si)
Step3:把归一化的
t
k
t_k
tk,变回灰度值区间[0,L-1]。具体的方法就是令
t
k
=
i
n
t
[
(
L
−
1
)
t
k
+
0.5
]
t_k=int[(L-1)t_k+0.5]
tk=int[(L−1)tk+0.5]
Step4:对图像中每一个像素的灰度值进行映射,得到均衡后的图像。
实现代码
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define width 500
#define height 500
int main()
{
FILE* AFile =NULL;
FILE* BFile=NULL;
AFile=fopen("seed.yuv","rb");
if(AFile==NULL)
{
printf("cannot find seed.yuv\n");
exit(1);
}
BFile=fopen("seed_1.yuv","wb");
if(BFile==NULL)
{
printf("cannot find seed_1.yuv\n");
exit(1);
}
unsigned char *yBuf;
yBuf=(unsigned char *)malloc(width*height);
unsigned char *uBuf;
uBuf=(unsigned char *)malloc(width*height);
unsigned char *vBuf;
vBuf=(unsigned char *)malloc(width*height);
int count[256]={0};
double freq[256]={0};
if (!feof(AFile))
{
if(!fread(yBuf,1,width*height,AFile))
{
printf("cannot read y%d ");
}
if(!fread(uBuf,1,width*height,AFile))
{
printf("cannot read u%d ");
}
if(!fread(vBuf,1,width*height,AFile))
{
printf("cannot read v%d ");
}
for (int i = 0; i < width*height; i++)
{
for(int m=0;m<256;m++)
if(yBuf[i]==m)
count[m]++;
}
for (int i = 0; i < 256; i++)
{
freq[i]=(double)count[i]/(width*height);
if (i)
freq[i]=freq[i]+freq[i-1];
count[i]=int(255*freq[i]+0.5);
}
for (int i = 0; i < width*height; i++)
{
//yBuf[i]=count[yBuf[i]];
for(int m=0;m<256;m++)
if(yBuf[i]==m)
{
yBuf[i]=count[m];
break;//注意
}
}
fwrite(yBuf,1,width*height,BFile);
fwrite(uBuf,1,width*height,BFile);
fwrite(vBuf,1,width*height,BFile);
free(yBuf);
free(uBuf);
free(vBuf);
fclose(AFile);
fclose(BFile);
getchar();
}
return 0;
}
实验结果
原始图像
增强图像
灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数:其横坐标是灰度级,纵坐标是该灰度出现的频率(对数字图像即指像素的个数)。 ↩︎