多媒体技术实验--BMP图像的直方图均衡化

今天把拖了几周的多媒体技术的实验作业给写完了,鉴于第一次实现关于图像处理的程序,爬上来记录一下做的过程以及犯过的错误。

以下为作业的要求。

课件中可以参考的代码如下:

关于直方图的均衡化就不做赘述了。

关于老师给的ppt,果真是不能全部照抄啊。。。血与泪的教训,多付出了一两个小时用来调试真是不会开心。

那么就从老师所给出的代码入手,由于之前没有接触过关于读取图像的2进制的程序,所以老师给出的代码还是很有意义的。

以下是我的代码:

#include <windows.h>
#include <stdio.h>
#define WIDTHBYTES(i) ((i+31)/32*4)
#define MAX 2048

BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
RGBQUAD lpRGB[256];
unsigned char ImgData[MAX][MAX];
int LineBytes;

float p[256] = {0};

//读入BMP

bool readBmp(char * BmpFileName)
{

 FILE *fp;

 fp = fopen(BmpFileName, "rb");
 if (fp == NULL)
  return 0;

 if((fread(&bf, sizeof(BITMAPFILEHEADER), 1, fp)) == 0)
  return 0;
 if((fread(&bi, sizeof(BITMAPINFOHEADER), 1, fp)) == 0)
  return 0;
 if((fread(lpRGB, sizeof(RGBQUAD), 256, fp)) == 0)
  return 0;
 LineBytes = (DWORD)WIDTHBYTES(bi.biWidth * bi.biBitCount);
 for (int i = bi.biHeight-1; i >= 0; i--)
  if((fread(ImgData[i], LineBytes, 1, fp)) == 0)
   return 0;
 
 fclose(fp);
 return 1;
}

//输出BMP
bool writeBmp(char * BmpFileName)
{
 FILE *fp;
 
 fp = fopen(BmpFileName, "wb");
 if(fp == NULL)
  return 0;

 if((fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, fp)) == 0)
  return 0;
 if((fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, fp)) == 0)
  return 0;
 if((fwrite(&lpRGB, sizeof(RGBQUAD), 256, fp)) == 0)
  return 0;

 LineBytes = (DWORD)WIDTHBYTES(bi.biWidth * bi.biBitCount);

 for (int i = bi.biHeight - 1; i >= 0; i--)
  if((fwrite(ImgData[i], LineBytes, 1, fp)) == 0)
   return 0;

 fclose(fp);
 return 1;
}

//生成直方图的每个灰度对应的值
bool histogram(int * Histog)
{
 int x = 0, y = 0, color = -1;
 for (x = 0; x < bi.biHeight; x++)
 {
  for (y = 0; y < bi.biWidth; y++)
  {
   color = ImgData[x][y];
   Histog[color]++;
  }
 }
 if (color == -1)
 {
  return 0;
 }
 return 1;
}

//输出直方图
bool writeHistog(int *Histog, char * FileName)
{
 FILE *fp;
 int numLine;
 char cnumLine[10];

 fp = fopen(FileName, "w");
 if(fp == NULL)
  return 0;
 
 for (numLine = 0; numLine < 256; numLine++)
 {
  sprintf(cnumLine, "%d", numLine);//将int型转化为string类型
  if((fputs(cnumLine, fp)) == EOF)
   return 0;
  if((fputc(' ', fp)) == EOF)
   return 0;
  sprintf(cnumLine, "%d", Histog[numLine]);
  if((fputs(cnumLine, fp)) == EOF)
   return 0;
  if((fputc('\n', fp)) == EOF)
   return 0;
 }
 fclose(fp);
 return 1;
}

//直方图均衡化
void histogEqualization(int * OldHistog, int * ChangeHistog)
{
 int gray = 0;
 int x = 0, y = 0;
 float n = (float)bi.biWidth * (float)bi.biHeight;

 for (gray = 0; gray < 256; gray ++)
 {
  p[gray] = (float)OldHistog[gray]/n;
  if (gray != 0)
  {
   p[gray] = p[gray] + p[gray - 1];
  }
 }

 for (gray = 0; gray < 256; gray++)
 {
  ChangeHistog[gray] = (int)(255 * p[gray]);
 }

 gray = -1;

 for(x = 0; x < bi.biHeight; x++)
  for(y = 0; y < bi.biWidth; y++)
  {
   gray = ImgData[x][y];
   ImgData[x][y] = ChangeHistog[gray]; //对每个像素点赋新值
  }
}

void usage_and_exit(char * program_name)
{
 printf("USAGE: %s path_for_image, path_for_oldhistogram, path_for_newhistogram, path_for_newimage\n",
  program_name);
 exit(1);
}

int main(int argc, char * argv[])
{
 int OldHistog[256] = {0};
 int NewHistog[256] = {0};
 int ChangeHistog[256] = {0};
 bool flag = 0;
 
 if(argc != 5)
  usage_and_exit(argv[0]);
 flag = readBmp(argv[1]);
 if (flag == 0)
 {
  printf("ERROR IN READBMP");
  return 0;
 }

 flag = histogram(OldHistog);
 if (flag == 0)
 {
  printf("ERROR IN HISTOGRAM FOR OLD IMAGE");
  return 0;
 }

 flag = writeHistog(OldHistog, argv[2]);
 if (flag == 0)
 {
  printf("ERROR IN WRITEHISTOGRAM FOR OLD IMAGE");
  return 0;
 }

 histogEqualization(OldHistog, ChangeHistog);

 flag = histogram(NewHistog);
 if (flag == 0)
 {
  printf("ERROR IN HISTOGRAM FOR NEW IMAGE");
  return 0;
 }
 
 flag = writeHistog(NewHistog, argv[3]);
 if (flag == 0)
 {
  printf("ERROR IN WRITEHISTOGRAM FOR NEW IMAGE");
  return 0;
 }

 flag = writeBmp(argv[4]);
 if (flag == 0)
 {
  printf("ERROR IN WRITEBMP FOR NEW IMAGE");
  return 0;
 }
 return 1;
}

 

照抄之后对于我的代码所犯的错误:

1.首先RGBQUAD *lpGRB这个指针的声明,我最开始没有注意到这个指针并没有赋值,导致我的程序在写完后运行崩溃,指向的是0x0000000这样一个地址。

2.unsigned char **ImgData的错误同1一样,依旧是没有赋值,报的错误好像是越界。

3.当把RGBQUAD *lpGRB改为RGBQUAD lpGRB并且后边的fread的第一个参数使用&lpRGB的时候,能够正常的输出结果,如果看到这篇日志的也是刚刚接触这个的你可以试一下,最后出来的结果反正我的是不知道什么的古怪颜色。因此这里事实上应该是改为lpRGB[256],似乎是用于放置灰度值的。。。这个我不是很清楚,给自己留个疑问。

4.在输出直方图这个函数中,我最开始使用fputc这个函数,输出的结果是乱码,由于读取数据的函数fputc只能读取char型,读入的整型造成了乱码,而使用sprintf函数可以将其他类型的变量转化为string类型,因此很好的帮助我输出直方图。

5.在设置变量的时候在路径的后边文件名后要加上文件后缀,第一个为.BMP 第二个为.TXT,第三个为.TXT 第四个为.BMP,否则会出错哟~

环境:VC6.0经检验,程序运行正常,结果正确。

6.新旧直方图的数组的定义我最开始定义其为全局变量,这样可以省略很多参数,但是调试的时候会发现,某些数组再进入函数之后,它本身所在地址的内容被改变了,猜测可能是被图像的某些数据所覆盖,还是要注意的一个地方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值