作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

实现原理

通过图像数据的直方图,可以快速判断图像的亮度和质量。而直方图均衡化就是通过图像变换使得直方图均匀分布,起到对比度增强的效果。在图像处理的课本中,针对离散形式的图像数据,最常用的一种方法就是累计概率分布。首先统计0-255灰度值所占像素个数;再计算出像素个数与总像素的比,表示为出现的概率;从0开始进行累计概率分布,即从0慢慢累加各层概率值直到1;则均衡化图像的灰度值=原灰度值所对应的累计概率*255。

基于上述原理,我自定义了一个简单的直方图均衡化函数EqualizeHist,并定义了直方图简易绘制函数drawHistImg,用来作直观对比。

功能函数代码

// 直方图均衡化
cv::Mat EqualizeHist(cv::Mat src)
{cv::Mat h = cv::Mat::zeros(1, 256, CV_32FC1);cv::Mat hs = cv::Mat::zeros(1, 256, CV_32FC1);cv::Mat hp = cv::Mat::zeros(1, 256, CV_32FC1);cv::Mat result = cv::Mat::zeros(src.size(), src.type());int sum = 0;for (int i = 0; i < src.rows; ++i){for (int j = 0; j < src.cols; ++j){h.at<float>(0, src.at <uchar>(i, j))++;sum++;}}for (int i = 0; i < 256; ++i){hs.at<float>(0, i) = h.at<float>(0, i) / sum;if (i == 0){hp.at<float>(0, i) = hs.at<float>(0, i);}else {hp.at<float>(0, i) = hp.at<float>(0, i - 1) + hs.at<float>(0, i);}}for (int i = 0; i < src.rows; ++i){for (int j = 0; j < src.cols; ++j){result.at <uchar>(i, j) = uchar(round(255 * hp.at<float>(0, src.at<uchar>(i, j))));}}return result;
}// 绘制简易直方图
cv::Mat drawHistImg(cv::Mat &src)
{cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);for (int i = 0; i < src.rows; ++i){for (int j = 0; j < src.cols; ++j){hist.at<float>(0, src.at <uchar>(i, j))++;}}cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);const int bins = 255;double maxValue;cv::Point2i maxLoc;cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);int scale = 4;int histHeight = 540;for (int i = 0; i < bins; i++){float binValue = (hist.at<float>(i));int height = cvRound(binValue * histHeight / maxValue);cv::rectangle(histImage, cv::Point(i * scale, histHeight),cv::Point((i + 1) * scale-1, histHeight - height), cv::Scalar(255), -1);}return histImage;
}

函数原型

官方OpenCV库中也有自带的直方图均衡化函数:

void equalizeHist( InputArray src, OutputArray dst );

参数说明

  1. InputArray类型的src,输入图像,如Mat类型。
  2. OutputArray类型的dst,输出图像。

C++测试代码

#include <iostream>
#include <time.h>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;cv::Mat EqualizeHist(cv::Mat src);
cv::Mat drawHistImg(cv::Mat &hist);int main()
{cv::Mat src = imread("test.jpg",0);cv::Mat src1 = imread("test.jpg");clock_t start1, start2, end1,end2;// 绘制原图直方图cv::Mat hI = drawHistImg(src);// 自定义直方图均衡化start1 = clock();cv::Mat result1 = EqualizeHist(src);end1 = clock();double dif1 = (end1 - start1) / CLOCKS_PER_SEC;cout << "time1:" << dif1 << endl;// 绘制均衡化后直方图cv::Mat hrI = drawHistImg(result1);// 官方直方图均衡化函数start2 = clock();cv::Mat result2;equalizeHist(src, result2);end2 = clock();double dif2 = (end2 - start2) / CLOCKS_PER_SEC;cout << "time2:" << dif2 << endl;// 绘制均衡化后直方图cv::Mat hr2I = drawHistImg(result2);// 彩色直方图均衡化,三通道分别作均衡再合并vector<cv::Mat> rgb,rgb_;cv::Mat r, g, b;cv::split(src1, rgb);equalizeHist(rgb[0], b);equalizeHist(rgb[1], g);equalizeHist(rgb[2], r);rgb_.push_back(b);rgb_.push_back(g);rgb_.push_back(r);cv::Mat src1_;cv::merge(rgb_, src1_);imshow("original", src1);imshow("result", src1_);waitKey(0);return 0;
}// 直方图均衡化
cv::Mat EqualizeHist(cv::Mat src)
{cv::Mat h = cv::Mat::zeros(1, 256, CV_32FC1);cv::Mat hs = cv::Mat::zeros(1, 256, CV_32FC1);cv::Mat hp = cv::Mat::zeros(1, 256, CV_32FC1);cv::Mat result = cv::Mat::zeros(src.size(), src.type());int sum = 0;for (int i = 0; i < src.rows; ++i){for (int j = 0; j < src.cols; ++j){h.at<float>(0, src.at <uchar>(i, j))++;sum++;}}for (int i = 0; i < 256; ++i){hs.at<float>(0, i) = h.at<float>(0, i) / sum;if (i == 0){hp.at<float>(0, i) = hs.at<float>(0, i);}else {hp.at<float>(0, i) = hp.at<float>(0, i - 1) + hs.at<float>(0, i);}}for (int i = 0; i < src.rows; ++i){for (int j = 0; j < src.cols; ++j){result.at <uchar>(i, j) = uchar(round(255 * hp.at<float>(0, src.at<uchar>(i, j))));}}return result;
}// 绘制简易直方图
cv::Mat drawHistImg(cv::Mat &src)
{cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);for (int i = 0; i < src.rows; ++i){for (int j = 0; j < src.cols; ++j){hist.at<float>(0, src.at <uchar>(i, j))++;}}cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);const int bins = 255;double maxValue;cv::Point2i maxLoc;cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);int scale = 4;int histHeight = 540;for (int i = 0; i < bins; i++){float binValue = (hist.at<float>(i));int height = cvRound(binValue * histHeight / maxValue);cv::rectangle(histImage, cv::Point(i * scale, histHeight),cv::Point((i + 1) * scale-1, histHeight - height), cv::Scalar(255), -1);}return histImage;
}

