opencv学习笔记9 直方图均衡化并绘制直方图

2024-03-25 00:38

本文主要是介绍opencv学习笔记9 直方图均衡化并绘制直方图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

进行直方图均衡化并将直方图绘制出来,主要需要如下几个函数:

1、CVAPI(void)  cvEqualizeHist( const CvArr* src, CvArr* dst );
这个函数用起来十分简单,只需要传入源图像以及已初始化的目标图像即可。

第一个参数:const CvArr* src:待处理的源图像;

第二个参数:CvArr* dst:目标图像;

在cvEqualizeHist()中,原始图像及目标图像必须是单通道,大小相同的8位图像。对于彩色图像,必须先利用cvSplite()将每个通道分开,再分别进行处理。

2、CVAPI(void) cvCvtColor( const CvArr* src, CvArr* dst, int code );
由上一个函数已知,因为我们传入的源图像必须为单通道图像,那么我们在进行其他操作之前,先将图像转换为单通道图像,即使用cvCvtColor()进行转换。

第一个参数:const CvArr* src:待处理的源图像;

第二个参数:CvArr* dst:目标图像;

第三个参数:int code:色彩空间转换的模式,该code来实现不同类型的颜色空间转换。比如CV_BGR2GRAY表示转换为灰度图,CV_BGR2HSV将图片从RGB空间转换为HSV空   间。其中当code选用CV_BGR2GRAY时,dst需要是单通道图片。当code选用CV_BGR2HSV时,对于8位图,需要将rgb值归一化到0-1之间。这样得到HSV图中的H范围才是0-360,S和V的范围是0-1。

3、CV_INLINE void cvCalcHist( IplImage** image, CvHistogram* hist,

                             int accumulate CV_DEFAULT(0),const CvArr* mask CV_DEFAULT(NULL) )<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
第一个参数:Iplimage** image:输入图像 (也可以使用 CvMat** ).
第二个参数:CvHistogram* hist::直方图指针 
第三个参数:int accumulate:累计标识。如果设置,则直方图在开始时不被清零。这个特征保证可以为多个图像计算一个单独的直方图,或者在线更新直方图。
第四个参数:const CvArr* mask:操作 mask, 确定输入图像的哪个象素被计数 函数 cvCalcHist 计算单通道或多通道图像的直方图。 用来增加直方块的数组元素可从相应输入图                         像的同样位置提取。

4、CVAPI(CvHistogram*) cvCreateHist( int dims, int* sizes, int type,

                                   float** ranges CV_DEFAULT(NULL),int uniform CV_DEFAULT(1));

由第3个函数可知,我们想要计算直方图,必须有一个直方图指针,那么我们得先用cvCreatHist()创建一个直方图指针;

第一个参数:dim是表示几维空间,即一般彩色图像是3通道的,dim=3;而灰度图是1通道的,dim=1
第二个参数:sizes如果想在图像中生成255个区间,那么设sizes=10
第三个参数:直方图的表示格式: CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组 CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组 CvSparseMat.
第四个参数: 图中方块范围的数组. 它的内容取决于参数 uniform 的值。这个范围的用处是确定何时计算直方图或决定反向映射(backprojected ),每个方块对应于输入图像的哪个/哪组值。 图像若为IPL_DEPTH_8U,即深度为8,则设成255比较合适,若深度为8位的图像ranges设为0-255,则图像上的像素点都会统计在0~255中(即第一个直方图方块中)。
第五个参数:归一化标识。 如果不为0,则ranges[i](0<=i<cDims,译者注:cDims为直方图的维数,对于灰度图为1,彩色图为3)是包含两个元素的范围数组,包括直方图第i维的上界和下界。在第i维上的整个区域 [lower,upper]被分割成 dims[i] 个相等的块(译者注:dims[i]表示直方图第i维的块数),这些块用来确定输入象素的第 i 个值(译者注:对于彩色图像,i确定R, G,或者B)的对应的块;如果为0,则ranges[i]是包含dims[i]+1个元素的范围数组,包括lower0, upper0, lower1, upper1 == lower2, ..., upperdims[i]-1, 其中lowerj 和upperj分别是直方图第i维上第 j 个方块的上下界(针对输入象素的第 i 个值)。任何情况下,输入值如果超出了一个直方块所指定的范围外,都不会被 cvCalcHist 计数,而且会被函数 cvCalcBackProject 置零。函数 cvCreateHist 创建一个指定尺寸的直方图,并且返回创建的直方图的指针。 如果数组的 ranges 是 0, 则直方块的范围必须由函数 cvSetHistBinRanges 稍后指定。虽然 cvCalcHist 和 cvCalcBackProject 可以处理 8-比特图像而无需设置任何直方块的范围,但它们都被假设等分 0..255 之间的空间。 


5、CVAPI(void) cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2,

                          CvScalar color, int thickness CV_DEFAULT(1),int line_type CV_DEFAULT(8),int shift CV_DEFAULT(0));
