【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 标准, 值越大相似度越大。因此可以看到对于采用这两个方法的对比,基准 - 基准 的对比结果值是最大的, 而 基准 - 半身 的匹配则是第二好(跟我们预测的一致)。而另外两种对比标准,则是结果越小相似度越大。 我们可以观察到基准图像直方图与两张测试图像直方图的匹配是最差的,这再一次印证了我们的预测。
【OpenCV 】直方图均衡化,直方图计算,直方图对比相关推荐
- [Python图像处理] 三十八.OpenCV图像增强和图像去雾万字详解(直方图均衡化、局部直方图均衡化、自动色彩均衡化)
该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...
- python opencv 直方图均衡_Python+OpenCV:全局直方图均衡化、局部直方图自适应均衡化、直方图比较(Python版)...
1. 全局直方图均衡化 cv2.equalizeHist(src, dst=None)函数只能处理单通道的数据,src为输入图像对象矩阵,必须为单通道的uint8类型的矩阵数据.直方图均衡化可以看作是 ...
- OpenCV基础(16)OpenCV直方图均衡化和自适应直方图均衡化(CLAHE)
在本教程中,您将学习使用OpenCV实现直方图均衡化和自适应直方图均衡化(CLAHE). 直方图均衡化是一种基本的图像处理技术,通过更新图像直方图的像素强度分布来调整图像的全局对比度.这样做可以使低对 ...
- 直方图均衡化、自适应直方图均衡化
一.直方图均衡化 简述 直方图均衡化的英文名称是:Histogram Equalization. 图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法.直方图拉伸和 ...
- 数图实验1直方图均衡化c语言,直方图均衡化
直方图均衡化Tag内容描述: 1.直方图均衡化的matlab实现 海南大学课程论文课程名称:数字图像处理 题目名称:直方图均衡化的matlab实现 学 院:信息科学技术学院 专业班级:2010级计算机 ...
- 第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波8 - 直方图处理 - 直方图均衡化(全局直方图均衡化)
直方图均衡化 灰度映射函数: s=T(r),0≤r≤L−1(3.8)s = T(r), \quad 0\leq r \leq L -1 \tag{3.8}s=T(r),0≤r≤L−1(3.8) 假设: ...
- c语言直方图均衡化程序,图像增强 直方图均衡化处理C语言实现.doc
图像增强 直方图均衡化处理C语言实现 图像增强 直方图均衡化处理C语言实现 #ifndef BMP_H_3_INCLUDED #define BMP_H_3_INCLUDED typedef unsi ...
- OpenCV之imgproc 模块. 图像处理(4)直方图均衡化 直方图计算 直方图对比 反向投影 模板匹配
直方图均衡化 目标 在这个教程中你将学到: 什么是图像的直方图和为什么图像的直方图很有用 用OpenCV函数 equalizeHist 对图像进行直方图均衡化 原理 图像的直方图是什么? 直方图是图像 ...
- OpenCV(十九)直方图(直方图计算、掩膜、均衡化、自适应均衡化)
目录 一.基础理论 1.原理及作用 2.专业术语 二.直方图计算 函数介绍: 1.灰度图 代码: 效果: 2.彩色图 代码: 三.直方图掩膜的应用(mask) 1.基础理论 2.代码 3.效果 四.直 ...
最新文章
- 基于高德地图的描点操作,监听地图缩放,展示合理数量的marker
- 概率图模型中的变量消除顺序
- C语言怎么确定用什么整形,【求助各位大虾!】 怎样用 if 语句验证一个整形数字。...
- 实现 IE6 支持 position fixed 的 CSS 属性
- 公司打卡少几秒分析--学会拒绝,学会选择
- 计算机局域网的组网,计算机局域网组网方案设计(精选).doc
- 俄罗斯计算机三进制优缺点,为什么我们没有用上三进制的计算机
- cad lisp 二次抛物线_用Cad画二次抛物线
- uniapp (H5、小程序、app)地图导航
- Json与XML在线互转工具
- 发射功率 dBm 计算
- mysql数据库应用题库_MySQL数据库设计与应用题库免费期末考试2021答案
- ∫e^(-x^2)dx怎么求 ??用的是什么方法??
- 部分选中文件的快捷键
- ImageMagick快速入门
- 让年轻人在年轻时做该做的事
- linux 查看子进程和父进程
- 那些我们不学不行的东西:date函数
- 阿里资深架构师推荐:技术人改如何提升源码阅读能力
- 一图讲清:如何将招聘管理流程化,让HR从重复工作中解放出来
热门文章
- java ee jsp程序_JavaEE——jsp介绍
- dedecms vdimgck.php,织梦dedecms后台验证码图片不显示解决方案
- android 数据库索引,SQLite数据库提供警告自动索引(列)升级Android L后
- html5 data url,HTML5 / Javascript – DataURL到Blob和Blob到DataURL
- Keras TensorFlow教程:使用自己的数据集进行训练
- Postgresql相关数据库、表占用磁盘大小统计
- 困扰一周的奇葩bug:重复相似代码多,导致单片机程序跑飞
- 【camera】1. 相机硬件组成
- Linux那些事儿 之 戏说USB(4)最终奥义
- python什么模块动态调用链接库_Python调用C/C++动态链接库的方法详解