⽤C++写个函数实现灰度图均衡化以及⽤C++显⽰灰度直⽅图⽤C++写个函数实现灰度图均衡化以及⽤C++显⽰灰度直⽅图。
1、灰度图均衡化
直⽅图均衡化在图像增强⽅⾯有着很重要的应⽤。⼀些拍摄得到的图⽚,我们从其直⽅图可以看出,它的分布是集中于某些灰度区间,这导致⼈在视觉上感觉这张图的对⽐度不⾼。所以,对于这类图像,我们可以通过直⽅图均衡技术,将图像的灰度分布变得较为均匀,从⽽使得图像对⽐度增⼤,视觉效果更佳。
直⽅图均衡化的代码实现有以下⼏个步骤:
1. 遍历全图,先统计每个灰度级下的像素点个数(为此我们开辟了256⼤⼩的数组);
2. 计算每个灰度级的像素点占总像素的点的⽐例;
3. 按照第⼆步求出的⽐例重新计算每个灰度级下的新的灰度值,即均衡化;
4. 依照新的灰度值表遍历更新图像的灰度值。
实现代码:
int gray[256] = { 0 };  //记录每个灰度级别下的像素个数
double gray_prob[256] = { 0 };  //记录灰度分布密度
double gray_distribution[256] = { 0 };  //记录累计密度
int gray_equal[256] = { 0 };  //均衡化后的灰度值
int gray_sum = 0;  //像素总数
Mat equalize_hist(Mat& input)
{
Mat output = input.clone();
gray_sum = ls * ws;
//统计每个灰度下的像素个数
for (int i = 0; i < ws; i++)
{
uchar* p = input.ptr<uchar>(i);
for (int j = 0; j < ls; j++)
{
int vaule = p[j];
gray[vaule]++;
}
}
//统计灰度频率
for (int i = 0; i < 256; i++)
{
gray_prob[i] = ((double)gray[i] / gray_sum);
}
//计算累计密度
gray_distribution[0] = gray_prob[0];
for (int i = 1; i < 256; i++)
{
gray_distribution[i] = gray_distribution[i-1] +gray_prob[i];
}
//重新计算均衡化后的灰度值,四舍五⼊。参考公式:(N-1)*T+0.5    for (int i = 0; i < 256; i++)
{
gray_equal[i] = (uchar)(255 * gray_distribution[i] + 0.5);
}
//直⽅图均衡化,更新原图每个点的像素值
for (int i = 0; i < ws; i++)
{
uchar* p = output.ptr<uchar>(i);
for (int j = 0; j < ls; j++)
{
p[j] = gray_equal[p[j]];
}
}
return output;
}
2、显⽰灰度直⽅图
void show_histogram(Mat& img)
{
//为计算直⽅图配置变量
//⾸先是需要计算的图像的通道,就是需要计算图像的哪个通道(bgr空间需要确定计算 b或g货r空间)
int channels = 0;
//然后是配置输出的结果存储的空间,⽤MatND类型来存储结果
MatND dstHist;
//接下来是直⽅图的每⼀个维度的柱条的数⽬(就是将数值分组,共有多少组)
int histSize[] = { 256 };      //如果这⾥写成int histSize = 256;  那么下⾯调⽤计算直⽅图的函数的时候,该变量需要写 &histSize
//最后是确定每个维度的取值范围,就是横坐标的总数
//⾸先得定义⼀个变量⽤来存储单个维度的数值的取值范围
float midRanges[] = { 0, 256 };
const float *ranges[] = { midRanges };
calcHist(&img, 1, &channels, Mat(), dstHist, 1, histSize, ranges, true, false);
//calcHist  函数调⽤结束后,dstHist变量中将储存了直⽅图的信息⽤dstHist的模版函数 at<Type>(i)得到第i个柱条的值
//at<Type>(i, j)得到第i个并且第j个柱条的值
//开始直观的显⽰直⽅图——绘制直⽅图
//⾸先先创建⼀个⿊底的图像,为了可以显⽰彩⾊,所以该绘制图像是⼀个8位的3通道图像
Mat drawImage = Mat::zeros(Size(256, 256), CV_8UC3);
/
/因为任何⼀个图像的某个像素的总个数,都有可能会有很多,会超出所定义的图像的尺⼨,针对这种情况,先对个数进⾏范围的限制    //先⽤ minMaxLoc函数来得到计算直⽅图后的像素的最⼤个数
double g_dHistMaxValue;
minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0);
//将像素的个数整合到图像的最⼤范围内
//遍历直⽅图得到的数据
for (int i = 0; i < 256; i++)
{
int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue);
line(drawImage, Point(i, ws - 1), Point(i, ws - 1 - value), Scalar(255, 255, 255));
}
imshow("【原图直⽅图】", drawImage);
}
⼏个关键函数的解释:
void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims,
const int* histSize, const float** ranges, booluniform=true, bool accumulate=false )
计算直⽅图,统计各灰度的像素个数,其输出为多维矩阵
const Mat* images:
为输⼊图像的指针。
int nimages:
要计算直⽅图的图像的个数。此函数可以为多图像求直⽅图,我们通常情况下都只作⽤于单⼀图像,所以通常nimages=1。
const int* channels:
图像的通道,它是⼀个数组,如果是灰度图像则channels[1]={0};如果是彩⾊图像则channels[3]={0,1,2};如果是只是求彩⾊图像第2个通道的直⽅图,则channels[1]={1};
IuputArray mask:
是⼀个遮罩图像⽤于确定哪些点参与计算,实际应⽤中是个很好的参数,默认情况我们都设置为⼀个空图像,即:Mat()。
OutArray hist:
计算得到的直⽅图
int dims:
得到的直⽅图的维数,灰度图像为1维,彩⾊图像为3维。
const int* histSize:
直⽅图横坐标的区间数。如果是10,则它会横坐标分为10份,然后统计每个区间的像素点总和。
const float** ranges:
这是⼀个⼆维数组,⽤来指出每个区间的范围。后⾯两个参数都有默认值,uniform参数表明直⽅图是否等距,最后⼀个参数与多图像下直⽅图的显⽰与存储有关。
void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0,
Point* maxLoc=0, InputArray mask=noArray())
出矩阵中最⼤和最⼩的值以及他们的坐标
src – Source single-channel array.
单通道数组
minVal – Pointer to the returned minimum value. NULL is used if not required.
指向最⼩值的指针
maxVal – Pointer to the returned maximum value. NULL is used if not required.
指向最⼤值的指针
minLoc – Pointer to the returned minimum location (in 2D case). NULL is used if not required.
最⼩值的⼆维坐标
maxLoc – Pointer to the returned maximum location (in 2D case). NULL is used if not required.
最⼤值得⼆维坐标
mask – Optional mask used to select a sub-array.
掩码
void cvLine( CvArr* img,CvPoint pt1, CvPoint pt2, CvScalar color,int thickness=1,
int line_type=8, int shift=0 );
第⼀个参数img:要划的线所在的图像;
第⼆个参数pt1:直线起点
第⼆个参数pt2:直线终点
第三个参数color:直线的颜⾊ e.g:Scalor(0,0,255)
第四个参数thickness=1:线条粗细
round函数有几个参数第五个参数line_type=8,
8 (or 0) - 8-connected line(8邻接)连接 线。
4 - 4-connected line(4邻接)连接线。
CV_AA - antialiased 线条。
第六个参数:坐标点的⼩数点位数。
static_cast

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。