C语言实现直方图均衡化

 更新时间:2021年10月26日 08:28:43   作者:@leozhang  
这篇文章主要为大家详细介绍了C语言实现直方图均衡化,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

直方图均衡化部分是用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++版代码实现

    简单了解设计模式中的装饰者模式及C++版代码实现

    这篇文章主要介绍了简单了解设计模式中的装饰者模式及C++版代码实现,ConcreteComponent的引用(指针)也可以达到修饰的功能,需要的朋友可以参考下
    2016-03-03
  • 浅析C++中的多线程编程

    浅析C++中的多线程编程

    这篇文章主要为大家详细介绍了C++中的多线程编程,包括创建线程、同步线程、传递数据给线程以及异常处理等方面,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • C++ Vector 动态数组的实现

    C++ Vector 动态数组的实现

    这篇文章主要介绍了C++ Vector 动态数组的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • C++读写ini配置文件实现过程详解

    C++读写ini配置文件实现过程详解

    这篇文章主要介绍了C++读写ini配置文件实现过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • C语言实现链栈的步骤

    C语言实现链栈的步骤

    链栈是栈的链式存储结构,链栈可以用单链表的头插法实现,本文主要讲述了如何用c语言去实现链栈,感兴趣的朋友可以了解下
    2021-05-05
  • C语言实现简单飞机大战

    C语言实现简单飞机大战

    这篇文章主要为大家详细介绍了C语言实现简单飞机大战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • C语言 实现N阶乘的程序代码

    C语言 实现N阶乘的程序代码

    本篇文章是对c语言中实现N阶乘的程序代码进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C语言结构体使用之链表

    C语言结构体使用之链表

    这篇文章主要介绍了C语言结构体使用之链表,下面文章主要围绕结构体的概念和用法、结构体数组和结构体指针、包含结构体的结构体、结构体搭建链表方法、结构体及链表在产品应用场景等多个主题展开链表的相关资料,需要的小伙伴可以参考一下
    2022-03-03
  • VS Code C/C++环境配置教程(无法打开源文件“xxxxxx.h”或者检测到 #include 错误,请更新includePath)(POSIX API)

    VS Code C/C++环境配置教程(无法打开源文件“xxxxxx.h”或者检测到 #include 错误,请更新in

    这篇文章主要介绍了VS Code C/C++环境配置教程(无法打开源文件“xxxxxx.h” 或者 检测到 #include 错误。请更新includePath) (POSIX API),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • C/C++ Qt 给ListWidget组件增加右键菜单功能

    C/C++ Qt 给ListWidget组件增加右键菜单功能

    本篇文章给大家介绍ListWidget组件增加一个右键菜单,当用户在ListWidget组件中的任意一个子项下右键,我们让其弹出这个菜单,并根据选择提供不同的功能,感兴趣的朋友跟随小编一起看看吧
    2021-11-11

最新评论