直⽅图均衡与平台直⽅图
直⽅图均衡化(Histogram Equalization)
直⽅图均衡化处理的“中⼼思想”是把原始图像的灰度直⽅图从⽐较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直⽅图均衡化就是对图像进⾏⾮线性拉伸,重新分配图像像素值,使⼀定灰度范围内的像素数量⼤致相同。直⽅图均衡化就是把给定图像的直⽅图分布改变成“均匀”分布直⽅图分布。
直⽅图均衡化的主要过程
统计每⼀个灰度值的像素点数和所占的百分⽐
累加每⼀个灰度值的百分⽐
利⽤新的灰度值的百分⽐,重新计算每⼀个灰度值的变化
将新的的对应的关系映射到新的图像中
⼀个简单的例⼦
⾸先需要说明的是,如果你说的是⼀道完整的题⽬,则这道题⽬没有唯⼀解,因为题⽬中没有说明原始图像的灰度级数(⽐如原始图像是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
关键的代码实现
</pre><pre name="code" class="cpp"><span > </span>Mat src,dest;
gb898
<span > </span&pyTo(src);
if (src.channels() > 1)
{
cvtColor(src, src, CV_BGR2GRAY);
}
MatND hist;
const int histSize = 256;
float range[] = { 0, 255 };
const float *ranges[] = { range };
const int channels = 0;
cv::calcHist(&src, 1, &channels, Mat(), hist, 1, &histSize, ranges);
float total = src.size().width* src.size().height;
float bins[histSize] = { 0 };
float binsAcc[histSize] = { 0 };
Mat lut(1, 256, CV_8U);
vector<float> vectorBins;
vector<float> maxBins;
float sumBins = 0.0;
int countMax = 0;
float TValue = 0;
// Find the mapping table
for (int i = 0; i<histSize; i++)
{
梦见很多花float bin_val = hist.at<float>(i); // 第i灰度级上的数
bins[i] = bin_val / total;
if (bins[i] > 0)
{
vectorBins.push_back(bins[i]);
}
if (i>0)
{
binsAcc[i] =binsAcc[i-1] + bins[i];
}
el
{
孟子二章原文
binsAcc[0] = bins[0];
}
lut.at<uchar>(i) = static_cast<uchar>(cvRound(binsAcc[i] * 255));
}
利⽤openCV中均衡化的代码只要⼀句话:
防患于未然
Mat dest2;
equalizeHist(src, dest2);
imshow("equlization2", dest2);
平台直⽅图及均衡化
平台直⽅图的概念
这种⽅法是基于直⽅图均衡算法的改进算法,它是通过在直⽅图分布中设计⼀个阈值T来对原来直⽅图进⾏改造。
这种⽅法的思路是:如果原直⽅图中某些灰度级对应的值⼤于阈值T,就将该处的值设置为T。要是该处的值不⼤于T时,那么该处的值保持不变。
其中 Pt(k)是平台直⽅图, Pr(k)是原来的直⽅图
和直⽅图均衡类似,对平台直⽅图进⾏累加计算,得到累积函数
然后通过均衡化把原图灰度值改为新的灰度值
在这种⽅法中T的确定是最主要的任务,它的确定⽅法介绍如下
平台阈值的确定
关键代码实现
Mat src,dest;
Mat src,dest;蜒怎么组词
if (src.channels() > 1)
{
cvtColor(src, src, CV_BGR2GRAY);
}
MatND hist;
const int histSize = 256;
float range[] = { 0, 255 };
const float *ranges[] = { range };
const int channels = 0;
cv::calcHist(&src, 1, &channels, Mat(), hist, 1, &histSize, ranges);
float total = src.size().width* src.size().height;
float bins[histSize] = { 0 };
float binsAcc[histSize] = { 0 };
Mat lut(1, 256, CV_8U);
vector<float> vectorBins;
vector<float> maxBins;
float sumBins = 0.0;
int countMax = 0;
float TValue = 0;
// Find the mapping table
for (int i = 0; i<histSize; i++)
{
float bin_val = hist.at<float>(i); // 第i灰度级上的数
bins[i] = bin_val / total;
if (bins[i] > 0)
{
vectorBins.push_back(bins[i]);
}
}
/
/ Calculate the Meadin value by 3 sapce
for (int i = 1; i < vectorBins.size() - 1; i++)
{
if (vectorBins[i] < vectorBins[i - 1] && vectorBins[i - 1] < vectorBins[i + 1] || vectorBins[i] > vectorBins[i - 1] && vectorBins[i - 1] > vectorBins[i + 1])
{
vectorBins[i] = vectorBins[i - 1];
}
el if (vectorBins[i] < vectorBins[i + 1] && vectorBins[i + 1] < vectorBins[i - 1] || vectorBins[i] > vectorBins[i + 1] && vectorBins[i + 1] > vectorBins[i - 1]) {
vectorBins[i] = vectorBins[i + 1];
}
}
// Calculate the max peak value
for (int i = 1; i < vectorBins.size() - 1; i++)
{
if (vectorBins[i] - vectorBins[i - 1] >= 0 && vectorBins[i+1] - vectorBins[i] <= 0)
{
maxBins.push_back(vectorBins[i]);
sumBins += vectorBins[i];
countMax++;
}
}维保方案
TValue = sumBins / countMax;