最近在研究冈萨雷斯的那本《数字图像处理》,发现此书确实不错。看到直方图均衡这一章,顺便研究了下OpenCV的源代码。
直方图均衡化是一个很强大的自适应对比度增强工具。
详细的说明可以见《数字图像处理.第三版》(冈萨雷斯)英文版 P144。
一个灰度值在一幅图像中出现的概率可以表示如下:
------------(1)
注: L表示灰度级别,8位灰度图的L=256.
-----------------------(2)
注:T()表示一个灰度变换函数,满足单调性。nj表示灰度j在图像中出现的次数。
由公式(2)可以得到每个输入图像的灰度对应输出图像的灰度值,对sk四舍五入。
详细的证明可以参考书上。
最后查看了下OpenCV的源代码。
查看源代码:可以进入OpenCV的安装目录,打开OpenCV.sln 这个工程文件。利用vs2008自带的搜索工具,搜索关键字 cvEqualizeHist。
附上OpenCV直方图均衡化的源码。
CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr )
{
CvMat sstub, *src = cvGetMat(srcarr, &sstub);
CvMat dstub, *dst = cvGetMat(dstarr, &dstub);
CV_Assert( CV_ARE_SIZES_EQ(src, dst) && CV_ARE_TYPES_EQ(src, dst) &&
CV_MAT_TYPE(src->type) == CV_8UC1 );
CvSize size = cvGetMatSize(src);
if( CV_IS_MAT_CONT(src->type & dst->type) )
{
size.width *= size.height;
size.height = 1;
}
int x, y;
const int hist_sz = 256;
int hist[hist_sz];
memset(hist, 0, sizeof(hist));
for( y = 0; y < size.height; y++ )
{
const uchar* sptr = src->data.ptr + src->step*y;
for( x = 0; x < size.width; x++ )
hist[sptr[x]]++;
}
float scale = 255.f/(size.width*size.height);
int sum = 0;
uchar lut[hist_sz+1];
for( int i = 0; i < hist_sz; i++ )
{
sum += hist[i];
int val = cvRound(sum*scale);
lut[i] = CV_CAST_8U(val);
}
lut[0] = 0;
for( y = 0; y < size.height; y++ )
{
const uchar* sptr = src->data.ptr + src->step*y;
uchar* dptr = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++ )
dptr[x] = lut[sptr[x]];
}
}