您的位置:首页 > 编程语言 > C语言/C++

c语言实现直方图均衡化

2014-07-28 12:55 141 查看
直方图均衡化部分是用c语言写的,最后用opencv显示原图像,处理后图像以及原图和处理后图的灰度直方图。

虽然做出来了,均衡化效果还可以,但不知道为什么处理后图像中有三条白线,真心搞不懂,有看出来问题的大神麻烦留言告诉我,谢谢。

(终于知道哪出问题了,原来是每行字节数求错了,改为LineByte=(width*8/8+3)/4*4;即可。)

实现原理参考:http://wenku.baidu.com/link?url=jEEUyr14TNX1B88qLrB0IMSOKMA-S8hNidKU2BqxmnEqnEgva6d18IC38NjlPE0OvCc7fsk2Pa3Uld6pj5YF-zY8yoes31r6HQBiNmLvutq

下面是代码:

#include "stdafx.h"
#include<stdio.h>
#include<windows.h>

#include<opencv2\highgui\highgui.hpp>
#include<opencv2\core\core.hpp>
#include<cv.h>

int main(void)
{
int width;//图像宽度
int height;//图像高度
RGBQUAD *pColorTable;
unsigned char *pBmpBuf,*pBmpBuf1;
BITMAPFILEHEADER bfhead;
BITMAPINFOHEADER bihead;

FILE *fp1=fopen("e:\\picture\\dog.bmp","rb");
if(fp1==0)
return 0;
fread(&bfhead,14,1,fp1);
fread(&bihead,40,1,fp1);
width=bihead.biWidth;
height=bihead.biHeight;

pColorTable=new RGBQUAD[256];
fread(pColorTable,4,256,fp1);
int LineByte=0;
LineByte=(width*1/4+1)*4;
<span style="white-space:pre">	</span>//LineByte=(width*8/8+3)/4*4;
pBmpBuf = new unsigned char[LineByte*height];

fread(pBmpBuf,LineByte*height,1,fp1);
fclose(fp1);

pBmpBuf1=new unsigned char[LineByte*height]; //用于存储均值化后的图像数据
//统计每个灰度级像素点的个数
int N[256]={0};
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
unsigned char *pb1,*pb2;
pb1=pBmpBuf+i*LineByte+j;
N[*pb1]++;
pb2=pBmpBuf1+i*LineByte+j;
*pb2=*pb1;
}
/*for(int i=0;i<256;i++ )
printf("%d  ",N[i]);*/

//统计最小与最大灰度值
int minGrayValue=255;
int maxGrayValue=0;
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
unsigned char *pb;
pb=pBmpBuf+i*LineByte+j;
if(*pb>maxGrayValue)
maxGrayValue=*pb;
else if(*pb<minGrayValue)
minGrayValue=*pb;
}
printf("%d ,%d\n",minGrayValue,maxGrayValue);//输出最大与最小灰度值

int x=maxGrayValue-minGrayValue+1;
float *p;
p=new float[x];

for(int i=0;i<x;i++)
{
*(p+i)=(float)N[i]/(float)(width*height);   //*(p+i)中存放的是灰度级为i的像素在整幅图像中出现
//的概率(即*(p+i)i=0,1,2,3...中存放的就是这幅图像归一化后的直方图)
}

float *c;
c=new float[x];      //定义c,用来存放累积的归一化直方图
for(int i=0;i<x;i++)  //对c进行初始化
{
*(c+i)=0;

}

for(int i=0;i<x;i++)
{
for(int j=0;j<=i;j++)
{
*(c+i)+=*(p+j);
}
}

for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
unsigned char *pb;
pb=pBmpBuf1+i*LineByte+j;
*pb=*(c+*pb)*(maxGrayValue-minGrayValue)+minGrayValue;
}

FILE *fp2=fopen("junhenghua.bmp","wb");
fwrite(&bfhead,14,1,fp2);
fwrite(&bihead,40,1,fp2);
fwrite(pColorTable,4,256,fp2);
fwrite(pBmpBuf1,LineByte*height,1,fp2);
fclose(fp2);

//显示原图与处理后的图像
IplImage *src1=cvLoadImage("e:\\picture\\dog.bmp");
IplImage *src2=cvLoadImage("junhenghua.bmp");

cvNamedWindow("原图");
cvNamedWindow("处理后图");

