直方图均衡化是间接增强图像对比度的方法。当一张图片的灰度比较相近的时候就可以用直方图均衡化来增大灰度对比,使图像清晰化。
基本思想:
首先,分别求每一个灰度级有多少个像素点,灰度级是0~255;
然后,进行归一化。对每一个当前的像素点,求0到这个像素点之间(包括0和这个点)一共有多少个图像上个的像素点,用这个像素点的个数除以总的像素点数;
最后,对每一个像素点,将归一化的后的像素点赋回到图像上。
void RealizeEqualize(IplImage* img, IplImage* dst)
{
IplImage* dst1 = cvLoadImage("images/74.jpg", 1);
dst = cvCreateImage(cvSize(dst1->width, dst1->height), IPL_DEPTH_8U, 1);
//img必须给出空间大小,才可以去接收灰度化之后的图像
img = cvCreateImage(cvSize(dst1->width, dst1->height), IPL_DEPTH_8U, 1);
//
灰度化 即使是灰度图像,也要做灰度化!!!
cvCvtColor(dst1, img, CV_BGR2GRAY);
//显示均衡化之前的图片
cvNamedWindow("原图", 1);
cvShowImage("原图", img);
int img_width = img->width;
int img_height = img->height;
int total_pixels = img_width*img_height;
int pixels[256] = { 0 };//统计像素
double equalize_pixels[256] = { 0 };//像素均衡化
int add_pixels[256] = { 0 };
int i, j;
//统计每一个像素值有多少个点
for (i = 0; i < img_height; i++)
{
for (j = 0; j < img_width; j++)
{
unsigned char grayvalue = img->imageData[i*img_width + j];
pixels[grayvalue]++;
}
}
//像素点归一化均衡化
for (i = 0; i < 256; i++)
{
for (j = i; j >= 0; j--)
{
add_pixels[i] += pixels[j];
}
equalize_pixels[i] = (double)add_pixels[i] / total_pixels;
}
//均衡化的像素点赋值到图像上
for (i = 0; i < dst->height; i++)
{
for (j = 0; j < dst->width; j++)
{
((uchar*)dst->imageData + i*dst->widthStep)[j] =
equalize_pixels[((uchar*)img->imageData + i*img->widthStep)[j]] * 255 + 0.5;
}
}
/*显示均衡化后的图片*/
cvNamedWindow("直方图均衡化", 1);
cvShowImage("直方图均衡化", dst);
cvWaitKey(0);
}
int main(){
IplImage* img = NULL;
IplImage* dst = NULL;
RealizeEqualize(img, dst);
cvReleaseImage(&img);
cvReleaseImage(&dst);
return 0;
}
效果图
此外,比较应该注意的是,图片即使是灰度图,也要做一次灰度化,因为只有灰度化之后每一次读取像素点的时候只要读一个通道就可以了,否则是要读取三个通道的,如果只读取一个通道的话,是错误的。