最近在研究岡薩雷斯的那本《數字圖像處理》,發現此書確實不錯。看到直方圖均衡這一章,順便研究了下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]];
}
}