第三次图像信息处理作业解析,这次要对直方图动手了。
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]; } }
|
效果如图
总结
总的来说这次作业依然是十分的宁静祥和、简单质朴,不过在直方图均衡化的部分由于不太了解细节,因此借鉴了部分代码,写作风格也十分的奇妙,希望多多包含。