一、实验目的
图像变换是数字图像处理中的一种综合变换,如直方图变换、几何变换等。通过本实验,掌握邻域平均法滤波处理。
二、实验任务
1.设计程序,用领域平均法(模板的大小为3×3),进行去噪处理。并将其与上次试验的中值滤波法去早处理对比,比较着两种方法去噪效果的好坏并分析具体原因。
三、实验环境
本实验在Windows平台上进行,对内存及cpu主频无特别要求,使用MINGW(gcc)编译器。
四、实验步骤
邻域平均法滤波处理
1. 利用第一次实验课提供的 dhc.h 和 dhc.c 文件以获取位图的高、宽, 以及从文件头到实际的位图数据的偏移字节数,从而实现对位图实际数据的操作。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "hdr.h"
2. 定义
//定义结构指针
struct bmphdr *hdr;
//定义用于直方图变量
unsigned char *bitmap,*newbitmap;//, new_color[256];
//定义结构指针
struct bmphdr *hdr;
//定义用于直方图变量
unsigned char *bitmap,*newbitmap;//, new_color[256];
int newwide,newheight;
//定义计算灰度分布,灰度累计分布的数组
int count[256], acum[256];
double gray;
3.具体实现
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "hdr.h"
//定义结构指针
struct bmphdr *hdr;
//定义用于直方图变量
unsigned char *bitmap,*newbitmap;//, new_color[256];
int newwide,newheight;
//定义计算灰度分布,灰度累计分布的数组
int count[256], acum[256];
double gray;
int main()
{
//定义整数 i, j 用于函数循环时的,nr_pixels为图像中像素的个数
int i, j, nr_pixels,newnr_pixels;
//定义两个文件指针分别用于提取原图像的数据和生成直方图均衡化后的图像
FILE *fp, *fpnew;
int argc;
char*argv[20];
argc=3;
argv[1]="testnoise.bmp";
argv[2]="testzf.bmp";
if (argc != 3) {//参数输入出错显示
printf("please input the name of input and out bitmap files\n");
exit(1);
}
hdr = get_header(argv[1]);// 获取位图文件相关信息
if (!hdr) exit(1);
fp = fopen(argv[1], "rb");//以二进制可读方式打开输入位图文件
if (!fp) {
printf("File open error!\n");
exit(1);
}
fseek(fp, hdr->offset, SEEK_SET);// 文件指针指向数据区域
nr_pixels = hdr->width * hdr->height;//计算位图像素的个数
bitmap = malloc(nr_pixels); //读取位图数据到bitmap中
fread(bitmap, nr_pixels, 1, fp);
fclose(fp);
//将新位图相对于原位图进行扩展,宽度和高度都加2
newheight=hdr->height+2;
newwide=hdr->width+2;
newnr_pixels=newheight*newwide;//新位图的大小
newbitmap=malloc(newnr_pixels);//新建一个位图指针
for(i=0;i<newheight;i++)//先将新位图像素都设为0
{
for(j=0;j<newwide;j++)
{
newbitmap[newwide*i+j]=0;
}
}
for(i=0;i<hdr->height;i++)//将原位图的像素值赋值给新位图
{
for(j=0;j<hdr->width;j++)
{
newbitmap[newwide*(i+1)+j]=bitmap[hdr->width*i+j];
}
}
for(i=1;i<newheight-1;i++)//邻域平均法进行图像处理
{
for(j=1;j<newwide-1;j++)
{//计算新的灰度值
gray=(double)(newbitmap[newwide*(i-1)+j-1]+
newbitmap[newwide*i+j-1]+
newbitmap[newwide*(i+1)+j-1]+
newbitmap[newwide*(i-1)+j]+
newbitmap[newwide*(i+1)+j]+
newbitmap[newwide*i+j]+
newbitmap[newwide*(i-1)+j+1]+
newbitmap[newwide*i+j+1]+
newbitmap[newwide*(i+1)+j+1])/9;
bitmap[hdr->width*(i-1)+j-1] =(int)gray;//将灰度值赋值给bitmap
}
}
fpnew = fopen(argv[2], "wb+");
//由于位图文件的头部信息并没有因直方图均衡化而改变,因此输出图像的头部信息从原位图文件中拷贝即可:
fwrite(hdr->signature, 2, 1, fpnew);
fwrite(&hdr->size, 4, 1, fpnew);
fwrite(hdr->reserved, 4, 1, fpnew);
fwrite(&hdr->offset, 4, 1, fpnew);
fwrite(&hdr->hdr_size, 4, 1, fpnew);
fwrite(&hdr->width, 4, 1, fpnew);
fwrite(&hdr->height, 4, 1, fpnew);
fwrite(&hdr->nr_planes, 2, 1, fpnew);
fwrite(&hdr->bits_per_pixel, 2, 1, fpnew);
fwrite(&hdr->compress_type, 4, 1, fpnew);
fwrite(&hdr->data_size, 4, 1, fpnew);
fwrite(&hdr->resol_hori, 4, 1, fpnew);
fwrite(&hdr->resol_vert, 4, 1, fpnew);
fwrite(&hdr->nr_colors, 4, 1, fpnew);
fwrite(&hdr->important_color, 4, 1, fpnew);
if (hdr->offset > 54)
fwrite(hdr->info, (hdr->offset - 54), 1, fpnew);
//直方图均衡化的数据(bitmap)赋值
fwrite(bitmap,nr_pixels,1,fpnew);
//关闭
fclose(fpnew);
//释放内存(优化程序必需)
free(hdr);
free(bitmap);
return 0;
}
hdr.h
#ifndef __HDR_H__
#define __HDR_H__
struct bmphdr
{
char signature[2]; //文件类型,字符串"BM"
int size; //文件大小
short reserved[2]; //保留字
int offset; //从文件到实际位图数据的偏移量
int hdr_size; //文件头的长度
int width; //图像的宽度,单位是像素
int height; //图像的高度,单位是像素
short nr_planes; //位平面数,值为1
short bits_per_pixel;//每个像素的位数
int compress_type; //指定压缩类型
int data_size; //位图数据大小
int resol_hori; //水平
int resol_vert; //垂直
int nr_colors; //使用的颜色数
int important_color; //图像中重要的颜色数
char info[1024];
};
struct bmphdr *get_header(char filename[]); //得到文件头信息
#endif
4.实验结果
中值滤波处理 邻域平均法滤波处理
5.比较着两种方法去噪效果的好坏并分析具体原因。
由上面实验结果可知,对于椒盐噪声中值滤波处理的去噪效果更好。椒盐噪声,是一种随机出现的白点或者黑点。而均值滤波器是一种最常用的线性低通平滑滤波器,可抑制图像中的加性噪声,但同时也使图像变得模糊;中值滤波器是一种最常用的非线性平滑滤波器,可消除图像中孤立的噪声点,又可产生较少的模糊。所以对于椒盐噪声中值滤波的处理效果更好。