/// <summary>
/// 程序功能:c语言实现纯高斯模糊
/// 系统Ubuntu 15.10,GCC开发环境,编程语言C,最新整理时间 whd 2016.9.2。
/// 参考代码:https://github.com/Duwaz/Gaussian_Blur
/// <remarks> 1: 能处理24位BMP格式图像。</remarks>
/// <remarks> 2: 主程序无参数,默认处理工程目录下的input.bmp,处理后的结果为output.bmp。</remarks>
/// <remarks> 3: 处理效果由高斯模糊半径决定:GaussBlur(bmp_t*, double)函数的第二个参数</remarks>
/// </summary>
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include <math.h>
#define SQRT_2PI 2.506628274631
//自定义数据类型
typedef unsigned long       DWORD; //四个字节
typedef int                 BOOL;
typedef unsigned char       BYTE; //一个字节
typedef unsigned short      WORD; //一个字节
//位图信息头结构体定义
typedef struct tagBITMAPINFOHEADER
{WORD   bfType;  //两个字节DWORD  bfileSize;DWORD  bfReserved;DWORD  bOffBits;DWORD  biSize;   //4个字节long   biWidth;  //4个字节long   biHeight;WORD   biPlanes;WORD   biBitCount;DWORD  biCompression;DWORD  biSizeImage;long   biXPelsPerMeter;long   biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;
} __attribute__((packed))BITMAPINFOHEADER,*PBITMAPINFOHEADER;  //字节对齐
typedef struct
{BITMAPINFOHEADER header;  //信息头char *data;//图像数据
} bmp_t;
int win_size(double);
double Gauss(double, 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(void)
{  char *InputName, *OutputName;  //输入输出图像文件名变量FILE *InputFile, *OutputFile;  //输入输出图像文件bmp_t *bmp = NULL, *blur = NULL;InputName = "input.bmp"; OutputName = "output.bmp";if(!(InputFile=fopen(InputName, "r")))  //图像文件打开函数,打不开返回,提示找不到文件{printf("File not found\n");return 1;}bmp = bmp_open(InputFile);   //图像文件读取操作,前面必须有打开的操作才能读取文件数据fclose(InputFile);//关闭文件OutputFile = fopen(OutputName, "wb"); //打开并创建输出文件if (OutputFile == NULL) {printf("Can't open %s\n", OutputName);return 1;}blur = GaussBlur(bmp, 4.0); //模糊处理并返回处理后数据bmp_write(blur, OutputFile);//将处理后数据存放到新建的文件中 fclose(OutputFile); //关闭文件bmp_free(bmp);//释放存放读取数据的内存free(blur);//释放处理后图像数据的内存return 0;
}
/// <summary>
/// 函数功能:给定一个BMP图像文件,将其中的数据读取出来,并返回图像数据
/// 函数返回:图像的数据(信息头和数据)
/// 知识点:如何读取一个图像文件的数据
/// </summary>
/// <param name="f">图像文件存放位置地址。</param>
bmp_t *bmp_open(FILE *f)
{bmp_t *bmp;bmp = (bmp_t *)malloc(sizeof(bmp_t));bmp->data = NULL;if (fread(&(bmp->header), sizeof(BITMAPINFOHEADER), 1, f)) {bmp->data = (char*)malloc(bmp->header.biSizeImage);if (fread(bmp->data, bmp->header.biSizeImage, 1, f))printf("图像读取成功\n");printf("Width: %ld\n", bmp->header.biWidth);printf("Height: %ld\n", bmp->header.biHeight);printf("BitCount: %d\n\n", (int)bmp->header.biBitCount);return bmp;}fprintf(stderr, "Error reading file");bmp_free(bmp);return NULL;
}
/// <summary>
/// 函数功能:释放存放图像数据的内存
/// 函数返回:无
/// 知识点:释放图像数据内存
/// </summary>
/// <param name="bmp">图像数据变量。</param>
void bmp_free(bmp_t *bmp)
{if (bmp == NULL) return;if (bmp->data != NULL) free(bmp->data);free(bmp);
}
/// <summary>
/// 函数功能:将图像数据写入到图像文件中
/// 函数返回:写入数据的个数
/// 知识点:将数据写入文件中(将数值从内存写入文件中)
/// </summary>
/// <param name="bmp">图像数据变量。</param>
/// <param name="out">文件流。</param>
int bmp_write(bmp_t *bmp, FILE *out) {return fwrite(&(bmp->header), sizeof(BITMAPINFOHEADER), 1, out)&& fwrite(bmp->data, bmp->header.biSizeImage, 1, out);
}
/// <summary>
/// 函数功能:模糊窗的大小(根据高斯半径和模糊半径满足3sigma原则)
/// 函数返回:模糊窗的大小,即长或宽(长=宽)
/// 知识点:高斯模糊的3*sigma原则
/// </summary>
/// <param name="sigma">高斯核函数的参数sigma</param>
int win_size(double sigma)
{return (1 + (((int)ceil(3 * sigma)) * 2));
}
/// <summary>
/// 函数功能:单像素点计算高斯系数
/// 函数返回:高斯系数
/// 知识点:高斯系数计算公式
/// </summary>
/// <param name="sigma">高斯核函数的参数sigma</param>
/// <param name="x">当前像素距离模糊窗中心的距离</param>
double Gauss(double sigma, double x)
{return exp(-(x * x) / (2.0 * sigma * sigma)) / (sigma * SQRT_2PI);
}
/// <summary>
/// 函数功能:计算高斯模糊窗下的每个像素对应的权值,计算一半就够了,因为是权值是对称的(一维高斯)
/// 函数返回:模糊窗下每个像素的权值
/// 知识点:模糊窗下的各点的高斯系数(一维数组)
/// </summary>
/// <param name="sigma">高斯核函数的参数sigma</param>
/// <param name="win_size">模糊窗的大小</param>
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;
}
/// <summary>
/// 函数功能:高斯模糊实现函数
/// 函数返回:模糊后的图像
/// 知识点:模糊窗下的各点的高斯系数(数组)
/// </summary>
/// <param name="src">待模糊的图像</param>
/// <param name="sigma">模糊半径(高斯核函数参数)</param>
/// <remarks> rgb三通道分别处理</remarks>
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;
}

