【OpenCV 】直方图均衡化,直方图计算,直方图对比
目录
1.直方图均衡化¶
1.1 原理
1.2 直方图均衡化
1.3 直方图均衡化原理
1.4 代码实例
1.5 运行效果
2. 直方图计算¶
2.1 目标
2.2 直方图
2.3 代码实例
2.4 运行结果
3 直方图对比¶
3.1 目标
3.2 原理
3.3 代码
3.4 运行结果
1.直方图均衡化¶
什么是图像的直方图和为什么图像的直方图很有用
用OpenCV函数 equalizeHist 对图像进行直方图均衡化
1.1 原理
直方图是图像中像素强度分布的图形表达方式.
它统计了每一个强度值所具有的像素个数.
1.2 直方图均衡化
直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法.
说得更清楚一些, 以上面的直方图为例, 你可以看到像素主要集中在中间的一些强度值上. 直方图均衡化要做的就是 拉伸 这个范围. 见下面左图: 绿圈圈出了 少有像素分布其上的 强度值. 对其应用均衡化后, 得到了中间图所示的直方图. 均衡化的图像见下面右图.
1.3 直方图均衡化原理
OpenCV 【九】——calcHist ——图像直方图统计
1.4 代码实例
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
/** @function main */
int main( int argc, char** argv )
{Mat src, dst;
char* source_window = "Source image";char* equalized_window = "Equalized Image";
/// 加载源图像src = imread( argv[1], 1 );
if( !src.data ){ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;return -1;}
/// 转为灰度图cvtColor( src, src, CV_BGR2GRAY );
/// 应用直方图均衡化equalizeHist( src, dst );
/// 显示结果namedWindow( source_window, CV_WINDOW_AUTOSIZE );namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );
imshow( source_window, src );imshow( equalized_window, dst );
/// 等待用户按键退出程序waitKey(0);
return 0;
}
1.5 运行效果
直方图均衡化
2. 直方图计算¶
2.1 目标
如何使用OpenCV函数 split 将图像分割成单通道数组。
如何使用OpenCV函数 calcHist 计算图像阵列的直方图。
如何使用OpenCV函数 normalize 归一化数组。
2.2 直方图
详见OpenCV 【九】——calcHist ——图像直方图统计
让我们再来搞清楚直方图的一些具体细节:
- dims: 需要统计的特征的数目, 在上例中, dims = 1 因为我们仅仅统计了灰度值(灰度图像)。
- bins: 每个特征空间 子区段 的数目,在上例中, bins = 16
- range: 每个特征空间的取值范围,在上例中, range = [0,255]
怎样去统计两个特征呢? 在这种情况下, 直方图就是3维的了,x轴和y轴分别代表一个特征, z轴是掉入
组合中的样本数目。 同样的方法适用于更高维的情形 (当然会变得很复杂)。
2.3 代码实例
本程序做什么?
装载一张图像
使用函数 split 将载入的图像分割成 R, G, B 单通道图像
调用函数 calcHist 计算各单通道图像的直方图
在一个窗口叠加显示3张直方图
下载代码: 点击 这里
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
/** @函数 main */
int main(int argc, char** argv)
{Mat src, dst;
/// 装载图像src = imread("C:\\Users\\guoqi\\Desktop\\ch7\\4.jpg", 1);
if (!src.data){return -1;}
/// 分割成3个单通道图像 ( R, G 和 B )vector<Mat> rgb_planes;split(src, rgb_planes);
/// 设定bin数目int histSize = 255;
/// 设定取值范围 ( R,G,B) )float range[] = { 0, 255 };const float* histRange = { range };
bool uniform = true; bool accumulate = false;
Mat r_hist, g_hist, b_hist;
/// 计算直方图:calcHist(&rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);calcHist(&rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);calcHist(&rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);
// 创建直方图画布int hist_w = 400; int hist_h = 400;int bin_w = cvRound((double)hist_w / histSize);
Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
/// 将直方图归一化到范围 [ 0, histImage.rows ]normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
/// 在直方图画布上画出直方图for (int i = 1; i < histSize; i++){line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),Point(bin_w*(i), hist_h - cvRound(r_hist.at<float>(i))),Scalar(0, 0, 255), 2, 8, 0);line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))),Scalar(0, 255, 0), 2, 8, 0);line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))),Scalar(255, 0, 0), 2, 8, 0);}
/// 显示直方图namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE);imshow("calcHist Demo", histImage);
waitKey(0);return 0;
}
2.4 运行结果
3 直方图对比¶
HSV 颜色空间
基于上述理由,在图像处理中使用较多的是 HSV 颜色空间,它比 RGB 更接近人们对彩色的感知经验。非常直观地表达颜色的色调、鲜艳程度和明暗程度,方便进行颜色的对比。
在 HSV 颜色空间下,比 BGR 更容易跟踪某种颜色的物体,常用于分割指定颜色的物体。
HSV 表达彩色图像的方式由三个部分组成:
Hue(色调、色相)
Saturation(饱和度、色彩纯净度)
Value(明度)
用下面这个圆柱体来表示 HSV 颜色空间,圆柱体的横截面可以看做是一个极坐标系 ,H 用极坐标的极角表示,S 用极坐标的极轴长度表示,V 用圆柱中轴的高度表示。
Hue 用角度度量,取值范围为0~360°,表示色彩信息,即所处的光谱颜色的位置。,表示如下:
颜色圆环上所有的颜色都是光谱上的颜色,从红色开始按逆时针方向旋转,Hue=0 表示红色,Hue=120 表示绿色,Hue=240 表示蓝色等等。
在 GRB中 颜色由三个值共同决定,比如黄色为即 (255,255,0);在HSV中,黄色只由一个值决定,Hue=60即可。
HSV 圆柱体的半边横截面(Hue=60):
其中Saturation*水平方向表示饱和度,饱和度表示颜色接近光谱色的程度。饱和度越高,说明颜色越深,越接近光谱色饱和度越低,说明颜色越浅,越接近白色。饱和度为0表示纯白色。取值范围为0~100%,值越大,颜色越饱和。**
Value(明度):竖直方向表示明度,决定颜色空间中颜色的明暗程度,明度越高,表示颜色越明亮,范围是 0-100%。明度为0表示纯黑色(此时颜色最暗)。
可以通俗理解为:
在Hue一定的情况下,饱和度减小,就是往光谱色中添加白色,光谱色所占的比例也在减小,饱和度减为0,表示光谱色所占的比例为零,导致整个颜色呈现白色。
明度减小,就是往光谱色中添加黑色,光谱色所占的比例也在减小,明度减为0,表示光谱色所占的比例为零,导致整个颜色呈现黑色。
HSV 对用户来说是一种比较直观的颜色模型。我们可以很轻松地得到单一颜色,即指定颜色角H,并让V=S=1,然后通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小V而S不变,同样增加白色可以减小S而V不变。例如,要得到深蓝色,V=0.4 S=1 H=240度。要得到浅蓝色,V=1 S=0.4 H=240度。
HSV 的拉伸对比度增强就是对 S 和 V 两个分量进行归一化(min-max normalize)即可,H 保持不变。
RGB颜色空间更加面向于工业,而HSV更加面向于用户,大多数做图像识别这一块的都会运用HSV颜色空间,因为HSV颜色空间表达起来更加直观!
3.1 目标
如何使用OpenCV函数 compareHist 产生一个表达两个直方图的相似度的数值。
如何使用不同的对比标准来对直方图进行比较。
3.2 原理
and
), 首先必须要选择一个衡量直方图相似度的 对比标准 (
) 。
OpenCV 函数 compareHist 执行了具体的直方图对比的任务。该函数提供了4种对比标准来计算相似度:
要比较两个直方图(
and
), 首先必须要选择一个衡量直方图相似度的 对比标准 (
) 。
OpenCV 函数 compareHist 执行了具体的直方图对比的任务。该函数提供了4种对比标准来计算相似度:
Correlation ( CV_COMP_CORREL )
其中
是直方图中bin的数目。
Chi-Square ( CV_COMP_CHISQR )
Intersection ( CV_COMP_INTERSECT )
Bhattacharyya 距离( CV_COMP_BHATTACHARYYA )
3.3 代码
本程序做什么?
装载一张 基准图像 和 两张 测试图像 进行对比。
产生一张取自 基准图像 下半部的图像。
将图像转换到HSV格式。
计算所有图像的H-S直方图,并归一化以便对比。
将 基准图像 直方图与 两张测试图像直方图,基准图像半身像直方图,以及基准图像本身的直方图分别作对比。
显示计算所得的直方图相似度数值。
下载代码: 点击 这里
代码一瞥:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
/** @函数 main */
int main( int argc, char** argv )
{Mat src_base, hsv_base;Mat src_test1, hsv_test1;Mat src_test2, hsv_test2;Mat hsv_half_down;
/// 装载三张背景环境不同的图像if( argc < 4 ){ printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n");return -1;}
src_base = imread( argv[1], 1 );src_test1 = imread( argv[2], 1 );src_test2 = imread( argv[3], 1 );
/// 转换到 HSVcvtColor( src_base, hsv_base, CV_BGR2HSV );cvtColor( src_test1, hsv_test1, CV_BGR2HSV );cvtColor( src_test2, hsv_test2, CV_BGR2HSV );
hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) );
/// 对hue通道使用30个bin,对saturatoin通道使用32个binint h_bins = 50; int s_bins = 60;int histSize[] = { h_bins, s_bins };
// hue的取值范围从0到256, saturation取值范围从0到180float h_ranges[] = { 0, 256 };float s_ranges[] = { 0, 180 };
const float* ranges[] = { h_ranges, s_ranges };
// 使用第0和第1通道int channels[] = { 0, 1 };
/// 直方图MatND hist_base;MatND hist_half_down;MatND hist_test1;MatND hist_test2;
/// 计算HSV图像的直方图calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false );normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() );
calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false );normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() );
calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false );normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() );
calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false );normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() );
///应用不同的直方图对比方法for( int i = 0; i < 4; i++ ){ int compare_method = i;double base_base = compareHist( hist_base, hist_base, compare_method );double base_half = compareHist( hist_base, hist_half_down, compare_method );double base_test1 = compareHist( hist_base, hist_test1, compare_method );double base_test2 = compareHist( hist_base, hist_test2, compare_method );
printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 );}
printf( "Done \n" );
return 0;}
3.4 运行结果
第一张为基准图像,其余两张为测试图像。同时我们会将基准图像与它自身及其半身图像进行对比。
我们应该会预料到当将基准图像直方图及其自身进行对比时会产生完美的匹配, 当与来源于同一样的背景环境的半身图对比时应该会有比较高的相似度, 当与来自不同亮度光照条件的其余两张测试图像对比时匹配度应该不是很好:
下面显示的是结果数值:
对比标准 基准 - 基准 基准 - 半身 基准 - 测试1 基准 - 测试2 Correlation 1.000000 0.930766 0.182073 0.120447 Chi-square 0.000000 4.940466 21.184536 49.273437 Intersection 24.391548 14.959809 3.889029 5.775088 Bhattacharyya 0.000000 0.222609 0.646576 0.801869 对于 Correlation 和 Intersection 标准, 值越大相似度越大。因此可以看到对于采用这两个方法的对比,基准 - 基准 的对比结果值是最大的, 而 基准 - 半身 的匹配则是第二好(跟我们预测的一致)。而另外两种对比标准,则是结果越小相似度越大。 我们可以观察到基准图像直方图与两张测试图像直方图的匹配是最差的,这再一次印证了我们的预测。
相关文章:

