0%

图像信息处理作业Assignment3

第三次图像信息处理作业解析,这次要对直方图动手了。

Assignment-3作业要求

  • Image logarithmic operation for visibility enhancement
  • Histogram equalization

    作业分析

    图像对数强化

这玩意儿老师上课貌似没讲,检索了一下大概就是通过如下的公式进行操作

在这里,我们定义如下的常数$C$

通过加一我们可以保证所有的$C$和$S$是非负数

首先先求出$C$

1
2
3
4
5
6
7
8
unsigned char* max;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
unsigned char data = *(biData + lineBytes * (height - 1 - i) / 3 + j);
max = max > data ? max : data;
}
}
double c = 255.0 / (log(1 + max));

然后代入公式

1
2
3
4
5
6
7
unsigned char* logData = new unsigned char[lineBytes * height / 3];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
unsigned char r = *(biData + lineBytes * (height - 1 - i) / 3 + j)
*(logData + lineBytes * (height - 1 - i) / 3 + j) = c * log(1 + r);
}
}

这样我们就获得了log后的图像

直方图均衡化

考虑一个离散的灰度图像$x$,让$n_i$ 表示灰度$i$出现的次数,这样图像中灰度为$i$的像素的出现概率是

$L$ 是图像中所有的灰度数(通常为256),$n$ 是图像中所有的像素数,$p_x(i)$实际上是像素值为$i$的图像的直方图,归一化到 [0,1]。

把对应于$p_x$的累积分布函数,定义为:

是图像的累计归一化直方图。

我们创建一个形式为$ y= T(x)$ 的变换,对于原始图像中的每个值它就产生一个$y$,这样 $y$的累计概率函数就可以在所有值范围内进行线性化,转换公式定义为:

对于常数$K$。CDF的性质允许我们做这样的变换(参见逆分布函数);定义为

其中$k$属于区间 [0,L)。注意 T 将不同的等级映射到${0..1}$​域,为了将这些值映射回它们最初的域,需要在结果上应用下面的简单变换:

上面描述了灰度图像上使用直方图均衡化的方法,但是通过将这种方法分别用于图像RGB颜色值的红色、绿色和蓝色分量,从而也可以对彩色图像进行处理。

首先,我们需要先得到直方图

1
2
3
4
5
6
7
8
9
10
unsigned char* histData = new unsigned char[lineBytes * height / 3];
int hist[256] = {0}, eqHist[256] = {0};
int size = height * width;
double fpHist[256] = {0}, eqHistTemp[256] = {0};
for (int i = 0; i < height; i++) { //计算直方图
for (int j = 0; j < width; j++) {
unsigned char GrayIndex = *(biData + lineBytes * (height - 1 - i) / 3 + j);
hist[GrayIndex]++;
}
}

然后,我们计算灰度分布和累计直方图分布

1
2
3
4
5
6
7
8
9
10
11
12
for (int i = 0; i < 256; i++) { //计算灰度分布密度
fpHist[i] = (double)hist[i] / (double)size;
}

for (int i = 0; i < 256; i++) { //计算累计直方图分布
if (i == 0) {
eqHistTemp[i] = fpHist[i];
}
else {
eqHistTemp[i] = eqHistTemp[i - 1] + fpHist[i];
}
}

最后,我们可以直接得出映射关系

1
2
3
4
5
6
7
8
9
10
//累计分布取整,保存计算出来的灰度映射关系
for (int i = 0; i < 256; i++) {
eqHist[i] = (int)(255.0 * eqHistTemp[i] + 0.5);
}
for (int i = 0; i < height; i++) { //进行灰度映射均衡化
for (int j = 0; j < width; j++) {
unsigned char GrayIndex = *(biData + lineBytes * (height - 1 - i) / 3 + j);
*(histData + lineBytes * (height - 1 - i) / 3 + j) = eqHist[GrayIndex];
}
}

效果如图

总结

总的来说这次作业依然是十分的宁静祥和、简单质朴,不过在直方图均衡化的部分由于不太了解细节,因此借鉴了部分代码,写作风格也十分的奇妙,希望多多包含。