算法处理效果:sigma=4.0

【算法学习】高斯模糊算法相关推荐

  1. 算法学习--排序算法--插入排序

    算法学习--排序算法--插入排序 插入排序算法 代码实现 插入排序算法 插入排序(Insertion sort)是一种简单直观且稳定的排序算法.如果有一个已经有序的数据序列,要求在这个已经排好的数据序 ...

  2. php算法学习,php算法学习之动态规划

    动态规划程序设计是对解最优化问题的一种途径.一种方法,最终问题的最优解可以通过前面子问题的最优解推导出来. 对于动态规划这个算法,自己学习的还不是很透彻,简单的总结自己学习的感受是: 动态规划思想中融 ...

  3. [算法学习]模拟退火算法(SA)、遗传算法(GA)、布谷鸟算法(CS)、人工蜂群算法(ABC)学习笔记---附MATLAB注释代码

    目录 1.模拟退火算法(Simulated Annealing,SA) 1.1 本质: 1.2 算法思想 1.3 SA流程图 1.4 模拟退火过程 1.5 SA解决TSP问题 1.6 SA改进方向 1 ...

  4. 算法学习之算法的引入

    一.算法的起始 1.第一次尝试 如果 a+b+c=1000,且 a^2+b^2=c^2(a,b,c 为自然数),如何求出所有a.b.c可能的组合? (可以考虑到百钱白鸡)  枚举法 # 注意是三重循环 ...

  5. 【C语言】算法学习·KMP算法

    KMP算法(全称Knuth-Morris-Pratt字符串查找算法,由三位发明者的姓氏命名)是可以在文本串s中快速查找模式串p的一种算法. 要想知道KMP算法是如何减少字符串查找的时间复杂度的,我们不 ...

  6. 【C语言】算法学习·回溯算法

    目录 一.全排列问题 二.N 皇后问题 三.最后总结 回溯算法基本框架 解决一个回溯问题,实际上就是一个决策树的遍历过程.你只需要思考 3 个问题: 1.路径:也就是已经做出的选择. 2.选择列表:也 ...

  7. C++算法学习(贪心算法)

    贪心算法 1.目标 2.方法 3.例题 [122. 买卖股票的最佳时机 II](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-s ...

  8. C++算法学习(动态规划算法)

    动态规划算法 1.目标 2.方法 3.过程 4.例题 (1)[力扣:5. 最长回文子串](https://leetcode-cn.com/problems/longest-palindromic-su ...

  9. C++算法学习(回溯算法)

    回溯算法 1.目标 2.方法 3.具体思路 4.例题 (1)[力扣:10. 正则表达式匹配](https://leetcode-cn.com/problems/regular-expression-m ...

  10. 机器学习算法学习——RBF算法原理图解

    1.隐含层(径向基层)算法 输入为列向量 R(看作R维向量空间内一点的坐标) 隐含层与之对应的是一个矩阵 W1 (看作S个向量空间的中心点坐标组合成的矩阵) 分别计算欧式距离得到||dist|| 与连 ...

最新文章

  1. nRF52832的UICR
  2. 配置防盗链、 访问控制Directory 、访问控制FilesMatch
  3. Python编程:制作电子相册
  4. UVa 10642 - Can You Solve It?
  5. Hibernate中的merge使用详情解说
  6. cocos2d-x初探学习笔记(17)--瓦片地图集
  7. 为什么要先装IIS后装.Net Framework?
  8. php框架中间件,【框架十】Coder PHP Framework 中间件
  9. Json扩展 (转)
  10. C# 生成随机数重复问题
  11. 【Matlab学习笔记】【编程实例】二(将两幅灰度图片调整成相同的尺寸,然后左右拼接到一起)
  12. Fiddler4 抓取Chrome浏览器的Http(s)
  13. android 基带版本,基带是什么 基带版本是什么
  14. 智慧环卫全流程设计方案
  15. iOS内存扫描工具实现
  16. 早秋山居 --温庭筠[唐.五言律诗]
  17. 对卡巴斯基发现的一个将shellcode写入evenlog的植入物的复现
  18. matlab将图片导入工作区,matlab数据的导入和导出,以matlab工作区workspace为source和destination...
  19. java 读取二进制文件_用Java读取二进制文件
  20. 信息中心网络ICN的物联网应用调研

热门文章

  1. jQuery点击行选中或者取消CheckBox
  2. 232接口针脚定义_VGA接口定义,详细图文资料
  3. maven依赖的作用域\<scope>
  4. 内核功能导致重启_错误信息:VS2010 Profiler导致Win7重启
  5. java求实数的整数部分和小数部分_输入一个浮点数,并输出该数的整数部分和小数部分...
  6. 网页实现语音对讲_GB28181实现摄像头语音对讲 - web音频采集调用示例
  7. 升级总代分享思路_定档了!升级了!1月23日《我家那闺女》第二季要给你“好看”...
  8. opencv_找cv::Mat中的最大值和最小值
  9. OpenCV_(Using GrabCut extract the foreground object) 使用 GrabCut 算法提取前景物体
  10. 可计算性与半可计算性 ---半可计算与半可判定