赞
踩
灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数,即 h ( k ) = n k ( k = 0 , 1 , ⋯ , L − 1 ) h(k)=n_k\quad (k=0,1,\cdots,L-1) h(k)=nk(k=0,1,⋯,L−1),其中 L L L为图像的灰度级数。
直方图均衡的目的是将图像的直方图修正为均匀分布形式(离散分布做不到完全均匀,但可以接近),增加像素灰度值的动态范围,从而达到增强图像对比度,提高清晰度的效果。
因而我们需要找到一种变换 t = E H ( s ) t=E_{\rm H}(s) t=EH(s)使得直方图变平直,且要使变换后的灰度仍保持从黑到白的单一变化顺序、变换范围与原先一致。同时规定:
具体方法如下:
设一幅图像的像素总数为
n
n
n,共有
L
L
L个灰度级,
n
k
n_k
nk为第
k
k
k个灰度级出现的频率。则第
k
k
k个灰度级直方图均衡出现的概率为
p
(
s
k
)
=
n
k
n
p(s_k) = \dfrac {n_k} n
p(sk)=nnk
计算累计概率
t
k
=
E
H
(
s
k
)
=
∑
i
=
0
k
p
(
s
k
)
,
0
≤
t
k
≤
1
t_{k}=E_{\mathrm{H}}\left(s_{k}\right)=\sum_{i=0}^{k} p\left(s_{k}\right), \quad 0 \leq t_{k} \leq 1
tk=EH(sk)=i=0∑kp(sk),0≤tk≤1
将
s
s
s的分布转换为
t
t
t的均匀分布;
将归一化的
t
k
t_k
tk,映射回灰度值区间
[
0
,
L
−
1
]
[0,L-1]
[0,L−1]:
t
k
=
i
n
t
[
(
L
−
1
)
t
k
+
0.5
]
t_k = {\rm int}\left[ (L-1)t_k+0.5 \right]
tk=int[(L−1)tk+0.5]
其中加0.5再取整即为在程序中取四舍五入的算法;
对图像中每一个像素的灰度值进行映射,得到均衡后的图像。
下面将对seed.yuv进行直方图均衡。
#pragma once
extern int w;
extern int h;
void Freq(unsigned char* yBuff, double freq[]);
void CumulativeFreq(double prob[], double cumProb[]);
void Mapping(double cumProb[], unsigned char* yBuffOri, unsigned char* yBuffEqu);
#include "declarations.h" #include <iostream> int w = 500; int h = 500; void Freq(unsigned char* yBuff, double prob[]) { double count[256] = { 0 }; for (int i = 0; i < w * h; i++) { int greyIndex = (int)yBuff[i]; count[greyIndex]++; } for (int i = 0; i < 256; i++) { prob[i] = count[i] / (w * h); //printf("%-5d%lf\n", i, prob[i]); } } void CumulativeFreq(double prob[], double cumProb[]) { cumProb[0] = 0; //printf("%-5d%lf\n", 0, cumProb[0]); for (int i = 1; i < 256; i++) { cumProb[i] = cumProb[i - 1] + prob[i - 1]; //printf("%-5d%lf\n", i, cumProb[i]); } } void Mapping(double cumProb[], unsigned char* yBuffOri, unsigned char* yBuffEqu) { for (int i = 0; i < 256; i++) { cumProb[i] = floor(255 * cumProb[i] + 0.5); } for (int i = 0; i < w * h; i++) { int greyIndex = (int)yBuffOri[i]; yBuffEqu[i] = cumProb[greyIndex]; } }
#include <iostream> #include "declarations.h" using namespace std; int main(int argc, char* argv[]) { FILE* oriImgPtr; FILE* equImgPtr; const char* oriImgName = argv[1]; const char* equImgName = argv[2]; int greyFreq[256] = { 0 }; double greyProb[256] = { 0 }; double greyCumProb[256] = { 0 }; /* Open the files */ if (fopen_s(&oriImgPtr, oriImgName, "rb") == 0) { cout << "Successfully opened \"" << oriImgName << "\"." << endl; } else { cout << "Failed to open \"" << oriImgName << "\"." << endl; exit(-1); } if (fopen_s(&equImgPtr, equImgName, "wb") == 0) { cout << "Successfully opened \"" << equImgName << "\"." << endl; } else { cout << "Failed to open \"" << equImgName << "\"." << endl; exit(-1); } /* Space allocation */ unsigned char* oriYBuff = new unsigned char[w * h]; unsigned char* equYBuff = new unsigned char[w * h]; unsigned char* equUBuff = new unsigned char[w * h / 4]; unsigned char* equVBuff = new unsigned char[w * h / 4]; /* Initialisation of U & V component (greyscale image) */ memset(equUBuff, 128, w * h / 4); memset(equVBuff, 128, w * h / 4); /* Read Y component into the buffer */ fread(oriYBuff, sizeof(unsigned char), w * h, oriImgPtr); /* Calculate probabilities of each grey value */ Freq(oriYBuff, greyProb); /* Calculate cumulative probabilites of each grey value */ CumulativeFreq(greyProb, greyCumProb); /* Mapping */ Mapping(greyCumProb, oriYBuff, equYBuff); /* Write histogram-equalised data into the new file */ fwrite(equYBuff, sizeof(unsigned char), w * h, equImgPtr); fwrite(equUBuff, sizeof(unsigned char), w * h / 4, equImgPtr); fwrite(equVBuff, sizeof(unsigned char), w * h / 4, equImgPtr); delete[]oriYBuff; delete[]equYBuff; delete[]equUBuff; delete[]equVBuff; fclose(oriImgPtr); fclose(equImgPtr); }
实验结果如下:
可以看到,相比原图,直方图均衡很好地实现了增强对比度、提高清晰度的功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。