#include "cv.h"
#include"highgui.h"
using namespace cv;
using namespace std;
/*
直方图均衡化
基本思想:把原始图的直方图变换为均匀分布的形式,
这样就增加了像素灰度值的动态 范围,从而达到增强图像整体对比度的效果
*/
void HE(Mat img)
{
int nub[256] = {0};
double p[256] = {0.0};
for(int i = 0 ; i < img.rows; ++i)
{
for(int j = 0 ; j < img.cols ; ++j)
{
nub[ img.at<uchar>(i,j) ]++;
}
}
int sum = img.rows*img.cols;
for(int i = 0 ; i < 256 ; ++i)
{
if( i == 0 )p[0] = 1.0*nub[i] / sum;
else p[i] = p[i-1] + 1.0*nub[i] / sum;
}
for(int i = 0 ; i < img.rows ; ++i)
{
for(int j = 0 ; j < img.cols ; ++j)
{
img.at<uchar>(i,j) = uchar(255*p[img.at<uchar>(i,j)]);
}
}
imshow("HE",img);
}
/*
自适应直方图均衡化
自适应直方图均衡化(AHE)用来提升图像的对比度的一种计算机图像处理技术。和普通的直方图均衡算法不同,AHE算法通过计算图像的局部直方图,然后重新分布亮度来来改变图像对比度。因此,该算法更适合于改进图像的局部对比度以及获得更多的图像细节。
*/
void AHE(Mat img , int step = 8)
{
Mat res = img.clone();
int w = img.cols;
int h = img.rows;
int step_wnub = w / step;
int step_hnub = h / step;
double p[8*8+1][256] = {0};
int nub[8*8+1][256] = {0};
int cnt = 0;
int sum = step_wnub*step_hnub;
for(int py = 0 ; py < step ; ++py)
{
for(int px = 0 ; px < step ; ++px)
{
for(int i = py*step_hnub; i < py*step_hnub+step_hnub ; ++i)
for( int j = px*step_wnub; j < px*step_wnub+step_wnub ; ++j)
nub[cnt][ img.at<uchar>(i,j) ]++;
for(int i = 0 ; i < 256 ; ++i){
if( i == 0 )p[cnt][0] = 1.0*nub[cnt][i] / sum;
else p[cnt][i] = p[cnt][i-1] + 1.0*nub[cnt][i] / sum;
}
for(int i = py*step_hnub; i < py*step_hnub+step_hnub ; ++i)
for( int j = px*step_wnub; j < px*step_wnub+step_wnub ; ++j){
//if( cnt == 0)cout << i << " " << j << " " << img.size() << endl;
img.at<uchar>(i,j) = uchar(255*p[cnt][img.at<uchar>(i,j)]);
//cout << img.at<uchar>(i,j) << endl;
}
cnt++;
}
}
imshow("AHE",img);
}
/*
限制对比度的直方图均衡化
*/
Mat CLHE(Mat img,int _step = 8)
{
int width = img.cols;
int height= img.rows;
Mat CLHE_GO = img.clone();
int tmp[256] ={0};
float C[256] = {0.0};
int total = width*height;
for (int i=0 ;i<img.rows;i++)
{
for (int j=0;j<img.cols;j++)
{
int index = img.at<uchar>(i,j);
tmp[index] ++;
}
}
/////////////////////////限制对比度计算部分,注意这个地方average的计算不一定科学
int average = width * height / 255/64;
int LIMIT = 4 * average;
int steal = 0;
for(int k = 0 ; k < 256 ; k++)
{
if(tmp[k] > LIMIT){
steal += tmp[k] - LIMIT;
tmp[k] = LIMIT;
}
}
int bonus = steal/256;
//hand out the steals averagely
for(int k = 0 ; k < 256 ; k++)
{
tmp[k] += bonus;
}
///////////////////////////////////////////
//计算累积函数
for(int i = 0;i < 256 ; i++){
if(i == 0)
C[i] = 1.0f * tmp[i] / total;
else
C[i] = C[i-1] + 1.0f * tmp[i] / total;
}
//这里的累积函数分配的方法非常直观高效
for(int i = 0;i < img.rows;i++){
for(int j = 0;j < img.cols;j++){
int index = img.at<uchar>(i,j);
CLHE_GO.at<uchar>(i,j) = C[index] * 255 ;
}
}
return CLHE_GO;
}
/*
CLAHE同普通的自适应直方图均衡不同的地方主要是其对比度限幅。这个特性也可以应用到全局直方图均衡化中,即构成所谓的限制对比度直方图均衡(CLHE),但这在实际中很少使用。在CLAHE中,对于每个小区域都必须使用对比度限幅。CLAHE主要是用来克服AHE的过度放大噪音的问题。 */