邻域平均法
使用下面的模板进行邻域平均法滤波处理
1
9
[
1
1
1
1
1
∗
1
1
1
1
]
\frac19 \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1* & 1 \\ 1 & 1 & 1 \end{bmatrix}
91⎣⎡11111∗1111⎦⎤
- 上面这个模板的意思就是说,把这一圈算上中间一共九个点像素值加一块取个平均值再放回到中间,作为中间像素值,就这样把整个图片弄一遍,输出新图,所谓邻域平均法,就这么简单
差分法求图像边缘
- 差分概念应该很清楚了,就是比如一个数组 a a a,那么它的差分数组可以是 b [ i ] = a [ i + 1 ] − a [ i ] b[i]=a[i+1]-a[i] b[i]=a[i+1]−a[i]或者 b [ i ] = a [ i ] − a [ i − 1 ] b[i]=a[i]-a[i-1] b[i]=a[i]−a[i−1],一个前向差分,一个后向差分,那么这里公式已经给出 G [ f ( x , y ) ] = ∣ f ( i , j ) − f ( i + 1 , j ) ∣ + ∣ f ( i , j ) − f ( i , j + 1 ) ∣ G[f(x, y)]=| f(i, j) - f(i+1, j) | + |f(i, j )- f(i, j+1) | G[f(x,y)]=∣f(i,j)−f(i+1,j)∣+∣f(i,j)−f(i,j+1)∣,显然就是横向和纵向求两个前向差分绝对值加一起替代原像素点就好了
hdr.h
#ifndef __HDR_H__
#define __HDR_H__
struct bmphdr {
char signature[2];//文件类型
int size;//位图大小
short reserved[2];//两个保留字
int offset;//位图偏移位置
int hdr_size;//头文件大小
int width;//位图宽度
int height;//位图高度
short nr_planes;//位平面数
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
hdr.c
#include <stdio.h>
#include <memory.h>
#include "hdr.h"
struct bmphdr *get_header(char filename[])
{
FILE *fp;
struct bmphdr *hdr;
fp = fopen(filename, "rb");
if (!fp) {
printf("File open error or such file does not exist!\n");
return NULL;
}
hdr = (struct bmphdr *)malloc(sizeof(struct bmphdr));//分配空间
fread(hdr->signature, 2, 1, fp);
if (hdr->signature[0] != 'B' || hdr->signature[1] != 'M') {//如果打开文件的扩展名不是.bmp
printf("Not a bmp file!\n");
return NULL;
}
//读位图头文件信息
fread(&hdr->size, 4, 1, fp);
fread(hdr->reserved, 4, 1, fp);
fread(&hdr->offset, 4, 1, fp);
fread(&hdr->hdr_size, 4, 1, fp);
fread(&hdr->width, 4, 1, fp);
fread(&hdr->height, 4, 1, fp);
fread(&hdr->nr_planes, 2, 1, fp);
fread(&hdr->bits_per_pixel, 2, 1, fp);
fread(&hdr->compress_type, 4, 1, fp);
fread(&hdr->data_size, 4, 1, fp);
fread(&hdr->resol_hori, 4, 1, fp);
fread(&hdr->resol_vert, 4, 1, fp);
fread(&hdr->nr_colors, 4, 1, fp);
fread(&hdr->important_color, 4, 1, fp);
if (hdr->offset > 54)//获得位图有效信息,偏移量为54的时候读的才是位图第一个像素
fread(&hdr->info, 1024, 1, fp);
fclose(fp);//关闭文件
return hdr;
}
bmphdr.c
#include <stdio.h>
struct bmphdr {
char signature[2];//文件类型
int size;//位图大小
short reserved[2];//两个保留字
int offset;//位图偏移位置
int hdr_size;//头文件大小
int width;//位图宽度
int height;//位图高度
short nr_planes;//位平面数
short bits_per_pixel;//每像素的位数
int compress_type;//压缩类型
int data_size;//数据大小
int resol_hori;//水平
int resol_vert;//垂直
int nr_colors;
int important_color;
} header;
int main(int argc, char *argv[])
{
FILE *fp;
if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
exit(1);
}
fp = fopen(argv[1], "r");
if (!fp) {
printf("File open error or such file does not exist!\n");
exit(1);
}
fread(header.signature, 2, 1, fp);
if (header.signature[0] != 'B' || header.signature[1] != 'M') {
printf("Not a bmp file!\n");
exit(1);
}
//均为位图头信息
fread(&header.size, 4, 1, fp);//图像大小
fread(header.reserved, 4, 1, fp);
fread(&header.offset, 4, 1, fp);//偏移量
fread(&header.hdr_size, 4, 1, fp);//图像信息头大小,识别不同版本bmp文件
fread(&header.width, 4, 1, fp);//图像宽度
fread(&header.height, 4, 1, fp);//图像高度
fread(&header.nr_planes, 2, 1, fp);
fread(&header.bits_per_pixel, 2, 1, fp);
fread(&header.compress_type, 4, 1, fp);
fread(&header.data_size, 4, 1, fp);
fread(&header.resol_hori, 4, 1, fp);
fread(&header.resol_vert, 4, 1, fp);
fread(&header.nr_colors, 4, 1, fp);
fread(&header.important_color, 4, 1, fp);
fclose(fp);
printf("signature %c%c\n", header.signature[0], header.signature[1]);
printf("size %d\n", header.size);
printf("offset %d\n", header.offset);
printf("hdr_size %d\n", header.hdr_size);
printf("width %d\n", header.width);
printf("height %d\n", header.height);
printf("nr_planes %d\n", header.nr_planes);
printf("bits_per_pixel %d\n", header.bits_per_pixel);
printf("compress_type %d\n", header.compress_type);
printf("data_size %d\n", header.data_size);
printf("resol_hori %d\n", header.resol_hori);
printf("resol_vert %d\n", header.resol_vert);
printf("nr_colors %d\n", header.nr_colors);
printf("important_color %d\n", header.important_color);
printf("\n");
return 0;
}
邻域平均
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "hdr.h"
struct bmphdr *hdr;
unsigned char *bitmap, *to;
char buf[2048];
int di[8] = {0, 0, 1, 1, 1, -1, -1, -1};//八个方向
int dj[8] = {1, -1, 0, 1, -1, 0, 1, -1};
int main(int argc, char *argv[]){
int i, j, k, nr_pixels;//定义整数i,j用于函数循环
//nr_pixels为图像中像素的个数
FILE *fp, *fpnew;
unsigned pj, px;
argc = 3;
argv[1] = "testnoise.bmp";
argv[2] = "testzf.bmp";
int ii, jj;
if(argc != 3){
printf("Usage: %s <file_from> <file_to>\n", argv[0]);
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);
fread(bitmap, nr_pixels, 1, fp);
fclose(fp);
to = malloc(nr_pixels);
for(i=0;i<hdr->height;i++){
for(j=0;j<hdr->width;j++){
if(i == 0 || i == hdr->height- 1|| j == 0 ||j == hdr->width - 1){
to[i * hdr->width + j] = bitmap[i * hdr->width + j];
}else{
int ans = bitmap[i * hdr->width + j];
for(k=0;k<8;k++){
ii = i + di[k];
jj = j + dj[k];
ans += bitmap[ii * hdr->width + jj];
}
to[i * hdr->width + j] = ans * 1.0 / 9;
}
}
}
fpnew = fopen(argv[2], "wb+");
if(!fpnew){
printf("File create error!\n");
exit(1);
}
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(to, nr_pixels, 1, fpnew);
fclose(fpnew);
free(hdr);
free(bitmap);
return 0;
}
差分求图像边缘
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "hdr.h"
struct bmphdr *hdr;
unsigned char *bitmap, *to;
char buf[2048];
int di[8] = {0, 0, 1, 1, 1, -1, -1, -1};//八个方向
int dj[8] = {1, -1, 0, 1, -1, 0, 1, -1};
int main(int argc, char *argv[]){
int i, j, k, nr_pixels;//定义整数i,j用于函数循环
//nr_pixels为图像中像素的个数
FILE *fp, *fpnew;
unsigned pj, px;
argc = 3;
argv[1] = "test.bmp";
argv[2] = "testzf2.bmp";
int ii, jj;
if(argc != 3){
printf("Usage: %s <file_from> <file_to>\n", argv[0]);
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);
fread(bitmap, nr_pixels, 1, fp);
fclose(fp);
to = malloc(nr_pixels);
for(i=0;i<hdr->height;i++){
for(j=0;j<hdr->width;j++){
if(i == 0 || i == hdr->height- 1|| j == 0 ||j == hdr->width - 1){
to[i * hdr->width + j] = bitmap[i * hdr->width + j];
}else{
to[i * hdr->width + j] = abs(bitmap[i * hdr->width + j + 1] - bitmap[i *hdr->width + j]) +abs(bitmap[(i + 1) * hdr->width + j] - bitmap[i * hdr->width + j]);
}
}
}
fpnew = fopen(argv[2], "wb+");
if(!fpnew){
printf("File create error!\n");
exit(1);
}
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(to, nr_pixels, 1, fpnew);
fclose(fpnew);
free(hdr);
free(bitmap);
return 0;
}
原图
加入椒盐噪声
邻域平均法去椒盐(脉冲)噪声
图像边缘
- 之前做过中值滤波法去椒盐噪声的实验,邻域平均法相对于中值滤波法去椒盐噪声效果不好,原因很简单,从方法上考虑,一个取平均值,另一个取中位数,显然取中位数彻底抛弃了噪声,所以效果好是很自然的,但是高斯噪声就不行了