本文实现彩色图像的全局直方图均衡。分别对R/G/B三通道均衡,读写图片采用OpenCV。代码如下:
#include <opencv2/opencv.hpp>
//#include <cv.h>
//#include <cxcore.h>
//#include <highgui.h>
#include <time.h>
#include <stdio.h>
#include <math.h>
#include "EqualizeHist.h"
//typedef unsigned char uchar;
IplImage* EqualizeHistColorImage(IplImage *pImage)
{
IplImage *pEquaImage = cvCreateImage(cvGetSize(pImage), pImage->depth, 3);
// 原图像分成各通道后再均衡化,最后合并即彩色图像的直方图均衡化
const int MAX_CHANNEL = 4;
IplImage *pImageChannel[MAX_CHANNEL] = {NULL};
int i;
for (i = 0; i < pImage->nChannels; i++)
pImageChannel[i] = cvCreateImage(cvGetSize(pImage), pImage->depth, 1);
cvSplit(pImage, pImageChannel[0], pImageChannel[1], pImageChannel[2], pImageChannel[3]);
for (i = 0; i < pImage->nChannels; i++)
// cvEqualizeHist(pImageChannel[i], pImageChannel[i]);
EqualizeHist( (uchar*)(pImageChannel[i]->imageData), (uchar*)(pImageChannel[i]->imageData),pImage->width,pImage->height );
cvMerge(pImageChannel[0], pImageChannel[1], pImageChannel[2], pImageChannel[3], pEquaImage);
for (i = 0; i < pImage->nChannels; i++)
cvReleaseImage(&pImageChannel[i]);
return pEquaImage;
}
int main( int argc, char** argv )
{
IplImage* pImg; //声明IplImage指针
IplImage* pEquaImage;
clock_t start, finish;
double time;
//载入图像,强制转化为Gray
pImg = cvLoadImage( "nupt.jpg", CV_LOAD_IMAGE_UNCHANGED);
if(pImg==NULL)
return -1;
printf("Load img success\n");
start = clock();
pEquaImage = EqualizeHistColorImage(pImg);
finish = clock();
time = (double)(finish - start) / CLOCKS_PER_SEC;
printf( "finish operation for %dchannels in %lf seconds\n",pImg->nChannels,time);
cvNamedWindow("src",CV_WINDOW_AUTOSIZE);
cvNamedWindow("dst",CV_WINDOW_AUTOSIZE);
cvShowImage("src",pImg);
cvShowImage("dst",pEquaImage);
cvWaitKey(0);
cvSaveImage("ret.jpg", pEquaImage);//把图像写入文件
cvReleaseImage(&pImg); //释放图像
cvReleaseImage(&pEquaImage);
return 0;
}
//#include <math.h>
#include <assert.h>
typedef unsigned char uchar;
void EqualizeHist( const unsigned char* src,unsigned char* dst,int width,int height )
{
int x,y;
const int hist_sz = 256;
int hist[hist_sz];
memset(hist, 0, sizeof(hist));
int size = width*height;
//统计每个灰度值出现的次数
for(x=0;x<size;x++){
assert(*(src+x)<257 && *(src+x)>=0);
hist[*(src+x)]++;
}
float scale = 255.f/(width*height);
int sum = 0;
uchar lut[hist_sz+1];
for(x = 0; x < hist_sz; x++ )
{
sum += hist[x];
//int val = round(sum*scale);
int val =(sum*scale+0.5);
lut[x] = val;
}
lut[0] = 0;
for( y = 0; y < size; y++ )
{
*(dst+y) = lut[*(src+y)];
if(y%100==0)
printf("%d\n",*(dst+y));
}
}
原图:
效果图