C语言实现直方图均衡化

Miki ·
更新时间:2024-11-01
· 1487 次阅读

直方图均衡化部分是用c语言写的,最后用opencv显示原图像,处理后图像以及原图和处理后图的灰度直方图。

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

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

下面是代码:

#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; }

原图:

处理后图:

原图直方图:

均衡化后直方图:



直方图均衡 直方图均衡化 直方图 C语言

需要 登录 后方可回复, 如果你还没有账号请 注册新账号