1.图像的直方图
图像的直方图,代表了图像的灰度值的分布状况。从直方图上,我们可以很明确的知道,图像的偏暗程度和饱和程度。如果一幅数字图像中,假设作为水平轴的灰度值rk出现了nk次,那么对应于垂直轴的归一化后的函数如下所示。
pk=nkMN
这样的图像,被称为直方图。为了直观感受一下直方图的作用,我使用相机调节曝光补偿,拍摄了以下3枚图像。
从图像的上方的直方图就可以看出来,图像的偏暗程度与饱和程度。并且,可以将左图像与中央图像称为动态范围较窄的图像。相反的,对于右边图像,其动态范围较宽,图像得到了很好的显示。
2.直方图均衡
直方图均衡,可以用于调节动态范围较窄的图像,增强图像对比度。然而,灰度拉升或者其他的灰度变换同样可以达到这个目的。所以,直方图均衡的本质目的是,将图像的累积分布函数(Probability Density Function)调节为45°曲线。为此,直方图均衡的目的是明确的,而不是像灰度拉升这种操作那么暧昧。
具体的直方图均衡的原理,可以参照的之前的博文。
2.1代码实现
下面是openCV的代码,由于写得比较早,可能不是那么整洁。
//-------------------------------------------------------
// 内容:OpenCV 环境的配置
// 图像的读取
// 直方图的绘制与直方图均衡的实现
// 直方图的累积分布函数(PDF)的计算
// 2015.4.17
// by zhou fan
// ------------------------------------------------------
#include "stdafx.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#define RGB_image 1
#define Gray_image 0
#define other_image -1
using namespace cv;
using namespace std;
int main(int argc, char** argv[])
{
//IplImage * ori= cvLoadImage("..\\Data\\Fig0320(4)(bottom_left).tif",Gray_image);
IplImage * ori= cvLoadImage("..\\Data\\EV.JPG",Gray_image);
cvNamedWindow("Original",1); //new window,
cvShowImage("Original",ori); //show
int hist_xMax = 256; //size
int hist_yMax = 256;
float range[] = {0,255}; //统计范围
float* ranges[]={range};
//创建直方图
CvHistogram* hist = cvCreateHist(1,&hist_xMax,CV_HIST_ARRAY,ranges,1);
//统计概率
cvCalcHist(&ori,hist,
0, //累積タイプではない
0);
//归一化
cvNormalizeHist(hist,1.0);
//histogram and PDF show
{
Mat HistImage(hist_xMax,hist_yMax,CV_8UC3,Scalar(255,255,255));
IplImage hist_show = HistImage;
Mat HistPDFImage(hist_xMax,hist_yMax,CV_8UC3,Scalar(255,255,255));
IplImage hist_PDF_show = HistPDFImage;
float HistPDF[256] = {0};
float max_value = 0;
float yMax_Limt = 0.1;
cvGetMinMaxHistValue(hist,0,&max_value,0,0);
for(int x=0;x<hist_xMax;x++)
{
float yHistVal = cvGetReal1D((hist)->bins,x); //取得1D数据的值
int yVal = cvRound(yHistVal*hist_yMax/yMax_Limt); //要绘制的高度
HistPDF[x] = (float)((x == 0)? cvGetReal1D((hist)->bins,x):
cvGetReal1D((hist)->bins,x) + HistPDF[x-1]);
cvLine(&hist_show,
cvPoint(x,hist_yMax),
cvPoint(x,hist_yMax - yVal),
CV_RGB(0,0,0));
cvLine(&hist_PDF_show,
cvPoint(x-1,hist_yMax - cvRound(HistPDF[x-1]*hist_yMax)),
cvPoint( x,hist_yMax - cvRound(HistPDF[x]*hist_yMax)),
CV_RGB(0,0,0));
//cout << yHistVal << " "<<(HistPDF[x])<<"\n" ;
}
//想要窗口内的图片随着窗口一起扩大的话,需要使用样式 WINDOW_NORMAL
//cvNamedWindow("Histogram",WINDOW_NORMAL);
cvNamedWindow("Histogram",1); //new window,
cvShowImage("Histogram",&hist_show); //show
cvNamedWindow("PDF",1); //new window,
cvShowImage("PDF",&hist_PDF_show); //show
}
//直方图均衡
cvEqualizeHist(ori,ori);
cvNamedWindow("Result",1); //new window,
cvShowImage("Result",ori); //show
//计算均衡后的直方图
cvCalcHist(&ori,hist,
0, //非累积
0);
//归一化
cvNormalizeHist(hist,1.0);
//histogram and PDF show
{
Mat HistImage(hist_xMax,hist_yMax,CV_8UC3,Scalar(255,255,255));
IplImage hist_show = HistImage;
Mat HistPDFImage(hist_xMax,hist_yMax,CV_8UC3,Scalar(255,255,255));
IplImage hist_PDF_show = HistPDFImage;
float HistPDF[256] = {0};
float max_value = 0;
float yMax_Limt = 0.1;
cvGetMinMaxHistValue(hist,0,&max_value,0,0);
for(int x=0;x<hist_xMax;x++)
{
float yHistVal = cvGetReal1D((hist)->bins,x); //取得1D数据的值
int yVal = cvRound(yHistVal*hist_yMax/yMax_Limt); //要绘制的高度
HistPDF[x] = (float)((x == 0)? cvGetReal1D((hist)->bins,x):
cvGetReal1D((hist)->bins,x) + HistPDF[x-1]);
cvLine(&hist_show,
cvPoint(x,hist_yMax),
cvPoint(x,hist_yMax - yVal),
CV_RGB(0,0,0));
cvLine(&hist_PDF_show,
cvPoint(x-1,hist_yMax - cvRound(HistPDF[x-1]*hist_yMax)),
cvPoint( x,hist_yMax - cvRound(HistPDF[x]*hist_yMax)),
CV_RGB(0,0,0));
//cout << yHistVal << " "<<(HistPDF[x])<<"\n" ;
}
cvNamedWindow("Histogram_Result",1); //new window,
cvShowImage("Histogram_Result",&hist_show); //show
cvNamedWindow("PDF_Result",1); //new window,
cvShowImage("PDF_Result",&hist_PDF_show); //show
}
cvWaitKey(0);
return (int)0;
}
2.1执行结果
执行直方图均衡前的直方图与PDF
结果的直方图与PDF
执行直方图均衡前的直方图与PDF
结果的直方图与PDF
原文发于博客:http://blog.csdn.net/thnh169/
时间: 2024-11-05 21:37:10