直方图均衡化函数可以自动的改变图像直方图的分布形式,这种方式极大的简化了直方图均衡化过程中需要的操作步骤,但是该函数不能指定均衡化后的直方图分布形式。在某些特定的条件下需要将直方图映射成指定的分布形式,这种将直方图映射成指定分布形式的算法称为直方图匹配或者直方图规定化。直方图匹配与直方图均衡化相似,都是对图像的直方图分布形式进行改变,只是直方图均衡化后的图像直方图是均匀分布的,而直方图匹配后的直方图可以随意指定,即在执行直方图匹配操作时,首先要知道变换后的灰度直方图分布形式,进而确定变换函数。直方图匹配操作能够有目的的增强某个灰度区间,相比于直方图均衡化操作,该算法虽然多了一个输入,但是其变换后的结果也更灵活。

由于不同图像间像素数目可能不同,为了使两个图像直方图能够匹配,需要使用概率形式去表示每个灰度值在图像像素中所占的比例。理想状态下,经过图像直方图匹配操作后图像直方图分布形式应与目标分布一致,因此两者之间的累积概率分布也一致。累积概率为小于等于某一灰度值的像素数目占所有像素中的比例。我们用Vs表示原图像直方图的各个灰度级的累积概率,用Vz表示匹配后直方图的各个灰度级累积概率。那么确定由原图像中灰度值n映射成r的条件如式(6.8)所示。

为了更清楚的说明直方图匹配过程,在图4-7中给出了一个直方图匹配示例。示例中目标直方图灰度值2以下的概率都为0,灰度值3的累积概率为0.16,灰度值4的累积概率为0.35,原图像直方图灰度值为0时累积概率为0.19。0.19距离0.16的距离小于距离0.35的距离,因此需要将原图像中灰度值0匹配成灰度值3。同样,原图像灰度值1的累积概率为0.43,其距离目标直方图灰度值4的累积概率0.35的距离为0.08,而距离目标直方图灰度值5的累积概率0.64的距离为0.21,因此需要将原图像中灰度值1匹配成灰度值4。

这个寻找灰度值匹配的过程是直方图匹配算法的关键,在代码实现中我们可以通过构建原直方图累积概率与目标直方图累积概率之间的差值表,寻找原直方图中灰度值n的累积概率与目标直方图中所有灰度值累积概率差值的最小值,这个最小值对应的灰度值r就是n匹配后的灰度值。

在OpenCV 4中并没有提供直方图匹配的函数,需要自己根据算法实现图像直方图匹配。在代码清单4-9中给出了实现直方图匹配的示例程序。程序中待匹配的原图是一个图像整体偏暗的图像,目标直方图分配形式来自于一张较为明亮的图像,经过图像直方图匹配操作之后,提高了图像的整体亮度,图像直方图分布也更加均匀,程序中所有的结果在图4-8、图4-9给出。

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;void drawHist(Mat&hist,int type,string name){//归一化并回执直方图函数int hist_w=512;int hist_h=400;int width=2;Mat histImage=Mat::zeros(hist_h,hist_w,CV_8UC3);normalize(hist,hist,1,0,type,-1,Mat());for(int i=1;i<=hist.rows;++i){rectangle(histImage,Point(width*(i-1),hist_h-1),Point(width*i-1,hist_h-cvRound(hist_h*hist.at<float>(i-1))-1),Scalar(255,255,255),-1);}imshow(name,histImage);
}int main(){Mat img1=imread("histMatch.png");Mat img2=imread("equalLena.png");if(img1.empty()||img2.empty()){cout<<"请确认输入的图片路径是否正确"<<endl;return -1;}Mat hist1,hist2;//计算两张图像的直方图const int channels[1]={0};float inRanges[2]={0,255};const float *ranges[1]={inRanges};const int bins[1]={256};calcHist(&img1,1,channels,Mat(),hist1,1,bins,ranges);calcHist(&img2,1,channels,Mat(),hist2,1,bins,ranges);//归一化两张图像drawHist(hist1,NORM_INF,"hist1");drawHist(hist2,NORM_INF,"hist2");//计算两张图向直方图的;累计概率float hist1_cdf[256]={hist1.at<float>(0)};float hist2_cdf[256]={hist2.at<float>(0)};for(int i=1;i<256;++i){hist1_cdf[i]=hist1_cdf[i-1]+hist1.at<float>(i);hist2_cdf[i]=hist2_cdf[i-1]+hist2.at<float>(i);}//构建累积概率误差矩阵float diff_cdf[256][256];for(int i=0;i<256;++i){for(int j=0;j<256;++j){diff_cdf[i][j]=fabs(hist1_cdf[i]-hist2_cdf[i]);}}//生成LUT映射表Mat lut(1,256,CV_8U);for(int i=0;i<256;++i){//查找源灰度级为i的映射灰度//和i的累积概率差值的最小的规定花灰度float min=diff_cdf[i][0];int index=0;//寻找累积概率误差矩阵中每一行中的最小值for(int j=1;j<256;++j){if(min>diff_cdf[i][j]){min=diff_cdf[i][j];index=j;}}lut.at<uchar>(i)=(uchar)index;}Mat result,hist3;LUT(img1,lut,result);imshow("待匹配图像",img1);imshow("匹配的模板图像",img2);imshow("直方图匹配结果",result);calcHist(&result,1,channels,Mat(),hist3,1,bins,ranges);drawHist(hist3,NORM_L1,"hist3");waitKey(0);return 0;
}