c语言实现线性结构(数组与链表)
由于这两天看了数据结构,所以又把大学所学的c语言和指针"挂"起来了。本人菜鸟一枚请多多指教。下面是我这两天学习的成果(数组和链表的实现,用的是c语言哦!哈哈)。(一)数组的实现和操…

OTSU 二值化的实现
#include <stdio.h> #include <string> #include "opencv2/highgui/highgui.hpp" #include "opencv2/opencv.hpp" using namespace std; using namespace cv; // 大均法函数实现 int OTSU(cv::Mat srcImage) {int nCols srcImage.cols;int nR…

vivo7.0系统机器(亲测有效)激活Xposed框架的教程
对于喜欢搞机的机友来说,常常会使用到Xposed框架和种种功能牛逼的模块,对于5.0以下的系统版本,只要手机能获得Root权限,安装和激活Xposed框架是异常轻松的,但随着系统版本的升级,5.0以后的系统,…

【OpenCV 】反向投影
目录 1 目标 2原理:什么是反向投影? 3 代码实现 4 实现结果 1 目标 什么是反向投影,它可以实现什么功能? 如何使用OpenCV函数 calcBackProject 计算反向投影? 如何使用OpenCV函数 mixChannels 组合图像的不同通道…
Linux编程之自定义消息队列
我这里要讲的并不是IPC中的消息队列,我要讲的是在进程内部实现自定义的消息队列,让各个线程的消息来推动整个进程的运动。进程间的消息队列用于进程与进程之间的通信,而我将要实现的进程内的消息队列是用于有序妥当处理来自于各个线程请求&am…

