作业要求:
1.计算一个图片的直方图
2.完成直方图的均衡化
环境:Win7(64bits),Visual Studio2010,OpenCV 2.4.10
1.计算一个图片的直方图
直方图的概念
设图像的灰度范围为[a,b],r为此灰度范围内的任一灰度级,p(r)为这幅图像中灰度级为r的像素出现的频率,可以看出p(r)是r的函数。该函数的图形称为这幅图像的直方图。
计算直方图主要步骤:读取图像,转化为灰度图,创建空白直方图,根据读取图像计算直方图,直方图归一化。
基本数据结构类型:CvHistogram
主要函数:cvCreateHist() , cvCalcHist(), cvNormalizeHist()
CVAPI(CvHistogram*) cvCreateHist(
intdims,
int*sizes,
inttype,
float**ranges CV_DEFAULT(NULL),
intuniform CV_DEFAULT(1) );
dims,直方图维数
sizes,直方图横轴宽度
type,直方图存储方式,CV_HIST_ARRAY密集矩阵存储,CV_HIST_SPARSE稀疏矩阵存储
ranges,直方图灰度范围(英文手册原文如下)
ranges– Array of the dims arrays of the histogram bin boundaries in eachdimension.When the histogram is uniform ( uniform =true), then for eachdimension i it is enough to specify the lower (inclusive) boundary L0 of the0-th histogram bin and the upper (exclusive)boundary UhistSize[i]-1 for thelast histogram bin histSize[i]-1 . That is, in case of a uniform histogram eachof ranges[i] is an array of 2 elements. When the histogram is not uniform (uniform=false ), then each of ranges[i] contains histSize[i]+1 elements:L0;U0 =L1;U1 = L2; :::;UhistSize[i]-2 = LhistSize[i]-1;UhistSize[i]-1 . The arrayelements, that are not between L0 and UhistSize[i]-1 , are not counted in thehistogram.
uniform,标志直方图是否均匀的标志
cvCreateHist()调用方式:
CvHistogram *gray_hist=cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
CV_INLINE void cvCalcHist(
IplImage**image,
CvHistogram*hist,
intaccumulate CV_DEFAULT(0),
constCvArr* mask CV_DEFAULT(NULL) );
image,需要计算的源图像
hist,用于存储直方图的图像
accumulate,是否允许对hist在计算前不清零
mask,当mask非零时,只有mask非0元素对应的像素点会被包含在计算直方图中
cvCalcHist()调用方式:
cvCalcHist(&img_gray,gray_hist,0,0);
img_gray是源图像,gray_hist是计算所得的直方图
CVAPI(void) cvNormalizeHist(
CvHistogram*hist,
doublefactor );
hist,需要归一化的图像
factor,归一化参数
2.完成直方图的均衡化
直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。
主要函数:cvEqualizeHist();
CVAPI(void) cvEqualizeHist(
constCvArr* src,
CvArr*dst );
Src,源图像
Dst,目标输出图像
cvCalcHist()调用方式:
cvEqualizeHist(img_gray,img_gray);
运行结果:
输入图像: 均衡化后图像:
输入图像直方图: 均衡化后直方图:
程序:
#include <highgui.h>
#include<cv.h>
CvFont font;
int main()
{
IplImage *img_in =cvLoadImage("orange.jpg");
IplImage *img_gray=cvCreateImage(cvGetSize(img_in),IPL_DEPTH_8U,1);
cvCvtColor(img_in,img_gray,CV_BGR2GRAY);
cvNamedWindow("img_gray",CV_WINDOW_AUTOSIZE);
cvShowImage("img_gray",img_gray);
inthist_size=256;//直方图的横轴长度
inthist_height=256;//直方图的纵轴高度
float range[]={0,255}; //灰度级的范围
float* ranges[]={range};
CvHistogram*gray_hist=cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);//创建直方图
cvCalcHist(&img_gray,gray_hist,0,0);//计算直方图
cvNormalizeHist(gray_hist,1.0);//归一化直方图
int scale=1;//横轴和纵轴的比例
IplImage *image_hist=cvCreateImage(cvSize(hist_size*scale+60,hist_height+60),IPL_DEPTH_8U,3);//创建直方图的区域
cvSet(image_hist,CV_RGB(255,255,255));
floatmax_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的值
intintensity=cvRound(bin_val*hist_height/max_value) + 1;//要绘制的高度
cvRectangle(image_hist,cvPoint(50+i*scale,10+hist_height-1),cvPoint(50+(i+1)*scale-1,10+hist_height-intensity),CV_RGB(0,0,0));
}
for(int i=0;i<256;i++)
cvRectangle(image_hist,cvPoint(50+i*scale,290),cvPoint(50+(i+1)*scale-1,270),CV_RGB(i,i,i));
cvInitFont(&font,CV_FONT_HERSHEY_PLAIN,1,1,1,1,1);
cvPutText(image_hist,"0",cvPoint(40,310),&font,cvScalar(0,0,0));
cvPutText(image_hist,"100",cvPoint(40+scale*100,310),&font,cvScalar(0,0,0));
cvPutText(image_hist,"200",cvPoint(40+scale*200,310),&font,cvScalar(0,0,0));
cvPutText(image_hist,"0",cvPoint(20,270),&font,cvScalar(0,0,0));
cvPutText(image_hist,"100",cvPoint(10,170),&font,cvScalar(0,0,0));
cvPutText(image_hist,"200",cvPoint(10,70),&font,cvScalar(0,0,0));
cvNamedWindow("H-SHistogram",CV_WINDOW_AUTOSIZE);
cvShowImage("H-SHistogram",image_hist);
cvEqualizeHist(img_gray,img_gray);
inthist_size2=256;//直方图的横轴长度
inthist_height2=256;//直方图的纵轴高度
float range2[]={0,255}; //灰度级的范围
float* ranges2[]={range2};
CvHistogram*gray_hist2=cvCreateHist(1,&hist_size2,CV_HIST_ARRAY,ranges2,1);//创建直方图
cvCalcHist(&img_gray,gray_hist2,0,0);//计算直方图
cvNormalizeHist(gray_hist2,1.0);//归一化直方图
int scale2=1;//横轴和纵轴的比例
IplImage *image_hist2=cvCreateImage(cvSize(hist_size2*scale2+60,hist_height2+60),IPL_DEPTH_8U,3);//创建直方图的区域
cvSet(image_hist2,CV_RGB(255,255,255));
floatmax_value2=0;
cvGetMinMaxHistValue(gray_hist2,0,&max_value2,0,0);//在输出直方图中找到最小值和最大值
for(int i=0;i<hist_size2;i++)
{
floatbin_val2=cvQueryHistValue_1D(gray_hist2,i);//获取直方图中像素i的值
intintensity2=cvRound(bin_val2*hist_height2/max_value2) + 1;//要绘制的高度
cvRectangle(image_hist2,cvPoint(50+i*scale2,10+hist_height2-1),cvPoint(50+(i+1)*scale2-1,10+hist_height2-intensity2),CV_RGB(0,0,0));
}
for(int i=0;i<256;i++)
cvRectangle(image_hist2,cvPoint(50+i*scale2,290),cvPoint(50+(i+1)*scale2-1,270),CV_RGB(i,i,i));
cvInitFont(&font,CV_FONT_HERSHEY_PLAIN,1,1,1,1,1);
cvPutText(image_hist2,"0",cvPoint(40,310),&font,cvScalar(0,0,0));
cvPutText(image_hist2,"100",cvPoint(40+scale2*100,310),&font,cvScalar(0,0,0));
cvPutText(image_hist2,"200",cvPoint(40+scale2*200,310),&font,cvScalar(0,0,0));
cvPutText(image_hist2,"0",cvPoint(20,270),&font,cvScalar(0,0,0));
cvPutText(image_hist2,"100",cvPoint(10,170),&font,cvScalar(0,0,0));
cvPutText(image_hist2,"200",cvPoint(10,70),&font,cvScalar(0,0,0));
cvNamedWindow("H-SHistogram EqualizeHist",CV_WINDOW_AUTOSIZE);
cvShowImage("H-SHistogram EqualizeHist",image_hist2);
cvNamedWindow("img_grayEqualizeHist",CV_WINDOW_AUTOSIZE);
cvShowImage("img_grayEqualizeHist",img_gray);
cvWaitKey(0);
cvDestroyAllWindows();
cvReleaseImage(&img_in);
cvReleaseImage(&img_gray);
cvReleaseImage(&image_hist);
cvReleaseHist(&gray_hist);//释放直方图
cvReleaseHist(&gray_hist2);//释放直方图
return 0;
}