测试效果

图1 灰度原图

其直方图如下:

图2 直方图

图3 均衡化后灰度图

两个函数运行时间都在0.001s以下,其均衡化后直方图略有差异,但都实现了均衡效果。

自定义函数:

图4 自定义函数均衡化后直方图

官方函数:

图5 官方函数均衡化后直方图

对彩色图的三通道分别进行直方图均衡化,实现彩色均衡效果:

图6 彩色原图

图7 彩色均衡化效果

如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~

如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

OpenCV-实现直方图均衡化(对比cv::equalizeHist)相关推荐

  1. opencv基础---直方图均衡化(原理equalizeHist)

    直方图均衡化的作用是图像增强. 有两个问题比较难懂,一是为什么要选用累积分布函数,二是为什么使用累积分布函数处理后像素值会均匀分布. 第一个问题.均衡化过程中,必须要保证两个条件:①像素无论怎么映射, ...

  2. OpenCV中直方图均衡化

    OpenCV中直方图均衡化 首先知道直方图是个什么鬼?在一幅图像中,直方图所体现的是每个像素值在所有的像素中所占的比例:例值为127的像素点的个数/图像总的像素点的个数\color{#f00}值为12 ...

  3. Python+OpenCV:直方图均衡化(Histogram Equalization)

    Python+OpenCV:直方图均衡化(Histogram Equalization) ####################################################### ...

  4. python opencv 直方图均衡_深入理解OpenCV+Python直方图均衡化

    原标题:深入理解OpenCV+Python直方图均衡化 正文 直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法. 基本思想:把原始图的直方图变换为均匀分 布的形式,这样就增加了像素灰度 ...

  5. 【OpenCV 】直方图均衡化,直方图计算,直方图对比

    目录 1.直方图均衡化¶ 1.1 原理 1.2 直方图均衡化 1.3 直方图均衡化原理 1.4 代码实例 1.5 运行效果 2. 直方图计算¶ 2.1 目标 2.2 直方图 2.3 代码实例 2.4 ...

  6. OpenCv:直方图均衡化(HE),自适应直方图均衡化(AHE),限制对比度自适应直方图均衡化(CLAHE)

    总结了使用Python OpenCv处理图像直方图均衡化(HE),自适应直方图均衡化(AHE),限制对比度自适应直方图均衡化(CLAHE)的方法. 目录 直方图均衡化(HE) 自适应直方图均衡化(AH ...

  7. Python 图像处理OpenCV:直方图均衡化(笔记)

    进行了直方图的均衡化和限制对比度的直方图均衡化. 代码如下: import cv2 as cv import matplotlib.pyplot as plt # 直方图均衡化 def img_his ...

  8. opencv中直方图均衡化的小例子及详细注释

    2019独角兽企业重金招聘Python工程师标准>>> #include <cv.h> #include <highgui.h>#include <io ...

  9. openCV中直方图均衡化算法的理解

    直方图均衡化就是调整灰度直方图的分布,即将原图中的灰度值映射为一个新的值.映射的结果直观表现是灰度图的分布变得均匀,从0到255都有分布,不像原图那样集中.图像上的表现就是对比度变大,亮的更亮,暗的更 ...

最新文章

  1. 春运渡劫!Python给我抢回家的火车票
  2. 无需额外数据、Tricks、架构调整,CMU开源首个将ResNet50精度提升至80%+新方法
  3. Unity3D 2D游戏中寻径算法的一些解决思路
  4. JSTL标签显示分页
  5. 交互 点击变色_明年旗舰机必将标配!电致变色技术解读
  6. 庖丁解牛TLD(二)——初始化工作(为算法的准备)
  7. 大话软件开发与开车的共同点
  8. 如何用Chrome读懂网站监测Cookie
  9. Linux下如何手动搭建论坛?
  10. 编译器--简单数学表达式计算器(一)
  11. MAC编译freetype
  12. [转载]软件测试学习资料
  13. dijkstra最短路径算法视频_最短路径之Dijkstra算法详细讲解
  14. ilo远程给服务器装系统,惠普hp服务器通过iLO接口远程安装操作系统
  15. 又一名程序员被判刑了!百度92年程序员改当“审核员”,编写脚本违规“开绿灯”
  16. 手绘风格的 JS 图表库:Chart.xkcd
  17. python getattrribute_Python学习——面向对象高级之反射
  18. 程序龙的密码(递归算法)
  19. 自控力读书笔记 第八章 传染:为什么意志力会传染?
  20. 脑裂是什么,zk是如何解决脑裂问题的

热门文章

  1. TOJ 2353: Billiard
  2. DOM 提供了一些滚动页面设置指定可见
  3. 因VPU预留内存太小造成的视频播放太卡
  4. 8-1 数据库分库分表的几种方式
  5. keil5怎么接入汇编_keil中如何让汇编语言生成hex文件
  6. python如何提高性能_python – 如何在这个短代码中提高numpy性能...
  7. gittrack_Git 分支跟踪详解(remote branch tracking)
  8. python网络爬图_Python爬虫爬图片需要什么
  9. css放服务器ttf文件格式,CSS如何实现读取服务器字体
  10. comsol分析时总位移代表什么_通过仿真分析球形盖的变形问题