threshold 二值化的实现
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" int main( ) {// 读取源图像及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg");if( !srcImage.data ) return 1;// 转化为灰度图像cv::Mat srcGray…

如何定时备份数据库并上传七牛云
前言: 这篇文章主要记录自己在备份数据库文件中踩的坑和解决办法。 服务器数据库备份文件之后上传到七牛云 备份数据库文件在服务器根目录下 创建 /backup/qiniu/.backup.sh #!/bin/bash# vuemall 数据库名称 # blog_runner vuemall 的管理用户# admin vuem…

【OpenCV 】计算物体的凸包/创建包围轮廓的矩形和圆形边界框/createTrackbar添加滑动条/
目录 topic 1:模板匹配 topic 2:图像中寻找轮廓 topic 3:计算物体的凸包 topic 4:轮廓创建可倾斜的边界框和椭圆 topic 5:轮廓矩 topic 6:为程序界面添加滑动条 3.1 目标 3.2 代码实例1 3.3 代码实例2 3.4 实例3运行结果 3.5 运行结果 topic 1:模板匹配 topic 2:图…

开源:Angularjs示例--Sonar中项目使用语言分布图
在博客中介绍google的Angularjs 客户端PM模式框架很久了,今天发布一个关于AngularJs使用是简单示例SonarLanguage(示例位于Github:https://github.com/greengerong/SonarLanguage)。本项目只是一个全为客户端的示例项目。项目的初始是我想看看在公司的项…

adaptiveThreshold 阈值化的实现
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" int main( ) {// 图像读取及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg");if( !srcImage.data ) return 1;// 灰度转换cv::Mat srcGray;cv::cvt…

