直方图规定化
就是通过一个灰度映像函数,将原灰度直方图改造成所希望的直方图。所以直方图修正的关键就是灰度映像函数。
直方图规定化是用于产生处理后有特殊直方图的图像方法。
直方图均衡化能自动增强图像的整体对比度,但是往往结果难以受到控制。实际中常常需要增强某个特定灰度值范围内的对比度或使图像灰度值的分布满足特定需求。这个时候使用直方图规定化会有较好的结果。
直方图规定化就是要调整原始图像的直方图去逼近规定的目标直方图。M为原始图的灰度级数,N为目标图的灰度级数,且M>N。
直方图规定化的基本原理
根据直方图均衡化理论,首先对原始图像进行直方图均衡化处理.即求变换函数
s = T ( r ) = ∫ 0 r P r ( x ) d x s=T(r)=\int_0^rP_r(x)dx s=T(r)=∫0rPr(x)dx
现假定直方图规定化的目标图像已经实现,因此,对于目标图像也采用同样的方法进行均衡化处理,因而:
v = G ( z ) = ∫ 0 z P z ( x ) d x v=G(z)=\int_0^zP_z(x)dx v=G(z)=∫0zPz(x)dx
上式的逆变换为
z = G − 1 ( v ) z=G^{-1}(v) z=G−1(v)
上式表明,可通过均衡化后的灰度级v求出目标函数的灰度级z。由于对目标图像和原始图像都进行了均衡化处理,因此具有相同的分布密度,即
P s ( s ) = P v ( v ) P_s(s)=P_v(v) Ps(s)=Pv(v)
因而可以用原始图像均衡化以后的灰度级s代表v,即
z = G − 1 ( v ) = G − 1 ( s ) z=G^{-1}(v)=G^{-1}(s) z=G−1(v)=G−1(s)
所以可以依据原始图像均衡化后的图像的灰度值得到目标图像的灰度级z。
直方图规定化方法
直方图规定化处理的一般步骤是:
- 根据直方图均衡化原理,对原图像的直方图进行灰度均衡化处理。
- 按照目标图像的概率密度函数 P z ( z ) P_z(z) Pz(z),求解目标图像进行均衡化处理的变换函数 G ( z ) G(z) G(z);
- 用原始图像均衡化中得到的灰度级s代替v,求解逆变换 z = G − 1 ( s ) z=G^{-1}(s) z=G−1(s).
经过上述处理得到的目标图像的灰度级将具有事先规定的概率密度 P z ( z ) P_z(z) Pz(z)。上述变换过程中所包含的两个变换函数 T ( r ) T(r) T(r)和 G − 1 ( s ) G^{-1}(s) G−1(s)可形成复合函数,即可表示为
z = G − 1 ( s ) = G − 1 [ T ( r ) ] z=G^{-1}(s)=G^{-1}[T(r)] z=G−1(s)=G−1[T(r)]
由此可知,无需进行直方图均衡化运算就可以直接实现直方图规定化处理,通过复合函数关系有效的简化了直方图规定化处理过程,求出
T
(
r
)
T(r)
T(r)和
G
−
1
(
s
)
G^{-1}(s)
G−1(s)之间的复合函数关系就可以直接对原始图像进行变换。
举例
假设一幅大小为64像素(MN=4096)的3比特图像(L=8)的灰度分布如表3.1所示,其中灰度级范围[0,L-1]=[0,7]中的整数。
表3.1 大小为64*64像素的3比特数字图像的灰度分布和直方图值
r k r_k rk n k n_k nk p r ( r k ) = n k / M N p_r(r_k)=n_k/MN pr(rk)=nk/MN r 0 r_0 r0 790 0.19 r 1 r_1 r1 1023 0.25 r 2 r_2 r2 850 0.21 r 3 r_3 r3 656 0.16 r 4 r_4 r4 329 0.08 r 5 r_5 r5 245 0.06 r 6 r_6 r6 122 0.03 r 7 r_7 r7 81 0.02 假设图像的直方图如图3.19(a)所示。直方图累计函数分布:
s 0 = T ( r 0 ) = 7 ∑ j = 0 0 p r ( r j ) = 7 p r ( r 0 ) = 1.33 s_0=T(r_0)=7\sum_{j=0}^{0} p_r(r_j)=7p_r(r_0)=1.33 s0=T(r0)=7j=0∑0pr(rj)=7pr(r0)=1.33 s 1 = T ( r 1 ) = 7 ∑ j = 0 1 p r ( r j ) = 7 p r ( r 0 ) + 7 p r ( r 1 ) = 7 ∗ 0.19 + 7 ∗ 0.25 = 3.08 s_1=T(r_1)=7\sum_{j=0}^{1}p_r(r_j)=7p_r(r_0)+7p_r(r_1)=7*0.19+7*0.25=3.08 s1=T(r1)=7j=0∑1pr(rj)=7pr(r0)+7pr(r1)=7∗0.19+7∗0.25=3.08 s 2 = T ( r 2 ) = 7 ∑ j = 0 2 p r ( r j ) = 7 p r ( r 0 ) + 7 p r ( r 1 ) + 7 p r ( r 2 ) = 7 ∗ 0.19 + 7 ∗ 0.25 + 7 ∗ 0.21 = 4.55 s_2=T(r_2)=7\sum_{j=0}^{2}p_r(r_j)=7p_r(r_0)+7p_r(r_1)+7p_r(r_2)=7*0.19+7*0.25+7*0.21=4.55 s2=T(r2)=7j=0∑2pr(rj)=7pr(r0)+7pr(r1)+7pr(r2)=7∗0.19+7∗0.25+7∗0.21=4.55
······
类似可得出:
s 3 = 5.67 , s 4 = 6.23 , s 5 = 6.65 , s 6 = 6.86 , s 7 = 7.00 s_3=5.67,s_4=6.23,s_5=6.65,s_6=6.86,s_7=7.00 s3=5.67,s4=6.23,s5=6.65,s6=6.86,s7=7.00。
该变换函数的形状为阶梯状态,如图3.19(b)。
由于s是由概率和求得,所以它一直是一个小数,因此要把它们改成最接近的整数:
s k s_k sk G ( z k ) G(z_k) G(zk) s 0 s_0 s0 1 s 1 s_1 s1 3 s 2 s_2 s2 5 s 3 s_3 s3 6 s 4 s_4 s4 6 s 5 s_5 s5 7 s 6 s_6 s6 7 s 7 s_7 s7 7 这些是均衡后的直方图的值。很明显,只有5个不同的灰度级。因为 r 0 = 0 r_0=0 r0=0被映射为 s 0 = 1 s_0=1 s0=1,在均衡后的图像中有790个像素具有该值(见表3.1)。另外,在图像中有1023个像素取 s 1 = 3 s_1=3 s1=3这个值,有850个像素取 s 2 = 5 s_2=5 s2=5这个值。由于 r 3 r_3 r3和 r 4 r_4 r4都被映射为同一个值6,所以均衡后的图像中有(656+329)=985个像素取这个值。类似的,在均衡后的图像中有(245+122+81)=448个像素取7这个值。
均衡后直方图取值:表3.11
s k s_k sk n k n_k nk p k ( s k ) = n k / M N p_k(s_k)=n_k/MN pk(sk)=nk/MN s 0 = 1 s_0=1 s0=1 790 0.19 s 1 = 3 s_1=3 s1=3 1023 0.25 s 2 = 5 s_2=5 s2=5 850 0.21 s 3 , 4 = 6 s_{3,4}=6 s3,4=6 985 0.24 s 5 , 6 , 7 = 7 s_{5,6,7}=7 s5,6,7=7 448 0.11
再次考虑上面64*64的假设图像,其直方图重复显示在图3.22(a)中。希望变换该直方图,以便使其具有表3.2中第二列规定的值。图3.22(b)显示了该直方图的大概形状。表3.2 规定直方图和实际直方图
z q z_q zq 规定的 p z ( Z q ) p_z(Z_q) pz(Zq) z 0 = 0 z_0=0 z0=0 0.00 z 1 = 1 z_1=1 z1=1 0.00 z 2 = 2 z_2=2 z2=2 0.00 z 3 = 3 z_3=3 z3=3 0.15 z 4 = 4 z_4=4 z4=4 0.20 z 5 = 5 z_5=5 z5=5 0.30 z 6 = 6 z_6=6 z6=6 0.20 z 7 = 7 z_7=7 z7=7 0.15 计算直方图均衡后的累计分布值:
G ( z 0 ) = 7 ∑ j = 0 0 p z ( z j ) = 7 ∗ 0.00 = 0.00 G(z_0)=7\sum_{j=0}^{0}p_z(z_j)=7*0.00=0.00 G(z0)=7j=0∑0pz(zj)=7∗0.00=0.00 G ( z 1 ) = 7 ∑ j = 0 1 p z ( z j ) = 7 ∗ 0.00 + 7 ∗ 0.00 = 0.00 G(z_1)=7\sum_{j=0}^{1}p_z(z_j)=7*0.00+7*0.00=0.00 G(z1)=7j=0∑1pz(zj)=7∗0.00+7∗0.00=0.00 G ( z 2 ) = 7 ∑ j = 0 2 p z ( z j ) = 0 G(z_2)=7\sum_{j=0}^{2}p_z(z_j)=0 G(z2)=7j=0∑2pz(zj)=0 G ( z 3 ) = 7 ∑ j = 0 3 p z ( z j ) = 7 ∗ 0.15 = 1.05 G(z_3)=7\sum_{j=0}^{3}p_z(z_j)=7*0.15=1.05 G(z3)=7j=0∑3pz(zj)=7∗0.15=1.05 G ( z 4 ) = 7 ∑ j = 0 4 p z ( z j ) = 7 ∗ 0.15 + 7 ∗ 0.20 = 2.45 G(z_4)=7\sum_{j=0}^{4}p_z(z_j)=7*0.15+7*0.20=2.45 G(z4)=7j=0∑4pz(zj)=7∗0.15+7∗0.20=2.45 G ( z 5 ) = 7 ∑ j = 0 5 p z ( z j ) = 7 ∗ 0.15 + 7 ∗ 0.20 + 7 ∗ 0.3 = 4.55 G(z_5)=7\sum_{j=0}^{5}p_z(z_j)=7*0.15+7*0.20+7*0.3=4.55 G(z5)=7j=0∑5pz(zj)=7∗0.15+7∗0.20+7∗0.3=4.55 G ( z 6 ) = 7 ∑ j = 0 6 p z ( z j ) = 4.55 + 7 ∗ 0.20 = 5.95 G(z_6)=7\sum_{j=0}^{6}p_z(z_j)=4.55+7*0.20=5.95 G(z6)=7j=0∑6pz(zj)=4.55+7∗0.20=5.95 G ( z 7 ) = 7 ∑ j = 0 7 p z ( z j ) = 5.95 + 7 ∗ 0.15 = 7.00 G(z_7)=7\sum_{j=0}^{7}p_z(z_j)=5.95+7*0.15=7.00 G(z7)=7j=0∑7pz(zj)=5.95+7∗0.15=7.00 把这些分数值转换为有效区间[0,7]内的整数。结果是:
结果形成表3.3,则可得变换函数3.22©。表3.3
z q z_q zq G ( z q ) G(z_q) G(zq) z 0 z_0 z0 0 z 1 z_1 z1 0 z 2 z_2 z2 0 z 3 z_3 z3 1 z 4 z_4 z4 2 z 5 z_5 z5 5 z 6 z_6 z6 6 z 7 z_7 z7 7 第三步,找到 z q z_q zq最小值。所以值 G ( Z q ) G(Z_q) G(Zq)最接近 s k s_k sk。我们对每一个 s k s_k sk值这样做,以产生从s到z所需要的映射。
- s 0 = 1 s_0=1 s0=1,我们看到 G ( z 3 ) = 1 G(z_3)=1 G(z3)=1,在这种情况下,这是最完美的匹配,因此有对应 s 0 = > z 3 s_0=>z_3 s0=>z3。也就是说,直方图均衡后的图像中的每一个值为1的像素映射为直方图规定化后的图像中(相应位置上)的值为3的像素。
- s 1 = 3 s_1=3 s1=3, G ( z q ) G(z_q) G(zq)中不存在对应的3,则找最接近3的值,则为2或者4。则有 s 1 = > z 4 s_1=>z_4 s1=>z4.
- s 2 = 5 s_2=5 s2=5, G ( z 5 ) = 5 G(z_5)=5 G(z5)=5与之完美对应,则有 s 2 = > z 5 s_2=>z_5 s2=>z5.
- s 3 = 6 s_3=6 s3=6, G ( z 6 ) = 6 G(z_6)=6 G(z6)=6与之完美对应,则有 s 3 = > z 6 s_3=>z_6 s3=>z6.
由此可以得到映射关系:
表3.4
s k s_k sk —> z q z_q zq 1 —> 3 3 3 3 —> 4 5 5 5 —> 5 6 6 6 —> 6 7 7 7 —> 7 结合3.11和3.4中的映射把直方图均衡后的图像中的每个像素映射为新创建的直方图规定化图像中相应的像素。结果如下:
z q z_q zq 规定的 p z ( Z q ) p_z(Z_q) pz(Zq) 实际的 p z ( z k ) p_z(z_k) pz(zk) z 0 = 0 z_0=0 z0=0 0.00 0.00 z 1 = 1 z_1=1 z1=1 0.00 0.00 z 2 = 2 z_2=2 z2=2 0.00 0.00 z 3 = 3 z_3=3 z3=3 0.15 0.19 z 4 = 4 z_4=4 z4=4 0.20 0.25 z 5 = 5 z_5=5 z5=5 0.30 0.21 z 6 = 6 z_6=6 z6=6 0.20 0.24 z 7 = 7 z_7=7 z7=7 0.15 0.11
代码实现
直方图规定化中要注意两点:
实际操作中不会进行两次均衡化。在推导中发现,假如sk 规定化后的对应灰度是zm的话,需要满足的条件是sk的累积概率和zm的累积概率是最接近的。所以可以根据计算累计密度的差值来进行映射。
//1.传入原图和待处理的目标图
Mat src1, src2;
src1 = imread("D:/test/src1.jpg");
src2 = imread("D:/test/src2.jpg");
//2. 将原图和目标图转化为灰度图像
Mat graySrc1, graySrc2;
cvtColor(src1, graySrc1, COLOR_BGR2GRAY);
cvtColor(src2, graySrc2, COLOR_RGB2GRAY);
//3. 将图像进行均衡化处理
equalizeHist(graySrc1, graySrc1);
equalizeHist(graySrc2, graySrc2);
//4. 计算图像的直方图
/*
calcHist( const Mat* images, int nimages,
const int* channels,
InputArray mask, OutputArray hist,
int dims, const int* histSize,
const float** ranges,
bool uniform = true, bool accumulate = false );
*/
int channels = 0;
Mat dst(src2.cols, src2.rows, CV_8UC3);
//计算均衡化后的图像的直方图
int dims = 1;
int histSize = 256;
float range[] = { 0,255 };
const float *histRange[] = { range };
Mat src1Hist, src2Hist;
calcHist(&graySrc1, 1, &channels, Mat(), src1Hist, dims, &histSize, histRange);
calcHist(&graySrc2, 1, &channels, Mat(), src2Hist, dims, &histSize, histRange);
//计算图像的累计直方图
float src1_cdf[256] = { 0 };
float src2_cdf[256] = { 0 };
for (int i = 0; i < 256; i++) {
if (i == 0) {
src1_cdf[i] = src1Hist.at<float>(i);
src2_cdf[i] = src2Hist.at<float>(i);
}
else
{
src1_cdf[i] = src1_cdf[i - 1] + src1Hist.at<float>(i);
src2_cdf[i] = src2_cdf[i - 1] + src2Hist.at<float>(i);
}
}
//对图像目标进行规定化处理
// 1. 计算累计概率的差值
float diff_cdf[256][256];
for (int i = 0;i < 256;i++) {
for (int j = 0; j < 256; j++)
{
diff_cdf[i][j] = fabs(src1_cdf[i] - src2_cdf[j]);
}
}
//2. 构建灰度级映射表
Mat lut(1, 256, CV_8U);
for (int i = 0; i < 256; i++)
{
//查找源灰度级为i的映射灰度和i的累积概率差最小的规定化灰度
float min = diff_cdf[i][0];
int index = 0;
for (int j = 0; j < 256; j++) {
if (min > diff_cdf[i][j]) {
min = diff_cdf[i][j];
index = j;
}
}
lut.at<uchar>(i) = static_cast<uchar>(index);
}
LUT(graySrc2, lut, dst);
waitKey(0);
return 0;