以下例子源自《数字图像处理》第三版
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
版权声明:本文为博主原创文章,未经博主允许不得转载。