另外:
如:I=[0,05,05,1,1,1]变换后应为[06,05,05,1,1,1]
请问你这里是什么变换?是06还是016啊?
不好意思啊,我之前的解答错了,现更正如下:
正好我前几天学习了数字图像处理的直方图内容,你的这个I有问题,I的各个值相加应该等于1,参见《图像处理与分析》(清华大学出版社)上册第78页。我现在把直方图均衡化的具体步骤写出来。
第一步,由计算原始直方图I,I的和是概率1
第二步,计算累计直方图。明白什么意思吗?举个例子吧:比如I=[019,025,021,016,008,006,003,002]变成[019,044,065,081,089,095,098,1]
第三步,取整。就是用7(8-1)去乘以累计直方图的各个值,然后将得到的值四舍五入,映射到相应的灰度区域。比如0197=1,0447=3,0657=5,后面依次是6,6,7,7,7
第四步:0区域没有,0
1区域为019
2区域为0
3区域为044-019=025
4区域为0
5区域为065-044=021
6区域为089-065=024
7区域为1-089=011
即变换后为[0,019,0,025,0,021,024,011]!
你的这个原始直方图I似乎不合规矩,我没办法做!C实现的,matlab里面就更简单了
//LPSTR lpDIBBits - 指向源DIB图像指针
//LONG lWidth - 源图像宽度(象素数)
//LONG lHeight - 源图像高度(象素数)
BOOL WINAPI InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
unsigned char lpSrc;
// 临时变量
LONG lTemp;
// 循环变量
LONG i;
LONG j;
// 灰度映射表
BYTE bMap[256];
// 灰度映射表
LONG lCount[256];
// 图像每行的字节数
LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth 8);
// 重置计数为0
for (i = 0; i < 256; i ++)
{
// 清零
lCount[i] = 0;
}
// 计算各个灰度值的计数
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
lpSrc = (unsigned char )lpDIBBits + lLineBytes i + j;
// 计数加1
lCount[(lpSrc)]++;
}
}
// 计算灰度映射表
for (i = 0; i < 256; i++)
{
// 初始为0
lTemp = 0;
for (j = 0; j <= i ; j++)
{
lTemp += lCount[j];
}
// 计算对应的新灰度值
bMap[i] = (BYTE) (lTemp 255 / lHeight / lWidth);
}
// 每行
for(i = 0; i < lHeight; i++)
{
// 每列
for(j = 0; j < lWidth; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char)lpDIBBits + lLineBytes (lHeight - 1 - i) + j;
// 计算新的灰度值
lpSrc = bMap[lpSrc];
}
}
// 返回
return TRUE;
}%直接读图像abcjpg,读到tuu中
%graydis是原始直方图各灰度级像素个数
%原始直方图graydispro,利用原始直方图计算原始累计直方图graydispro
%t[ ]计算和原始灰度对应的新的灰度t[ ],建立映射关系,t坐标代表原始的灰度,t[ ]代表对应原始坐标的新坐标
%new_graydis是统计新直方图各灰度级像素个数
%计算新的灰度直方图new_graydispro,利用新的直方图计算新的累计直方图new_graydispro
%计算直方图均衡后的新图new_tu
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
tuu=imread('abcjpg'); %读入
tu=rgb2gray(tuu); %将彩色转换为灰度图
graydis=zeros(1,256); %设置矩阵大小
graydispro=zeros(1,256);
new_graydis=zeros(1,256);
new_graydispro=zeros(1,256);
[h w]=size(tu);
new_tu=zeros(h,w);
%计算原始直方图各灰度级像素个数graydis
for x=1:h
for y=1:w
graydis(1,tu(x,y))=graydis(1,tu(x,y))+1;
end
end
%计算原始直方图graydispro
graydispro=graydis/sum(graydis);
subplot(1,2,1);
plot(graydispro);
title('灰度直方图');
xlabel('灰度值');ylabel('像素的概率密度');
%计算原始累计直方图
for i=2:256
graydispro(1,i)=graydispro(1,i)+graydispro(1,i-1);
end
%计算和原始灰度对应的新的灰度t[],建立映射关系
for i=1:256
t(1,i)=floor(254graydispro(1,i)+05);
end
%统计新直方图各灰度级像素个数new_graydis
for i=1:256
new_graydis(1,t(1,i)+1)=new_graydis(1,t(1,i)+1)+graydis(1,i);
end
%计算新的灰度直方图new_graydispro
new_graydispro=new_graydis/sum(new_graydis);
subplot(1,2,2);
plot(new_graydispro);
title('均衡化后的灰度直方图');
xlabel('灰度值');ylabel('像素的概率密度');
%计算直方图均衡后的新图new_tu
for x=1:h
for y=1:w
new_tu(x,y)=t(1,tu(x,y));
end
end
figure,imshow(tu,[]);
title('原图');
figure,imshow(new_tu,[]);
title('直方图均衡化后的图');
1、首先是图像的读入与double精度化。
2、将图像对比度增大的图像、直方图和将其均衡化的图像、直方图。
3、将图像对比度减小的图像、直方图和将其均衡化的图像、直方图。
4、将图像线性增加亮度的图像、直方图和将其均衡化的图像、直方图。
5、将图像线性减小亮度的图像、直方图和将其均衡化的图像、直方图。
6、完成后看效果,可以看出,线性变换后的图像的均衡化结果基本相同。
首先需要说明的是,如果你说的是一道完整的题目,则这道题目没有唯一解,因为题目中没有说明原始图像的灰度级数(比如原始图像是16个灰度级的,或者是32个灰度级的,等等)。为了给你提供一个解题思路,现在人为假设原始图像是16个灰度级的,其它灰度级的解法类似。1、图像的灰度直方图求法为:
(1)先计算图像中各个灰度级的出现频率,用h(i)表示灰度级i的出现频率,其值等于灰度级出现次数/图像像素个数:
h(0)=2/16
h(1)=1/16
h(2)=3/16
h(3)=2/16
h(4)=0/16
h(5)=1/16
h(6)=4/16
h(7)=1/16
h(8)=1/16
h(9)=1/16
h(10)=h(11)=h(12)=h(13)=h(14)=h(15)=0/16。
然后以灰度级i为横轴,出现频率h(i)为纵轴即可绘制出图像对应的直方图。
(2)图像进行直方图均衡化处理的过程为:
先计算累积分布,用r(i)表示灰度级i的累积分布:
r(0)=h(0)=2/16
r(1)=r(0)+h(1)=2/16+1/16=3/16
r(2)=r(1)+h(2)=3/16+3/16=6/16
r(3)=r(2)+h(3)=6/16+2/16=8/16
r(4)=r(3)+h(4)=8/16+0/16=8/16
r(5)=r(4)+h(5)=8/16+1/16=9/16
r(6)=r(5)+h(6)=9/16+4/16=13/16
r(7)=r(6)+h(7)=13/16+1/16=14/16
r(8)=r(7)+h(8)=14/16+1/16=15/16
r(9)=r(8)+h(9)=15/16+1/16=16/16=1
r(10)=r(11)=r(12)=r(13)=r(14)=r(15)=1
将累积分布进行量化(量化时需要用到原始图像的灰度级数,这也是为什么前面需要说明的原因),量化后的灰度级用rq(i)表示,量化公式为rq(i)=ROUND(r(i)15),(说明:量化公式中的15等于原始图像灰度级数减1),可得:
rq(0)=ROUND(r(0)15)=2
rq(1)=ROUND(r(1)15)=3
rq(2)=ROUND(r(2)15)=6
rq(3)=ROUND(r(3)15)=8
rq(4)=ROUND(r(4)15)=8
rq(5)=ROUND(r(5)15)=8
rq(6)=ROUND(r(6)15)=12
rq(7)=ROUND(r(7)15)=13
rq(8)=ROUND(r(8)15)=14
rq(9)=ROUND(r(9)15)=15
rq(10)=ROUND(r(10)15)=15
rq(11)=ROUND(r(11)15)=15
rq(12)=ROUND(r(12)15)=15
rq(13)=ROUND(r(13)15)=15
rq(14)=ROUND(r(14)15)=15
rq(15)=ROUND(r(15)15)=15
因此,原始图像中的灰度级和均化后图像中的灰度级之间的对应关系为:
0->2
1->3
2->6
3->8
4->8
5->8
6->12
7->13
8->14
9->15
10->15
11->15
12->15
13->15
14->15
15->15
将原始图像中对应的灰度值按照上述对应关系替换成相应的灰度值,即可得到均化图像,结果如下:
3 8 13 8
6 12 2 12
14 6 12 8
15 6 12 2
(在电脑上直接做的,仅供参考。ROUND()表示四舍五入。)根据 维基百科 上的定义, 直方图均衡(Histogram Equalization)是图像处理领域中利用直方图对对比度进行调整的方法
顾名思义, 直方图均衡是将直方图的分布(概率密度)调整为均匀分布
根据信息论, 信息的熵越大, 包含的信息也就越多, 熵的计算公式如下:
只有当 均匀分布时, 熵的值最大 对应到图像上, 当图像直方图均匀分布时, 图像对比度最大 如下图所示:
蓝色为原始图像直方图, 绿色为均衡后直方图, 对应的处理后的图像为:
可以看到, 直方图均衡处理后, 图像变得更加清晰了
知道了为什么, 就要知道怎么做 一般直方图均值有以下几个步骤:
式中, , 分别为图像的高和宽, 表示灰度值为 的像素的个数, 为变换后的灰度值, 为映射函数, 计算过程使用了累计直方图
知道怎么做了, 就要知道为什么可以这么做 这里解释下为啥可以这么做, 即公式(3)是怎么得到的
设原始直方图分为为
均衡化后的直方图分布为
映射函数为
这里映射函数必须为单调递增函数, 满足:
即对应区域间内像素点的总数是一样的, 如下图红色区域所示:
将公式(4)代入公式(5), 则有:
因而, 可以得到:
对应的离散形式为公式(3)
直方图均衡过度的强调了灰度个数的重要性, 对数量多的灰度过度的进行了增强, 而图像中, 比例比不是很多的灰度往往更重要, 因而改进的方向就是减少数量多的灰度的影响, 我这里想到的有 3 种方法:
这3种方法的映射关系曲线如下所示:
从图中可以看到, 原始的直方图均衡后图像最亮, 如下所示为几种方法的结果对比, 依次为原图, 原始直方图, 改进0, 改进1, 改进2:
可以看到, 直方图可以改善图像整体的质量, 但对于某些局部图像, 则由于直方图的性质导致过亮或者过暗
这里总结下直方图均衡化的优缺点:
想象一下,如果一副图像中的大多是像素点的像素值都集中在一个像素值范围之内会怎样呢?例如,如果一幅整体很亮,那所有的像素值应该都会很高。但是一副高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向拉伸(如下图),这就是直方图均衡化要做的事情。通常情况下,这种 *** 作会改善图像的对比度。
这种方法通常用来增加许多图像的全局 对比度 ,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法, 亮度 可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来 X光 图像中更好的 骨骼 结构显示以及曝光过度或者曝光不足 照片 中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是 可逆 *** 作,如果已知均衡化 函数 ,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景 噪声 的对比度并且降低有用 信号 的对比度。
我们先来看看相应的直方图和累积直方图,然后使用 OpenCV 进行直方图均衡化。
我们可以看出来直方图大部分在灰度值较高的部分,而且分布很集中。而我们希望直方图的分布比较分散,能够涵盖整个 x 轴。所以,我们就需要一个变换函数帮助我们把现在的直方图映射到一个广泛分布的直方图中,这就是直方图均衡化。
限制对比度自适应性直方图均衡化 CLAHE
在上边做的直方图均衡化会改变整个图像的对比度,但是在很多情况下,这样做的效果并不好。的确在进行完直方图均衡化之后,背景的对比度被改变了。但是你再对比一下两幅图像中雕像的面图,由于太亮我们丢失了很多信息。
原理:
为了解决这个问题,我们需要使用自适应的直方图均衡化 CLAHE (Contrast Limited Adaptive Histogram Equalization)。这种情况下,整幅图像会被分成很多小块,这些小块被称为“tiles”(在 OpenCV 中 tileGridSize默认是 8x8),然后再对每一个小块分别进行直方图均衡化(跟前面类似)。所以在每一个的区域中,直方图会集中在某一个小的区域中(除非有噪声干扰)。如果有噪声的话,噪声会被放大。为了避免这种情况的出现,要使用对比度限制。
CLAHE中,每一个像素邻域都要进行对比度限制,从而得到对应的变换函数,被用来降低AHE中噪声的增强,这主要是通过限制AHE中的对比度增强来实现的。像素周围邻域噪声的增强主要是由变换函数的斜率造成的,由于像素邻域的噪声与邻域的CDF成正比,因此也与邻域直方图在该中心像素位置的值成正比,CLAHE之所以能够限制对比度,是因为它在计算邻域的CDF之前在指定阈值处对直方图进行了修剪,如下图所示,这一做法不仅限制了CDF的斜率,也限制了变换函数的斜率,其中对直方图进行切割所使用的阈值,被称作修剪限制度(clip limit),这个参数不仅依赖于直方图的归一化,而且依赖于像素邻域的size大小,通常设为3到4之间。
对于每个小块来说,如果直方图中的 bin 超过对比度的上限的话,就把其中的像素点均匀分散到其他 bins 中,然后在进行直方图均衡化。最后,为了去除每一个小块之间“人造的”(由于算法造成)边界,再使用双线性差值,与原图做图层滤色混合 *** 作(可选)。
实现:
参考文献:
网址: 直方图均衡化
Adaptive_histogram_equalization
书籍:《数字图像处理》《OpenCV-Python 中文教程》
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)