灰度直方图(histogram)是灰度级的函数,它表示图象中具有每种灰度级的象素的个数,反映图象中每种灰度出现的频率。灰度直方图的横坐标是灰度级,纵坐标是该灰度级出现的频率。
直方图均衡化是通过灰度变换将一幅图像转换为另一幅具有均衡直方图,即在每个灰度级上都具有相同的象素点数的过程。
对于离散图像,转换公式为
D = f( d ) = ( H0 + H1 + H2 + ... + Hd ) * Dmax / A0;
其中 Hi为第 i 级灰度的像素个数,A0 为图像面积,Dmax 为最大灰度值。

原图

原图灰度直方图

均衡化后

均衡化后灰度直方图
1
/**//*
2
ProcessGrayZ.h
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
256级灰度图处理(灰度直方图,直方图均衡化)。
7
*/
8
9
10
#ifndef __PROCESSGRAY_Z_H_INCLUDED__
11
#define __PROCESSGRAY_Z_H_INCLUDED__
12
13
14
#include "TypeZ.h"
15
#include "ClassImageZ.h"
16
17
18
#define GRAY_NUM_Z 256
19
20
21
/**//* 获得灰度直方图数据 */
22
/**//* 参数 hist 要求数组大小至少256个元素 */
23
PublicFuncZ R32 getHistogramZ( cImageZ src, U32 hist[] );
24
/**//* 创建 256 * 256 黑白图像,为绘制好的灰度直方图 */
25
PublicFuncZ ImageZ createImageHistogramZ( cImageZ src );
26
/**//* 创建 直方图均衡化 后的新图像 */
27
PublicFuncZ ImageZ createImageHistogramEqualizationZ( cImageZ src );
28
29
30
#endif /* __PROCESSGRAY_Z_H_INCLUDED__ */
31
1
/**//*
2
ProcessGrayZ.c
3
4
Copyright (C) 2011, coreBugZJ, all rights reserved.
5
6
256级灰度图处理(灰度直方图,直方图均衡化)。
7
*/
8
9
10
#include "stdafx.h"
11
#include "ProcessGrayZ.h"
12
13
#include <string.h>
14
15
16
PublicFuncZ R32 getHistogramZ( cImageZ src, U32 hist[] )
{
17
U32 i, x, y;
18
if ( (NULL == hist) || (!isImageValidZ(src)) || (GRAY_NUM_Z != src->colorNum) )
{
19
return RERR;
20
}
21
for ( i = 0; i < GRAY_NUM_Z; ++i )
{
22
hist[ i ] = 0;
23
}
24
for ( y = 0; y < src->height; ++y )
{
25
for ( x = 0; x < src->width; ++x )
{
26
++hist[ *( src->pPixel + src->linePitch * y + x ) ];
27
}
28
}
29
return ROK;
30
}
31
32
PublicFuncZ ImageZ createImageHistogramZ( cImageZ src )
{
33
ImageZ img = NULL;
34
U32 hist[ GRAY_NUM_Z ], mh, x, y;
35
ColorZ color;
36
37
if ( ROK != getHistogramZ( src, hist ) )
{
38
return NULL;
39
}
40
41
img = createImageZ( GRAY_NUM_Z, GRAY_NUM_Z, 2 );
42
if ( NULL == img )
{
43
return NULL;
44
}
45
46
color.r = color.g = color.b = 0;
47
color.a = 0;
48
putImagePaletteColorZ( img, 0, &color );
49
color.r = color.g = color.b = 255;
50
color.a = 0;
51
putImagePaletteColorZ( img, 1, &color );
52
53
memset( img->pPixel, 1, img->linePitch * img->height );
54
55
mh = 0;
56
for ( x = 0; x < GRAY_NUM_Z; ++x )
{
57
if ( mh < hist[ x ] )
{
58
mh = hist[ x ];
59
}
60
}
61
for ( x = 0; x < GRAY_NUM_Z; ++x )
{
62
y = hist[ x ] * GRAY_NUM_Z / mh;
63
y = GRAY_NUM_Z - y;
64
while ( GRAY_NUM_Z > y )
{
65
*( img->pPixel + y * img->linePitch + x ) = 0;
66
++y;
67
}
68
}
69
return img;
70
}
71
72
PublicFuncZ ImageZ createImageHistogramEqualizationZ( cImageZ src )
{
73
U32 hist[ GRAY_NUM_Z ], lut[ GRAY_NUM_Z ], x, y, i;
74
F64 cdf[ GRAY_NUM_Z ], size, sum, tf, t0, t255;
75
ImageZ img = NULL;
76
77
if ( ROK != getHistogramZ( src, hist ) )
{
78
return NULL;
79
}
80
81
MOV_F64_U32_Z( size, src->width );
82
MUL_F64_U32_Z( size, size, src->height );
83
84
MOV_F64_U32_Z( sum, 0 );
85
MOV_F64_U32_Z( t255, 255 );
86
MOV_F64_U32_Z( t0, 0 );
87
for ( i = 0; i < GRAY_NUM_Z; ++i )
{
88
ADD_F64_U32_Z( sum, sum, hist[ i ] );
89
DIV_F64_Z( cdf[ i ], sum, size );
90
MUL_F64_Z( tf, cdf[ i ], t255 );
91
MIN_F64_Z( tf, tf, t255 );
92
MAX_F64_Z( tf, tf, t0 );
93
MOV_U32_F64_Z( lut[ i ], tf );
94
}
95
96
img = createImageFromImageInfoZ( src );
97
if ( NULL == img )
{
98
return NULL;
99
}
100
if ( ROK != copyImagePaletteZ( img, src ) )
{
101
destroyImageZ( img );
102
return NULL;
103
}
104
for ( y = 0; y < img->height; ++y )
{
105
for ( x = 0; x < img->width; ++x )
{
106
*( img->pPixel + y * img->linePitch + x ) =
107
( (U08)( lut[ * ( src->pPixel + y * src->linePitch + x ) ]
108
)
109
);
110
}
111
}
112
return img;
113
}
114