直方图均衡 视觉显著_直方图均衡化C++实现

直方图均衡化是一种图像增强技术,通过重新分配灰度值,使图像对比度增大,视觉效果更佳。本文介绍了直方图均衡化的步骤,并提供了C++代码实现,包括统计灰度分布、计算累计密度、重新分配灰度值,以及如何绘制灰度直方图。测试结果显示,均衡化后图像对比度显著增加。
摘要由CSDN通过智能技术生成

直方图均衡化在图像增强方面有着很重要的应用。一些拍摄得到的图片,我们从其直方图可以看出,它的分布是集中于某些灰度区间,这导致人在视觉上感觉这张图的对比度不高。所以,对于这类图像,我们可以通过直方图均衡技术,将图像的灰度分布变得较为均匀,从而使得图像对比度增大,视觉效果更佳。

直方图均衡化的代码实现有以下几个步骤:

遍历全图,先统计每个灰度级下的像素点个数(为此我们开辟了256大小的数组);

计算每个灰度级的像素点占总像素的点的比例;

按照第二步求出的比例重新计算每个灰度级下的新的灰度值,即均衡化;

依照新的灰度值表遍历更新图像的灰度值。

实现代码:

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 = input.cols * input.rows;

//统计每个灰度下的像素个数

for (int i = 0; i < input.rows; i++)

{

uchar* p = input.ptr(i);

for (int j = 0; j < input.cols; 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 < output.rows; i++)

{

uchar* p = output.ptr(i);

for (int j = 0; j < output.cols; j++)

{

p[j] = gray_equal[p[j]];

}

}

return output;

}

这里还分享一段代码,就是如何画灰度直方图

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(i)得到第i个柱条的值

//at(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(i) * 256 * 0.9 / g_dHistMaxValue);

line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(255, 255, 255));

}

imshow("【原图直方图】", drawImage);

}

测试图片以及其灰度直方图:

直方图均衡化后,图像对比度显著增加,图像增强效果明显。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值