C++版本OpenCv教程(二十四)直方图匹配相关推荐

  1. OpenCV学习(二十) :直方图匹配、对比:calcHist(),minMaxLoc(),compareHist()

    直方图匹配.对比:calcHist ,minMaxLoc,compareHist 1.calcHist()函数 2.归一化:normalize()函数 3.minMaxLoc()函数 4.compar ...

  2. 【Visual C++】游戏开发五十七 浅墨DirectX教程二十四 打造游戏GUI界面(二)

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/16922703 作者:毛星 ...

  3. OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()

    OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客: Harris角点检测原理详解 Harri ...

  4. OpenCV(二十)模板匹配

    目录 一.基础理论 1.作用与过程 2.原理 3.函数matchTemplate 二.代码 三.效果 参考资料 一.基础理论 1.作用与过程 所谓的模板匹配,就是在给定的图片中查找和模板最相似的区域, ...

  5. C++版本OpenCv教程(二十七)图像中添加高斯噪声

    OpenCV 4中同样没有专门为图像添加高斯噪声的函数,对照在图像中添加椒盐噪声的过程,我们可以根据需求利用能够产生随机数的函数来完成在图像中添加高斯噪声的任务.在OpenCV 4中提供了fill() ...

  6. C++版本OpenCv教程

    C++版本OpenCv教程(一)Mat-基本的图像容器 目标 我们有多种方法从现实世界获取数字图像:数码相机.扫描仪.计算机断层扫描和磁共振成像等等.在以上任何情况下,我们(人类)看到的都是图像.然而 ...

  7. 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  8. 【OpenCV新手教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  9. SAP UI5 初学者教程之二十四 - 如何使用 OData 数据模型试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 初学者教程之一:Hello World SAP UI5 初学者教程之二:SAP UI5 ...

最新文章

  1. 计算机桌面分页,电脑word文档怎么快速分页?
  2. Android N Display Size
  3. numpy基础(part14)--积分
  4. twitter集成第三方登录是窗口一直出现闪退的解决方法
  5. 我的.Net+SQLServer更新设计
  6. SpringCloud Gateway 服务网关,过滤器
  7. 自动驾驶——CenterNet(Objects as Points)的学习笔记
  8. 年底购物狂欢,移动支付安全不容忽视
  9. [java实战篇]--java的GUI(1)
  10. 分布式常见面试题整理
  11. win10系统镜像下载及在VMware虚拟机上创建虚拟机
  12. 破解电信光猫 HG6201T 超管账号密码 (C语言源代码)
  13. 豆瓣高分JAVA书籍,你都读过吗?
  14. Redis---客户端和服务端
  15. 编译原理笔记 导言和目录
  16. PLC控制模拟量输入\输出方式
  17. 基础算法-支持向量机
  18. 彭亮—Python学习
  19. MySql将两个字段查询值合并拼接
  20. 北京师范大学计算机研究生毕业去向,北京师范大学的计算机科研实力怎么样啊?我想考北..._考研_帮考网...

热门文章

  1. idea导入项目及导入项目后无目录解决
  2. 有约束多变量寻优方法——内点罚函数法
  3. Python模拟超级大乐透随机选号
  4. sync.Pool 问题argument should be pointer-like to avoid allocations (SA6002)
  5. 数据结构之数组与广义表
  6. 【chatGPT】01 数组、二维数组在不同语言中的存储方式
  7. 键盘--(微机原理实验五)
  8. 【Proteus】Proteus里的蜂鸣器的使用
  9. 开发环境配置--windows许可证过期
  10. zemax-01 衍射级次