cvShowImage("原图",src1);
cvShowImage("处理后图",src2);

//显示原图像与处理后图像的灰度直方图
int size=256;
float range[]={0,255};
float *ranges[]={range};
CvHistogram *hist1=cvCreateHist(1,&size, CV_HIST_ARRAY,ranges,1);//创建一维直方图,
CvHistogram *hist2=cvCreateHist(1,&size, CV_HIST_ARRAY,ranges,1);
IplImage* gray1=cvCreateImage(cvGetSize(src1),8,1);
IplImage* gray2=cvCreateImage(cvGetSize(src2),8,1);
cvCvtColor(src1,gray1,CV_BGR2GRAY);
cvCvtColor(src2,gray2,CV_BGR2GRAY);
//vCvtColor(...),是Opencv里的颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。
//参数CV_RGB2GRAY是RGB到gray,
//参数CV_GRAY2RGB是gray到RGB

cvCalcHist(&gray1,hist1,0,0);//统计图像在[0 255]像素的均匀分布,将统计结果存在结构体中
cvCalcHist(&gray2,hist2,0,0);

//draw histogram-----

//统计直方图中的最大直方块
float histMax1=0,histMax2=0;
cvGetMinMaxHistValue(hist1,0,&histMax1,0);
cvGetMinMaxHistValue(hist2,0,&histMax2,0);
//创建一张一维直方图的“图”,横坐标为灰度级,纵坐标为像素个数
IplImage *grayHist1=cvCreateImage(cvSize(256*2,64*2),8,1);
IplImage *grayHist2=cvCreateImage(cvSize(256*2,64*2),8,1);
cvZero(grayHist1);
cvZero(grayHist2);

//分别将每个直方块的值绘制到图中
for(int i=0;i<255;i++)
{
float histValue=cvQueryHistValue_1D(hist1,i);
float nextValue=cvQueryHistValue_1D(hist1,i+1);

//计算直方块4个点的值
CvPoint pt1=cvPoint(i*2,64*2);
CvPoint pt2=cvPoint((i+1)*2,64*2);
CvPoint pt3=cvPoint((i+1)*2,(64-(nextValue/histMax1)*64)*2);
//nextValue/histMax是将i级像素点个数归一到0~1,在*64是使其高对在0~64之间
//由于opencv图像是以左上角为坐标原点,向右为x轴,向下时y轴,而显示的直方图是向上增长的,所以用64减,将其倒过来显示
CvPoint pt4=cvPoint(i*2,   (64-(histValue/histMax1)*64)*2);

int ptNum=5;
CvPoint pt[5];
pt[0]=pt1;
pt[1]=pt2;
pt[2]=pt3;
pt[3]=pt4;
pt[4]=pt1;

cvFillConvexPoly(grayHist1,pt,ptNum,cvScalar(255)); //填充直方块

}

for(int i=0;i<255;i++)
{
float histValue=cvQueryHistValue_1D(hist2,i);
float nextValue=cvQueryHistValue_1D(hist2,i+1);

//计算直方块4个点的值
CvPoint pt1=cvPoint(i*2,64*2);
CvPoint pt2=cvPoint((i+1)*2,64*2);
CvPoint pt3=cvPoint((i+1)*2,(64-(nextValue/histMax2)*64)*2);
//nextValue/histMax是将i级像素点个数归一到0~1,在*64是使其高对在0~64之间
//由于opencv图像是以左上角为坐标原点,向右为x轴,向下时y轴,而显示的直方图是向上增长的,所以用64减,将其倒过来显示
CvPoint pt4=cvPoint(i*2,   (64-(histValue/histMax2)*64)*2);

int ptNum=5;
CvPoint pt[5];
pt[0]=pt1;
pt[1]=pt2;
pt[2]=pt3;
pt[3]=pt4;
pt[4]=pt1;

cvFillConvexPoly(grayHist2,pt,ptNum,cvScalar(255)); //填充直方块

}

cvNamedWindow("grayHistogram1");
cvNamedWindow("grayHistogram2");
cvShowImage("grayHistogram1",grayHist1);
cvShowImage("grayHistogram2",grayHist2);

cvWaitKey(0);

system("pause");

return 0;
}


原图:



处理后图:



原图直方图:



均衡化后直方图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: