【OpenCV】数字图像灰度直方图

2024-02-19 21:32

本文主要是介绍【OpenCV】数字图像灰度直方图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

灰度直方图是数字图像中最简单且有用的工具,这一篇主要总结OpenCV中直方图CvHistogram的结构和应用。

灰度直方图的定义

灰度直方图是灰度级的函数,描述图像中该灰度级的像素个数(或该灰度级像素出现的频率):其横坐标是灰度级,纵坐标表示图像中该灰度级出现的个数(频率)。
一维直方图的结构表示为

高维直方图可以理解为图像在每个维度上灰度级分布的直方图。常见的是二维直方图。如红-蓝直方图的两个分量分别表示红光图像的灰度值和蓝光图像灰度值的函数。其图像坐标(Dr,Db)处对应在红光图像中具有灰度级Dr同时在蓝光图像中具有灰度级Db的像素个数。这是基于多光谱——每个像素有多个变量——的数字图像,二维中对应每个像素统计个变量。

OpenCV中的直方图CvHistogram

注意我们在上面理解直方图的意义时更多把他想象成一幅 “图”,继而理解图中横坐标,纵坐标的意义。而在OpenCV中,应该更多把直方图看做 “数据结构”来理解。
OpenCV中用CvHistogram表示多维直方图( http://www.opencv.org.cn/index.php/Cv%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86#CvHistogram):
typedef struct CvHistogram
{int     type;CvArr*  bins;  //存放每个灰度级数目的数组指针float   thresh[CV_MAX_DIM][2];  //均匀直方图float** thresh2; //非均匀直方图CvMatND mat;  //直方图数组的内部数据结构
}
CvHistogram;
这个结构看起来简单(比IplImage*元素少多了。。。)其实并不太好理解。
第一个成员type用来指定第二个成员bins的类型。OpenCv中常见到CvArr*的接口,可以用以指定诸如CvMat、CvMatND、IplImage的类型,其实CvArr*的是一个指向void的指针。在函数内部有时需要得到确切的指向类型,这就需要type来指定。
thresh用来指定统计直方图分布的上下界。比如[0 255]表示用来统计图像中像素分别在灰度级[0 255]区间的分布情况,CV_MAX_DIM对应直方图的维数,假如设定二维红-蓝直方图的thresh为[0 255;100 200],就是分别统计红色图像灰度级在[0 255]以及蓝色图像在灰度级[100 200]的分布情况。
thresh用以指定均匀直方图的分布,我们按每个像素理解自然是“均匀分布”,其实也可以统计像素在几个区间的分布。如果统计像素在2个区间的分布,则对应[0 255]的上下界,均匀分布统计的区间即[0 127] [127 255]分布的概率,这也是为什么thresh第二个维数默认为2——会自动均分上下界;而thresh2指定非均匀的分布,这就需要指定每个区间的上下界,如果要统计直方图在区间(0,10,100,255)的分布,那需要指定thresh2的一个维度为[0 10 100 255],所以用float**形式表示。
mat简单说就是存储了直方图的信息,即我们统计的直方图分布概率。

创建直方图 cvCreateHist()

OpenCV中用cvCreateHist()创建一个直方图:
CvHistogram* cvCreateHist( int dims, //直方图维数 int* sizes,//直翻图维数尺寸int type, //直方图的表示格式float** ranges=NULL, //图中方块范围的数组int uniform=1 //归一化标识);
size数组的长度为dims,每个数表示分配给对应维数的bin的个数。如dims=3,则size中用[s1,s2,s3]分别指定每维bin的个数。
type有两种:CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组 CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组 CvSparseMat。
ranges就是那个复杂的不好理解的thresh的范围,他的内容取决于uniform的值。uniform为0是均匀的,非0时不均匀。
计算图像直方图的函数为CalcHist():
void cvCalcHist( IplImage** image, //输入图像(也可用CvMat**)CvHistogram* hist, //直方图指针int accumulate=0, //累计标识。如果设置,则直方图在开始时不被清零。const CvArr* mask=NULL //操作 mask, 确定输入图像的哪个象素被计数);
要注意的是这个函数用来计算一张(或多张) 单通道图像的直方图,如果要计算多通道,则用这个函数分别计算图像每个单通道。

实践:一维直方图

下面实践一下用OpenCV生成图像的一维直方图
int main( )
{IplImage * src= cvLoadImage("baboon.jpg");IplImage* gray_plane = cvCreateImage(cvGetSize(src),8,1);cvCvtColor(src,gray_plane,CV_BGR2GRAY);int hist_size = 256;    //直方图尺寸int hist_height = 256;float range[] = {0,255};  //灰度级的范围float* ranges[]={range};//创建一维直方图,统计图像在[0 255]像素的均匀分布CvHistogram* gray_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);//计算灰度图像的一维直方图cvCalcHist(&gray_plane,gray_hist,0,0);//归一化直方图cvNormalizeHist(gray_hist,1.0);int scale = 2;//创建一张一维直方图的“图”,横坐标为灰度级,纵坐标为像素个数(*scale)IplImage* hist_image = cvCreateImage(cvSize(hist_size*scale,hist_height),8,3);cvZero(hist_image);//统计直方图中的最大直方块float max_value = 0;cvGetMinMaxHistValue(gray_hist, 0,&max_value,0,0);//分别将每个直方块的值绘制到图中for(int i=0;i<hist_size;i++){float bin_val = cvQueryHistValue_1D(gray_hist,i); //像素i的概率int intensity = cvRound(bin_val*hist_height/max_value);  //要绘制的高度cvRectangle(hist_image,cvPoint(i*scale,hist_height-1),cvPoint((i+1)*scale - 1, hist_height - intensity),CV_RGB(255,255,255));  }cvNamedWindow( "GraySource", 1 );cvShowImage("GraySource",gray_plane);cvNamedWindow( "H-S Histogram", 1 );cvShowImage( "H-S Histogram", hist_image );cvWaitKey(0);
}
试验结果:

对应的,我们可以用一样的思路统计每个通道的直方图,并绘制图像每个通道像素的分布:


实践:二维直方图

我们也可以结合OpenCV的例子生成二维直方图:
IplImage* r_plane  = cvCreateImage( cvGetSize(src), 8, 1 );IplImage* g_plane  = cvCreateImage( cvGetSize(src), 8, 1 );IplImage* b_plane  = cvCreateImage( cvGetSize(src), 8, 1 );IplImage* planes[] = { r_plane, g_plane };//将HSV图像分离到不同的通道中cvCvtPixToPlane( src, b_plane, g_plane, r_plane, 0 );// 生成二维直方图数据结构int r_bins =256, b_bins = 256; CvHistogram* hist;{int    hist_size[] = { r_bins, b_bins };float  r_ranges[]  = { 0, 255 };          // hue is [0,180]float  b_ranges[]  = { 0, 255 }; float* ranges[]    = { r_ranges,b_ranges };hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1); }//计算一张或多张单通道图像image(s) 的直方图cvCalcHist( planes, hist, 0, 0 );
刚才的图我们是对应每个横坐标绘制纵坐标的直方块,二维的图需要绘制每个点:
for( int h = 0; h < r_bins; h++ ) {for( int s = 0; s < b_bins; s++ ) {float bin_val = cvQueryHistValue_2D( hist, h, s ); //查询直方块的值int intensity = cvRound( bin_val * 255 / max_value );cvRectangle( hist_img, cvPoint( h*scale, s*scale ),cvPoint( (h+1)*scale - 1, (s+1)*scale - 1),CV_RGB(intensity,intensity,intensity), CV_FILLED);}
}


最终生成二维直方图:

直方图的应用以后再讨论。

转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7600666

实验代码下载:http://download.csdn.net/detail/xiaowei_cqu/4328881




这篇关于【OpenCV】数字图像灰度直方图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/726033

相关文章

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++中OpenCV 矩阵运算的实现

《C/C++中OpenCV矩阵运算的实现》本文主要介绍了C/C++中OpenCV矩阵运算的实现,包括基本算术运算(标量与矩阵)、矩阵乘法、转置、逆矩阵、行列式、迹、范数等操作,感兴趣的可以了解一下... 目录矩阵的创建与初始化创建矩阵访问矩阵元素基本的算术运算 ➕➖✖️➗矩阵与标量运算矩阵与矩阵运算 (逐元

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

C/C++和OpenCV实现调用摄像头

《C/C++和OpenCV实现调用摄像头》本文主要介绍了C/C++和OpenCV实现调用摄像头,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录准备工作1. 打开摄像头2. 读取视频帧3. 显示视频帧4. 释放资源5. 获取和设置摄像头属性

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

c/c++的opencv实现图片膨胀

《c/c++的opencv实现图片膨胀》图像膨胀是形态学操作,通过结构元素扩张亮区填充孔洞、连接断开部分、加粗物体,OpenCV的cv::dilate函数实现该操作,本文就来介绍一下opencv图片... 目录什么是图像膨胀?结构元素 (KerChina编程nel)OpenCV 中的 cv::dilate() 函

qtcreater配置opencv遇到的坑及实践记录

《qtcreater配置opencv遇到的坑及实践记录》我配置opencv不管是按照网上的教程还是deepseek发现都有些问题,下面是我的配置方法以及实践成功的心得,感兴趣的朋友跟随小编一起看看吧... 目录电脑环境下载环境变量配置qmake加入外部库测试配置我配置opencv不管是按照网上的教程还是de

python+OpenCV反投影图像的实现示例详解

《python+OpenCV反投影图像的实现示例详解》:本文主要介绍python+OpenCV反投影图像的实现示例详解,本文通过实例代码图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前言二、什么是反投影图像三、反投影图像的概念四、反向投影的工作原理一、利用反向投影backproj