?? 对于“直方图”,我想绝大部分人都不会陌生,毕竟在数学中很早就遇见过,而图像的直方图(图1),从事图像相关工作的朋友肯定是再熟悉不过了。可谓是最基础不过的知识点,也是很多种空间域处理技术的基础。
图1 直方图示意图
?? 通常而言,图像的直方图都是用亮度直方图(灰度直方图)表示。对于彩色图像,还会有各个颜色通道的直方图。文中主要讲述图像的亮度直方图。它反映了图像最基本的统计特征,表示图像中具有某个灰度级的像素个数,同时也反映了图像中每种灰度出现的频率。灰度级范围为
[
0
,
L
?
1
]
[0,L-1]
[0,L?1]的数字图像的直方图是离散函数
h
(
r
k
)
=
n
k
h(r_{k})=n_{k}
h(rk?)=nk?,其中
r
k
r_{k}
rk?是第k个灰度级的值,
n
k
n_{k}
nk?是图像中的灰度
r
k
r_{k}
rk?的像素个数。若要反映灰度出现的频率,还需要做归一化操作。假设图像的长宽分别是
M
M
M和
N
N
N,则归一化的图像直方图可由离散函数
p
(
r
k
)
=
n
k
/
M
N
p(r_{k})=n_{k}/MN
p(rk?)=nk?/MN表示,
p
(
r
k
)
p(r_{k})
p(rk?)则是灰度级
r
k
r_{k}
rk?在图像出现的概率估计,因此需要满足概率性质,归一化直方图的所有分量之和等于1 。可转化为如下代码
bool histogram(BYTE* src, double* phist, int height, int width, int n=256)
{
if (n <= 0 || n > 256) return false;
double dNumber;
memset(phist, 0, n * sizeof(double));
dNumber = 256.0 / (double)n;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; i++)
{
int index = i * width + j;
BYTE pixel = src[index];
phist[(int)(pixel / dNumber)]++;
}
}
int totalpixel = height * width;
for(int k = 0; k < n; k++)
{
phist[k] = phist[k] / totalpixel;
}
return true;
}
?? 以上只是生成灰度直方图的方式,要显示直方图,还需要做单独的显示处理。图像直方图应用十分广泛,是十分重要的图像分析工具,在图像增强、图像分割以及图像灰度变换等图像处理过程中得到了广泛应用。 ?? 另外,因为这几年工作的缘故,发现直方图在ISP的pipeline中应用十分广泛,才有了此篇文章,用来巩固直方图相关的知识。比如Gamma、GTM、LTM等模块,会改变直方图的灰度级分布范围。AEC模块会根据亮度直方图确定当前曝光是否合理,判断当前曝光属于曝光不足、曝光正常还是曝光过度;也可以根据直方图中亮区和暗区的统计结果,确定HDR的触发条件等等。
个人声明: ?? 以上内容,纯属个人观点,不喜勿喷。未经本人同意,不得私自转载。若文中存在纰漏,或读者有更好的建议,欢迎留言探讨。也可邮箱联系:yxyx_0212@163.com
|