hashMap传入参数,table长度为多少
前言 我的所有文章同步更新与Github--Java-Notes,想了解JVM,HashMap源码分析,spring相关,剑指offer题解(Java版),可以点个star。可以看我的github主页,每天都在更新哟。 邀请您跟我一同完成 rep…

【OpenCV】图像/视频相似度测量PSNR( Peak signal-to-noise ratio) and SSIM,视频/图片转换
目录 1 目标 2 原理 2.1 图像比较 - PSNR and SSIM 3 代码 3.1如何读取一个视频流(摄像头或者视频文件)? 3 运行效果 视频/图片转换: 如何用OpenCV创建一个视频文件用OpenCV能创建什么样的视频文件如何释放视频文件当中的某个颜色通道…

struts2提交list
2019独角兽企业重金招聘Python工程师标准>>> Action: private List<User> users; jsp: <input type"text" name"users[0].name" value"aaa" /> <input type"text" name"users[1].name" value&q…

双阈值法的实现
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" int main( ) {// 图像读取及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg");if( !srcImage.data ) return 1;// 灰度转换cv::Mat srcGray;cv::cvt…

设计模式 小记
观察者模式 1.被观察者是单例模式。 生成这模式 1.Director中对于Builder的引用不一定是Strong,根据情况也有可能是Copy。 2.Director 聚合 Builder, 所以Builder本身可以单独拿出来使用。 转载于:https://juejin.im/post/5ca8c24df265da3094116c18

【MATLAB】————matlab raw图转bmp实现
image_path [layer_3_list_folder,\,layer_3_list_name]; img_raw_path fopen(image_path,r);%%打开图像 img_raw fread(img_raw_path,[Width,Height],uint16);% uchar为无符号字符型 mg_raw uint8(img_raw);%%unit8表示无符号整数,范围0-255,u…

