纯高斯模糊源码

本文介绍了一种基于C语言实现的高斯模糊算法,通过定义结构体和编写关键函数完成图像处理任务。该算法适用于不同尺寸的位图文件,并展示了在不同图像大小下模糊效果的变化。
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <conio.h>
#include <malloc.h>
#include "time.h"  
#define SQRT_2PI 2.506628274631

#pragma pack(push,2)
typedef struct
{
	uint16_t bfType;
	uint32_t bfileSize;
	uint32_t bfReserved;
	uint32_t bOffBits;
	uint32_t biSize;
	uint32_t biWidth;
	uint32_t biHeight;
	uint16_t biPlanes;
	uint16_t biBitCount;
	uint32_t biCompression;
	uint32_t biSizeImage;
	uint32_t biXPelsPerMeter;
	uint32_t biYPelsPerMeter;
	uint32_t biClrUsed;
	uint32_t biClrImportant;
} bmp_header_t;
#pragma pack(pop)

typedef struct
{
	bmp_header_t header;
	char *data;
} bmp_t;

int win_size(double);
double Gauss(double, double);
double *GaussAlgorithm(int, double);
void bmp_free(bmp_t *);
bmp_t *bmp_open(FILE *);
int bmp_write(bmp_t*, FILE*);
bmp_t *GaussBlur(bmp_t*, double);

int main(int argc, char** argv)
{
	char *InputName, *OutputName;
	FILE *InputFile, *OutputFile;
	bmp_t *bmp = NULL, *blur = NULL;
	clock_t start, finish;     
	double duration; 
	InputName = "input.bmp"; OutputName = "output.bmp";
	if (0 != fopen_s(&InputFile, InputName, "rb"))
	{
		printf("File not found\n");
		_getch();
		return 1;
	}
	bmp = bmp_open(InputFile);
	fclose(InputFile);

	OutputFile = fopen(OutputName, "wb");
	if (OutputFile == NULL) {
		fprintf(stderr, "Can't open %s\n", OutputName);
		return EXIT_FAILURE;
	}
	start = clock();  
	blur = GaussBlur(bmp, 4.0);
	finish = clock();      
    duration = (double)(finish - start) / CLOCKS_PER_SEC;      
    printf( "%f seconds\n", duration );      
	bmp_write(blur, OutputFile);  
	fclose(OutputFile);
	bmp_free(bmp);
	free(blur);
	getchar();

	return 0;
}

bmp_t *GaussBlur(bmp_t *src, double sigma) 
{
	int	row, col, col_r, col_g, col_b, winsize, halfsize, k, count, rows, count1, count2, count3;
	int width, height;
	double  row_g, row_b, row_r, col_all;
	unsigned char  r_r, r_b, r_g, c_all;
	char *tmp;
	double *algorithm;

	count=0;
	width = 3*src->header.biWidth; height = src->header.biHeight;

	if ((width % 4) != 0) width += (4 - (width % 4)); 
	bmp_t *blur;
	blur = (bmp_t*)malloc(sizeof(bmp_t));
	blur->header = src->header;
	blur->header.biWidth = src->header.biWidth;
	blur->header.biHeight = src->header.biHeight;
	blur->header.biSizeImage = width * blur->header.biHeight;
	blur->data = (char*)malloc(blur->header.biSizeImage);

	winsize = win_size(sigma);
	algorithm = GaussAlgorithm(winsize, sigma); 
	winsize *= 3; 
	halfsize = winsize / 2;

	tmp = (char*)calloc(width * height, sizeof(char)); 
	
	for (row = 0; row < height; row++)
	{
		col_r = 0;
		col_g = 1;
		col_b = 2;
		for (rows = 0; rows < width; rows += 3)
		{
			row_r = row_g = row_b = 0.0;
			count1 = count2 = count3 = 0;
		
			for (k = 1; k < winsize; k += 3)
			{
				if ((k + col_r - halfsize >= 0) && (k + col_r - halfsize < width))
				{
					r_r = *(src->data + row * width + col_r + k - halfsize);
					row_r += (int)(r_r)* algorithm[count1];
					count1++;
				}
				if ((k + col_g - halfsize >= 0) && (k + col_g - halfsize < width))
				{
					r_g = *(src->data + row * width + col_g + k - halfsize);
					row_g += (int)(r_g)* algorithm[count2];
					count2++;
				}

				if ((k + col_b - halfsize >= 0) && (k + col_b - halfsize < width))
				{
					r_b = *(src->data + row * width + col_b + k - halfsize);
					row_b += (int)(r_b)* algorithm[count3];
					count3++;
				}
			}

			*(tmp + row * width + col_r) = (unsigned char)(ceil(row_r));
			*(tmp + row * width + col_g) = (unsigned char)(ceil(row_g));
			*(tmp + row * width + col_b) = (unsigned char)(ceil(row_b));
			col_r += 3;
			col_g += 3;
			col_b += 3;
		}
	}
	
	winsize /= 3;
	halfsize = winsize / 2;
	for (col = 0; col < width; col++)
		for (row = 0; row < height; row++)
		{
		col_all = 0.0;
		for (k = 0; k < winsize; k++)
			if ((k + row - halfsize >= 0) && (k + row - halfsize < height))
			{
			c_all = *(tmp + (row + k - halfsize) * width + col);
			col_all += ((int)c_all) * algorithm[k];
			}
		*(blur->data + row * width + col) = (unsigned char)(ceil(col_all));
		}
	
	free(tmp);
	free(algorithm);

	return blur;
}

