您的位置:首页 > 其它

数字图像处理之直方图均衡化

2015-07-18 11:11 429 查看
以下例子源自《数字图像处理》第三版

r表示待处理图像的灰度,取值区间[0,L-1]。r=0表示黑色,r= L-1表示白色。输出灰度值s,变换形式:

s = T(r) ,0<=r<=L-1。

离散变换形式

sk = T(rk) = (L-1)(pr0+pr1+...+prk) ,pr为像素值的概率密度。

= (L-1)(n0+n1+...+nk)/MN,n为每个像素值对于的个数,M、N为图像行和列数。

笔者采用c++语言,编写了直方图均衡化处理的类,并用opencv绘制了均衡化前后的统计直方图,以及通过直方图均衡化的原图像。

类的头文件代码如下:

//<span style="font-family: Arial, Helvetica, sans-serif;">histogramEqualization.h</span>
#ifndef  _HIS_E_
#define _HIS_E_

class hisEqt
{
public:
hisEqt::hisEqt();
hisEqt::~hisEqt();
public:
int w ;
int h;
int nlen;

int *pHis;
float *pdf;

//=====求像素分布概率密度====
void  getPdf();

//======统计像素个数=======
void getHis(unsigned char*imgdata);

//==========画统计分布直方图===============
//void drawHistogram(const float*pdf,Mat &hist1);

//===========直方图均衡化==========
void hisBal();

//====直方图均衡化后的图像===
void imgBal(unsigned char* img);
};

#endif
类源文件:

#include <iostream>
#include "histogramEqualization.h"

using namespace std;

hisEqt::hisEqt():nlen(0){
pHis = new int[256*sizeof(int)];
memset(pHis,0,256*sizeof(int));
pdf = new float[255*sizeof(float)];
memset(pdf,0,255*sizeof(float));
}

hisEqt::~hisEqt(){
delete []pHis;
delete []pdf;
}

//======统计像素个数=======
void hisEqt::getHis(unsigned char*imgdata){
for (int i =0;i<nlen;i++)
{
pHis[imgdata[i]]++;
}
}

//=====求像素分布概率密度====
void hisEqt:: getPdf(){
for(int k =0;k<256;k++)
{
pdf[k] = pHis[k]/float(nlen);
}
}

//===========直方图均衡化==========
void hisEqt::hisBal(){
for(int k =1;k<256;k++)
{
pdf[k] += pdf[k-1];
}
for(int k =0;k<256;k++)
{
pHis[k] = 255*pdf[k];
}
}

//====直方图均衡化
void hisEqt:: imgBal(unsigned char* img){
for (int i =0;i<nlen;i++)
{
img[i] = pHis[img[i]];
}
}


最后写了测试函数test.cpp,代码如下:

#include <opencv2/opencv.hpp>
#include "histogramEqualization.h"
using namespace cv;
void drawHistogram(const float*pdf,Mat& hist1);
int main()
{
Mat image = imread("Fig0308(a)(pollen).tif");
if (!image.data)
{

return -1;
}

Mat hist2(256,256,CV_8UC3,Scalar(0,0,0));
Mat hist1(256,256,CV_8UC3,Scalar(0,0,0));

Mat imgOut = Mat(image.rows,image.cols,CV_8UC3,Scalar(0,0,0));
vector<Mat> planes;
int chn = image.channels();
if (chn==3)
{
split(image,planes);

}
while (chn)
{
chn--;
unsigned char* imageData =  new unsigned char[sizeof(unsigned char)*(image.cols*image.rows)];
memcpy(imageData,planes[chn].data,planes[chn].cols*planes[chn].rows);
hisEqt his;
his.nlen = image.rows*image.cols;
his.getHis(imageData);
his.getPdf();

//	//======画原图直方图并保存============
drawHistogram(his.pdf,hist1);
imwrite("hisline.jpg",hist1);

his.hisBal();
his.getPdf();
//	//======画均衡化后直方图并保存============
drawHistogram(his.pdf,hist2);
imwrite("his_balanceline.jpg",hist2);

//	//=====图像均衡化===
his.imgBal(imageData);
memcpy(planes[chn].data,imageData,planes[chn].cols*planes[chn].rows);
imageData = NULL;
delete[] imageData;
}

//merge(planes0,imgOut);
merge(planes,image);
imwrite("result.jpg",image);
}

void drawHistogram(const float *pdf,Mat& hist1){
for(int k =0;k<256;k++)
{
/*if (k>0)
{
Point a(k-1,255-pdf[k-1]*2550),b(k,255-pdf[k]*2550);
line( hist1,
a,
b,
Scalar( 0, 0, 255 ),
2);
}*/
if (k%2==0)
{
Point a(k,255),b(k,255-pdf[k]*2550);
line( hist1,
a,
b,
Scalar( 0, 0, 255 ),
1);
}
else
{
Point a(k,255),b(k,255-pdf[k]*2550);
line( hist1,
a,
b,
Scalar( 0, 255, 0 ),
1);
}

}
}


结果如图:

原图直方图


均衡化后直方图


原图像(出自冈萨雷斯第三版)


直方图均衡化后的图:



转载请注明出处:http://write.blog.csdn.net/postedit/46940805

实验代码下载:http://download.csdn.net/my

版权声明:本文为博主原创文章,未经博主允许不得转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: