均值濾波、中值濾波等都是常見的圖像去噪手段,在知道了原理以後實施起來的方法其實都差不多。
這裏就放一份均值濾波的代碼,同樣還是針對24位bmp圖像來做的:
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
//位圖文件頭定義;
typedef struct tagBITMAPFILEHEADER{
// WORD bfType;//單獨讀取,結構體中就不定義了
DWORD bfSize;//文件大小
WORD bfReserved1;//保留字
WORD bfReserved2;//保留字
DWORD bfOffBits;//從文件頭到實際位圖數據的偏移字節數
}BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;//信息頭大小
DWORD biWidth;//圖像寬度
DWORD biHeight;//圖像高度
WORD biPlanes;//位平面數,必須爲1
WORD biBitCount;//每像素位數
DWORD biCompression; //壓縮類型
DWORD biSizeImage; //壓縮圖像大小字節數
DWORD biXPelsPerMeter; //水平分辨率
DWORD biYPelsPerMeter; //垂直分辨率
DWORD biClrUsed; //位圖實際用到的色彩數
DWORD biClrImportant; //本位圖中重要的色彩數
}BITMAPINFOHEADER; //位圖信息頭定義
//像素信息
typedef struct tagIMAGEDATA
{
BYTE blue;
BYTE green;
BYTE red;
}DATA;
BITMAPFILEHEADER strHead;
BITMAPINFOHEADER strInfo;
int h,w,size;
WORD bfType;
void meanFiltering(const DATA* src, DATA* target);
void printImage(const DATA* src, string filename);
int main(){
FILE *fpi;
fpi=fopen("input.bmp","rb");
if(fpi != NULL){
//先讀取文件類型
fread(&bfType,1,sizeof(WORD),fpi);
if(0x4d42!=bfType) {
cout<<"Error: The file is not a bmp image!"<<endl;
return 0;
}
//讀取bmp文件的文件頭和信息頭
fread(&strHead,1,sizeof(tagBITMAPFILEHEADER),fpi);
fread(&strInfo,1,sizeof(tagBITMAPINFOHEADER),fpi);
h=strInfo.biHeight;
w=strInfo.biWidth;
if(w % 4 != 0)
w = (w/4+1)*4;
size=strInfo.biSizeImage/3;
DATA *imgdata=new DATA[size];
fread(imgdata,1,sizeof(DATA)*size,fpi); //讀取bmp數據信息
fclose(fpi);
DATA *mean = new DATA[size];
memset(mean, 0, sizeof(DATA)*size);
meanFiltering(imgdata, mean);
printImage(mean, "meanFiltering.bmp");
delete[] mean;
delete[] imgdata;
}
else
cout<<"Can't open the input file!"<<endl;
return 0;
}
void meanFiltering(const DATA* src, DATA* target){
int redTotal = 0;
int blueTotal = 0;
int greenTotal = 0;
for(int i = 0; i < h; i++){
for(int j = 0; j < w; j++){
//不處理最外圍的一圈
if( i == 0 || i == h-1 || j == 0 || j == w-1 ){
target[i*w+j] = src[i*w+j];
}
else{
redTotal = 0;
blueTotal = 0;
greenTotal = 0;
/*
(j-1,i+1) | (j,i+1) | (j+1,i+1)
(j-1,i) | (j,i) | (j+1,i)
(j-1,i-1) | (j,i-1) | (j+1,i-1)
*/
redTotal = src[(i+1)*w+(j-1)].red + src[(i+1)*w+(j+1)].red +
src[(i+1)*w+(j+1)].red + src[(i)*w+(j-1)].red + src[(i)*w+(j)].red
+ src[(i)*w+(j+1)].red + src[(i-1)*w+(j-1)].red + src[(i-1)*w+(j)].red
+ src[(i-1)*w+(j+1)].red;
blueTotal = src[(i+1)*w+(j-1)].blue + src[(i+1)*w+(j+1)].blue +
src[(i+1)*w+(j+1)].blue + src[(i)*w+(j-1)].blue + src[(i)*w+(j)].blue
+ src[(i)*w+(j+1)].blue + src[(i-1)*w+(j-1)].blue + src[(i-1)*w+(j)].blue
+ src[(i-1)*w+(j+1)].blue;
greenTotal = src[(i+1)*w+(j-1)].green + src[(i+1)*w+(j+1)].green +
src[(i+1)*w+(j+1)].green + src[(i)*w+(j-1)].green + src[(i)*w+(j)].green
+ src[(i)*w+(j+1)].green + src[(i-1)*w+(j-1)].green + src[(i-1)*w+(j)].green
+ src[(i-1)*w+(j+1)].green;
target[i*w+j].red = (BYTE) (redTotal / 9);
target[i*w+j].blue = (BYTE) (blueTotal / 9);
target[i*w+j].green = (BYTE) (greenTotal / 9);
}
}
}
}
void printImage(const DATA* output, string filename){
FILE *fpo1;
fpo1=fopen(filename.c_str(),"wb");
if(fpo1==NULL){
cout<<"Can't open the output file: "<<filename<<" !"<<endl;
return;
}
fwrite(&bfType,1,sizeof(WORD),fpo1);
fwrite(&strHead,1,sizeof(tagBITMAPFILEHEADER),fpo1);
fwrite(&strInfo,1,sizeof(tagBITMAPINFOHEADER),fpo1);
fwrite(output,1,sizeof(DATA)*(size),fpo1);
fclose(fpo1);
}
濾波前:
濾波後: