进行直方图均衡化并将直方图绘制出来,主要需要如下几个函数:
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) )
第一个参数:Iplimage** image:输入图像 (也可以使用 CvMat** ).
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 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
#include
#include
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);
//自己释放图像空间的函数;
}
结果显示如下:
原图像及直方图:
经直方图均衡化之后的结果图像及直方图: