博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
直方图均衡化C++实现
阅读量:6213 次
发布时间:2019-06-21

本文共 2863 字,大约阅读时间需要 9 分钟。

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

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

  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 = 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);}

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

1093303-20171101161223435-56320431.png

1093303-20171101161236795-1730411258.png

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

1093303-20171101161255982-547099141.png

1093303-20171101161310701-1597481131.png

转载地址:http://yidja.baihongyu.com/

你可能感兴趣的文章
CSS布局 -- 左右定宽,中间自适应
查看>>
shiro密码的比对,密码的MD5加密,MD5盐值加密,多个Relme
查看>>
什么是句柄(HANDLE)
查看>>
RT-thread内核之IO设备管理系统
查看>>
测试用例设计方法
查看>>
HRBUST 1211 火车上的人数【数论解方程/模拟之枚举+递推】
查看>>
shouldChangeCharactersInRange
查看>>
HDU 2717 Catch That Cow (BFS)
查看>>
Linux coredump
查看>>
第二次结对编程作业——毕设导师智能匹配
查看>>
linux中MTDflash设备驱动大概
查看>>
Entity Fr“.NET技术”amework 4.1 Code First 学习之路(二)
查看>>
CentOS7防火墙设置--iptables
查看>>
Recordset的Open函数的参数LockType
查看>>
SharePoint 2010 文档管理之过期归档工具
查看>>
第11章代码详解
查看>>
树莓派配置小记1:系统篇
查看>>
第三次作业——吴有恒
查看>>
Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结(转)
查看>>
Ubuntu16下Hadoop安装
查看>>