人工手动冷备不完全恢复介绍(purge表不完全恢复)
不完全恢复不完全恢复的基本类型:1)基于时间点 (until time): 使整个数据库恢复到过去的一个时间点前2)基于scn (until change): 使整个数据库恢复到过去的某个SCN前3)基于cancel (u…

半阈值法的实现
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> using namespace std; using namespace cv; int main( ) {// 读取源图像及判断cv::Mat srcImage cv::imread("..\\images\\hand1.jpg&q…

novaclient的api调用流程与开发
novaclient的api调用流程与开发 2015年07月05日 19:27:17 qiushanjushi 阅读数:3915 http://blog.csdn.net/tpiperatgod/article/details/18375387?utm_sourcetuicool 另一个地址:http://neuromancer.sinaapp.com/?p64 从nova client的入口查看 cat /u…

【C++】 保存内容到文件工具
1. c 输出到文件 // save mean distance between center and descriptorsstd::string filename configuration_.debug_output_path() "ref_max_mean_distance.txt";FILE* fp fopen(filename.c_str(), "w");try {if (fp nullptr) {return error::Failed…

你知道实习对你有多重要吗?
大学生就业一直是个永恒不变的话题,在过去几年中,每次临近毕业季,我们肯定会一次次的听到“史上最难就业季”之说。而每一年的数据也会不断突破前一年的数字。在国新办举行的新闻发布会上,人力资源社会保障部部长尹蔚民提到…

灰度直方图的实现
#include <opencv2\opencv.hpp> int main() {// 图像源获取及判断 cv::Mat Image, ImageGray;Image cv::imread("..\\images\\flower3.jpg"); if(Image.empty()) return -1;cv::imshow("Image",Image);// 转换为灰度图像cv::cvtColor(Image,Image…

Android笔记之ViewModel的使用示例
依赖 implementation android.arch.lifecycle:extensions:1.1.1 implementation com.squareup.retrofit2:retrofit:2.5.0 implementation com.squareup.retrofit2:converter-gson:2.5.0 implementation com.squareup.retrofit2:adapter-rxjava2:2.5.0 implementation io.reacti…

vscode配置记录
vscode配置记录 按照官网教程安装好vs:实际上只需要配置launch.json的”program“如下所示 "configurations": [{"name": "(gdb) Launch","type": "cppdbg","request": "launch","program":…

unity 2d 游戏优化之路 遇坑记录
情景说明: unity 出的Android包,在目前一些主流机型跑都没有问题,但是在 小米3 这种比较老的机器上跑,报如下错误 GLSL compilation failed, no infolog provided 起先,我们一直以为是在低端机器上某个特定的GLSL 在这…

自定义直方图实现
#include <opencv2/opencv.hpp> int main() {// 图像获取及判断cv::Mat srcImage cv::imread("..\\images\\flower3.jpg");if( !srcImage.data ) return 1;cv::imshow("srcImage",srcImage);// 灰度转换 cv::Mat srcGray;cv::cvtColor(srcImage,sr…

js数组指定位置添加删除
示例参考:http://www.w3school.com.cn/jsref/jsref_splice.asp转载于:https://www.cnblogs.com/CarryYou-lky/p/10669859.html

【C++】对象实例化/成员函数/成员变量的内存管理
文章目录1. 对象实例化的内存管理总结2.C成员函数在内存中的存储方式3.C类的实例化对象的大小之sizeof()实例一:实例二:实例三:实例四:实例五:实例六:实例七:实例八:实例九ÿ…

HTML form 标签的 enctype 属性
1. enctype 的定义和用法 enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。 默认地,表单数据会编码为 "application/x-www-form-urlencoded"。 就是说,在发送到服务器之前,所有字符都会进行编码(空格转…

灰度直方图均衡化实现
#include <opencv2/opencv.hpp> int main() {cv::Mat srcImage cv::imread("..\\images\\flower3.jpg");if( !srcImage.data ) return 1;cv::Mat srcGray;cv::cvtColor(srcImage, srcGray, CV_BGR2GRAY);cv::imshow("srcGray", srcGray);// 直方图均…