函数功能:通过对角线上的两个顶点绘制简单、指定粗细或者带填充的矩形。因为我们想要将直方图绘制出来,所以选用了矩形绘制函数。

参数介绍:
第一个参数:img -- 图像.
第二个参数:pt1 -- 矩形的一个顶点。
第三个参数:pt2 -- 矩形对角线上的另一个顶点
第四个参数:color -- 线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。
第五个参数:thickness -- 组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
第六个参数:line_type -- 线条的类型。见cvLine的描述
第七个参数:shift -- 坐标点的小数点位数。
第八个参数:CvSize cvSize(int height,int width)

6、CVAPI(void) cvGetMinMaxHistValue( const CvHistogram* hist,

                                   float* min_value, float* max_value,int* min_idx CV_DEFAULT(NULL),int* max_idx CV_DEFAULT(NULL));
函数功能:发现最大和最小直方块

参数介绍:

第一个参数:hist 直方图
第二个参数:min_value 直方图最小值的指针
第三个参数:max_value 直方图最大值的指针
第四个参数:min_idx 数组中最小坐标的指针
第五个参数:max_idx 数组中最大坐标的指针
函数 cvGetMinMaxHistValue 发现最大和最小直方块以及它们的位置。任何输出变量都是可选的。在具有同样值几个极值中,返回具有最小下标索引(以字母排列顺序定)的那一个。 

7、cvQueryHistValue_1D( hist, idx0 ) 
函数功能:访问直方图元素,与cvGetReal2d功能是一样的。

好了,将所需要的函数已经全部介绍完毕,下面贴出经过验证的示例代码:

注意:此例程还未进行优化,绘制直方图部分的代码有些重复,应将其进行简化为一个函数调用。但是对于新手来说,可能这种方式比较容易理解。

#include<cv.h>
#include<highgui.h>
#include<iostream>
using namespace std;void main()
{IplImage* pSrcImage, *pGrayImage, *pGrayImageEqualizeHist;pSrcImage = cvLoadImage("E:\\f\\图像处理图片\\equalizeHist1.jpg");pGrayImage = cvCreateImage(cvGetSize(pSrcImage), pSrcImage->depth, 1);pGrayImageEqualizeHist = cvCreateImage(cvGetSize(pSrcImage), pSrcImage->depth, 1);cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);cvEqualizeHist(pGrayImage, pGrayImageEqualizeHist);int size = 256;float ranges[] = { 0, 256 };float *pfRanges[] = { ranges };float max_value = 0;CvHistogram* originalPictureHist = cvCreateHist(1, &size, CV_HIST_ARRAY, pfRanges);cvCalcHist(&pGrayImage, originalPictureHist);IplImage* originalPictureHistImage = cvCreateImage(cvSize(510, 150), 8, 1);cvRectangle(originalPictureHistImage, cvPoint(0, 0), cvPoint(originalPictureHistImage->width, originalPictureHistImage->height), CV_RGB(255, 255, 255));cvGetMinMaxHistValue(originalPictureHist, NULL, &max_value, 0, 0);for (int i = 0; i < 255; i++){float fHistValue = cvQueryHistValue_1D(originalPictureHist, i);int realHeight = cvRound(fHistValue * 150 / max_value);cvRectangle(originalPictureHistImage, cvPoint(i * 2, 150 - 1), cvPoint((i + 1) * 2 - 1, 150 - realHeight),cvScalar(i,0,0,0),CV_FILLED);}CvHistogram* pGrayImageHist = cvCreateHist(1, &size, CV_HIST_ARRAY, pfRanges);cvCalcHist(&pGrayImageEqualizeHist, pGrayImageHist);IplImage* equalizeHistImage = cvCreateImage(cvSize(500, 150), pGrayImageEqualizeHist->depth, 1);float hist_max_value = 0;cvGetMinMaxHistValue(pGrayImageHist, NULL, &hist_max_value, 0, 0);for (int i = 0; i < 255; i++){float value = cvQueryHistValue_1D(pGrayImageHist, i);int realHeight = cvRound(value * 150 / hist_max_value);cvRectangle(equalizeHistImage, cvPoint(i * 2, 150 - 1), cvPoint((i + 1) * 2 - 1, 150 - realHeight), cvScalar(i, 0, 0, 0), CV_FILLED);}cvSaveImage("E:\\f\\图像处理图片\\originalHist.jpg", originalPictureHistImage);cvSaveImage("E:\\f\\图像处理图片\\afterEqualizeHist.jpg", equalizeHistImage);cvShowImage("originalPicture", pSrcImage);cvShowImage("histImage", equalizeHistImage);cvShowImage("originalHist", originalPictureHistImage);cvShowImage("equalizeHistPicture", pGrayImageEqualizeHist);cvWaitKey(0);//自己释放图像空间的函数;
}
结果显示如下:

原图像及直方图:


经直方图均衡化之后的结果图像及直方图:




这篇关于opencv学习笔记9 直方图均衡化并绘制直方图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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

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

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

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

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

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() 函