圖像的均值濾波(mean filtering)

均值濾波、中值濾波等都是常見的圖像去噪手段,在知道了原理以後實施起來的方法其實都差不多。

這裏就放一份均值濾波的代碼,同樣還是針對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);
}


濾波前:




濾波後:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章