double* GaussAlgorithm(int win_size, double sigma)
{
	int wincenter, x;
	double *kern, sum = 0.0;
	wincenter = win_size / 2;
	kern = (double*)calloc(win_size, sizeof(double));

	for (x = 0; x < wincenter + 1; x++)
	{
		kern[wincenter - x] = kern[wincenter + x] = Gauss(sigma, x);
		sum += kern[wincenter - x] + ((x != 0) ? kern[wincenter + x] : 0.0);
	}
	for (x = 0; x < win_size; x++)
		kern[x] /= sum;

	return kern;
}

double Gauss(double sigma, double x)
{
	return exp(-(x * x) / (2.0 * sigma * sigma)) / (sigma * SQRT_2PI);
}

int win_size(double sigma)
{
	return (1 + (((int)ceil(3 * sigma)) * 2)); 
}

bmp_t *bmp_open(FILE *f) {
	bmp_t *bmp;
	bmp = (bmp_t *)malloc(sizeof(bmp_t));
	bmp->data = NULL;

	if (fread(&(bmp->header), sizeof(bmp_header_t), 1, f)) {
		bmp->data = (char*)malloc(bmp->header.biSizeImage);
		if (fread(bmp->data, bmp->header.biSizeImage, 1, f))
			return bmp;
	}
	fprintf(stderr, "Error reading file");
	bmp_free(bmp);
	return NULL;
}

int bmp_write(bmp_t *bmp, FILE *out) {
	return fwrite(&(bmp->header), sizeof(bmp_header_t), 1, out)
		&& fwrite(bmp->data, bmp->header.biSizeImage, 1, out);
}

void bmp_free(bmp_t *bmp)
{
	if (bmp == NULL) return;
	if (bmp->data != NULL) free(bmp->data);
	free(bmp);
}

电脑配置(开发环境VS2010):


原图像:

模糊后:


图像大小(5000*3000bmp图像),模糊半径sigma=4.0(≈12*12的模糊核),从处理效果上看,模糊并没有自己想想的严重,主要是图片比较大,细节分布距离比较大的缘故。所以大图像使用大的模糊核,小图像使用小的模糊核是有道理的。

处理时间:


图像大小(1024*681)模糊半径同上




图像大小(1024*685)模糊半径同上

我一开始练习,开始慢慢练习,ㄟ(⊙ω⊙ㄟ)哈!!




可见同样的模糊半径处理较小的图片,模糊的效果会更加的明显!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌三角猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值