图像算法之高斯模糊(灰度图像)

2023-10-31

1、函数定义

// 高斯模糊
struct stPGMImage* GaussianBlur(struct stPGMImage* image, unsigned int  radius);

2、函数实现

struct stPGMImage* GaussianBlur(struct stPGMImage* image, unsigned  int  radius)
{
	unsigned  int  width = image->width;
	unsigned  int  height = image->height;
	unsigned  int  channels = 1;

	struct stPGMImage* result = (struct stPGMImage*)malloc(sizeof(struct stPGMImage));
	result->height = image->height;
	result->width = image->width;
	result->maxraw = image->maxraw;
	result->data = (unsigned char*)malloc(sizeof(unsigned char) * result->width * result->height * channels);
	memcpy(result->data, image->data, image->height * image->width);

	radius = min(max(1, radius), 248);
	unsigned  int  kernelSize = 1 + radius * 2;
	unsigned  int* kernel = (unsigned  int*)malloc(kernelSize * sizeof(unsigned  int));
	memset(kernel, 0, kernelSize * sizeof(unsigned  int));
	int(*mult)[256] = (int(*)[256]) malloc(kernelSize * 256 * sizeof(int));
	memset(mult, 0, kernelSize * 256 * sizeof(int));

	int  xStart = 0;
	int  yStart = 0;
	width = xStart + width - max(0, (xStart + width) - width);
	height = yStart + height - max(0, (yStart + height) - height);
	int  imageSize = width * height;
	int  widthstep = width * channels;
	if (channels == 3 || channels == 4)
	{
		unsigned  char* CacheImg = NULL;
		CacheImg = (unsigned  char*)malloc(sizeof(unsigned  char) * imageSize * 6);
		if (CacheImg == NULL)
		{
			free(result);
			return NULL;
		}

		unsigned  char* rCache = CacheImg;
		unsigned  char* gCache = CacheImg + imageSize;
		unsigned  char* bCache = CacheImg + imageSize * 2;
		unsigned  char* r2Cache = CacheImg + imageSize * 3;
		unsigned  char* g2Cache = CacheImg + imageSize * 4;
		unsigned  char* b2Cache = CacheImg + imageSize * 5;
		int  sum = 0;
		for (int K = 1; K < radius; K++) 
		{
			unsigned  int  szi = radius - K;
			kernel[radius + K] = kernel[szi] = szi * szi;
			sum += kernel[szi] + kernel[szi];
			for (int j = 0; j < 256; j++)
			{
				mult[radius + K][j] = mult[szi][j] = kernel[szi] * j;
			}
		}

		kernel[radius] = radius * radius;
		sum += kernel[radius];
		for (int j = 0; j < 256; j++)
			mult[radius][j] = kernel[radius] * j;

		for (int Y = 0; Y < height; ++Y)
		{
			unsigned  char* LinePS = result->data + Y * widthstep;
			unsigned  char* LinePR = rCache + Y * width;
			unsigned  char* LinePG = gCache + Y * width;
			unsigned  char* LinePB = bCache + Y * width;
			for (int X = 0; X < width; ++X)
			{
				int      p2 = X * channels;
				LinePR[X] = LinePS[p2];
				LinePG[X] = LinePS[p2 + 1];
				LinePB[X] = LinePS[p2 + 2];
			}
		}

		int  kernelsum = 0;
		for (int K = 0; K < kernelSize; K++)
			kernelsum += kernel[K];

		float  fkernelsum = 1.0f / kernelsum;
		for (int Y = yStart; Y < height; Y++)
		{
			int  heightStep = Y * width;
			unsigned  char* LinePR = rCache + heightStep;
			unsigned  char* LinePG = gCache + heightStep;
			unsigned  char* LinePB = bCache + heightStep;
			for (int X = xStart; X < width; X++) 
			{
				int  cb = 0;
				int  cg = 0;
				int  cr = 0;
				for (int K = 0; K < kernelSize; K++)
				{
					unsigned     int      readPos = ((X - radius + K + width) % width);
					int* pmult = mult[K];
					cr += pmult[LinePR[readPos]];
					cg += pmult[LinePG[readPos]];
					cb += pmult[LinePB[readPos]];
				}

				unsigned  int  p = heightStep + X;
				r2Cache[p] = cr * fkernelsum;
				g2Cache[p] = cg * fkernelsum;
				b2Cache[p] = cb * fkernelsum;
			}
		}

		for (int X = xStart; X < width; X++)
		{
			int  WidthComp = X * channels;
			int  WidthStep = width * channels;
			unsigned  char* LinePS = result->data + X * channels;
			unsigned  char* LinePR = r2Cache + X;
			unsigned  char* LinePG = g2Cache + X;
			unsigned  char* LinePB = b2Cache + X;
			for (int Y = yStart; Y < height; Y++) 
			{
				int  cb = 0;
				int  cg = 0;
				int  cr = 0;
				for (int K = 0; K < kernelSize; K++)
				{
					unsigned  int    readPos = ((Y - radius + K + height) % height) * width;
					int* pmult = mult[K];
					cr += pmult[LinePR[readPos]];
					cg += pmult[LinePG[readPos]];
					cb += pmult[LinePB[readPos]];
				}

				int     p = Y * WidthStep;
				LinePS[p] = (unsigned  char)(cr * fkernelsum);
				LinePS[p + 1] = (unsigned  char)(cg * fkernelsum);
				LinePS[p + 2] = (unsigned  char)(cb * fkernelsum);


			}
		}

		free(CacheImg);
	}
	else  if (channels == 1)
	{
		unsigned  char* CacheImg = NULL;
		CacheImg = (unsigned  char*)malloc(sizeof(unsigned  char) * imageSize * 2);
		if (CacheImg == NULL)
		{
			free(result);
			return NULL;
		}

		unsigned  char* rCache = CacheImg;
		unsigned  char* r2Cache = CacheImg + imageSize;

		int  sum = 0;
		for (int K = 1; K < radius; K++)
		{
			unsigned  int  szi = radius - K;
			kernel[radius + K] = kernel[szi] = szi * szi;
			sum += kernel[szi] + kernel[szi];
			for (int j = 0; j < 256; j++) 
				mult[radius + K][j] = mult[szi][j] = kernel[szi] * j;
		}

		kernel[radius] = radius * radius;
		sum += kernel[radius];
		for (int j = 0; j < 256; j++) 
			mult[radius][j] = kernel[radius] * j;

		for (int Y = 0; Y < height; ++Y) 
		{
			unsigned  char* LinePS = result->data + Y * widthstep;
			unsigned  char* LinePR = rCache + Y * width;
			for (int X = 0; X < width; ++X)
				LinePR[X] = LinePS[X];
		}

		int  kernelsum = 0;
		for (int K = 0; K < kernelSize; K++)
			kernelsum += kernel[K];

		float  fkernelsum = 1.0f / kernelsum;
		for (int Y = yStart; Y < height; Y++) 
		{
			int  heightStep = Y * width;
			unsigned  char* LinePR = rCache + heightStep;
			for (int X = xStart; X < width; X++) 
			{
				int  cb = 0;
				int  cg = 0;
				int  cr = 0;
				for (int K = 0; K < kernelSize; K++)
				{
					unsigned     int      readPos = ((X - radius + K + width) % width);
					int* pmult = mult[K];
					cr += pmult[LinePR[readPos]];
				}

				unsigned  int  p = heightStep + X;
				r2Cache[p] = cr * fkernelsum;
			}
		}

		for (int X = xStart; X < width; X++) 
		{
			int  WidthComp = X * channels;
			int  WidthStep = width * channels;
			unsigned  char* LinePS = result->data + X * channels;
			unsigned  char* LinePR = r2Cache + X;
			for (int Y = yStart; Y < height; Y++) 
			{
				int  cb = 0;
				int  cg = 0;
				int  cr = 0;
				for (int K = 0; K < kernelSize; K++) 
				{
					unsigned  int    readPos = ((Y - radius + K + height) % height) * width;
					int* pmult = mult[K];
					cr += pmult[LinePR[readPos]];
				}

				int     p = Y * WidthStep;
				LinePS[p] = (unsigned  char)(cr * fkernelsum);
			}
		}

		free(CacheImg);
	}

	free(kernel);
	free(mult);
	return result;
}

3、效果图

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图像算法之高斯模糊(灰度图像) 的相关文章

  • R语言 第3章 R语言常用的数据管理(2)

    关注公众号凡花花的小窝 收获更多的考研计算机专业编程相关的资料 字符串处理 正则表达其实就是对文本进行模式匹配 所有语言中的正则表达式都有一些共同的特征 我们使用help regex 命令查看R正则表达的帮助内容 在我看来 正则表达式的主要
  • umi框架实战项目

    29 9React课程 第10节 umi框架实战项目 第10节 umi框架实战项目 第10节 umi框架实战项目 Generator是异步解决方案 next执行下一个步骤 可以放在后面也可以放在前面 Yield表示暂停 import Rea
  • [已解决]java.lang.NoClassDefFoundError: com/google/common/base/Function

    为了解决inject的报错 pom已经被我改乱了 结果最后即便改过来 项目编译报了以上错误 据说是缺少一个jar包 我用的是selenium 2 46 0 所以需要下载对应版本 selenium server standalone 2 46
  • Sentinel高并发解决方案

    Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景 本文介绍阿里开源限流熔断方案 Sentinel 功能 原理 架构 快速入门以及相关框架比较 基本介绍 1 名词解释 服务限流 当系统资源不够 不足以应对大量请求 对系统
  • 常见异常解析

    ConcurrentHashMap与CopyOnWriteArrayList比较 博客分类 Java ConcurrentHashMap ConcurrentHashMap引入了Segment 每个Segment又是一个hashtable
  • LeetCode 之 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面(Java)

    文章目录 LeetCode 之 剑指 Offer 21 调整数组顺序使奇数位于偶数前面 Java 一 题目 二 解题思路 三 代码 LeetCode 之 剑指 Offer 21 调整数组顺序使奇数位于偶数前面 Java 一 题目 剑指 Of
  • QuaggaJS在给定图像中定位条形码的工作原理

    QuaggaJS在给定图像中定位条形码的工作原理 一 介绍 二 步骤 1 创建图像的二进制表示 2 将图像切成网格 20 x 15个单元 3 提取每个细胞的骨架 4 组件标记 5 确定组件的方向 6 测定细胞质量 7 查找连接的单元格 8
  • PDF去水印教程

    现在的互联网时代是一个共享的时代 我们一定会经常从网络上面下载一些文件资料等等 那么是不是经常会遇到一些网站上的PDF文件会含有该网站的水印或者网址链接等等 这些水印有时候会影响我们正常的阅读文件 那么我们就需要将他们都去掉 接下来我们就是
  • java利用条件运算符的嵌套来完成此题:学习成绩> =90分.....(java50道经典编程题)

    题目 利用条件运算符的嵌套来完成此题 学习成绩 gt 90分的同学用A表示 60 89分之间的用B表示 60分以下的用C表示 这是一个写条件运算的例子 先和大家聊一下条件运算符 所谓条件运算也是比较简单的格式如下 基本格式 条件 值1 值2
  • AD9910模块高速DDS模块、功能性能讲解、开发调试注意事项、代码详解、电子设计大赛DDS

    AD9910模块高速DDS模块 STM32 驱动代码 功能性能讲解 开发调试注意事项 代码详解 电子设计大赛DDS 目录 AD9910模块高速DDS模块 STM32 驱动代码 功能性能讲解 开发调试注意事项 代码详解 电子设计大赛DDS 1
  • 稀疏数组和二维数组转换(以及持久化io实现)

    稀疏数组 1 当一个数组中大部分元素为0 或者为同一值的数组时 可以使用稀疏数组来保存数组 2 稀疏数组的处理方式是 a 记录数组一共有几行几列 有多少个不同值 b 把具有不同值元素的行 列及值记录在一个小规模的数组中 从而缩小程序的规模
  • 遥感影像深度学习样本制作

    交流QQ 3239516597 对于遥感同学 在学习深度学习时 第一步就要解决遥感数据样本的制作 遥感影像数据的样本根据不同的应用也有所不同 不知道的同学可以去看视频 遥感深度学习样本制作视频1 今天介绍一下如果已经有了遥感影像和对应的类别
  • 地址栏输入 URL 敲下回车后发生了什么

    浏览器地址栏输入 URL 回车后发生了什么 一 总结分析 分析如下 从输入 URL到回车后发生的行为如下 URL解析 DNS 查询 TCP 连接 HTTP 请求 响应请求 页面渲染 URL解析 首先判断你输入的是一个合法的URL 还是一个待
  • 定位排查Java线上内存溢出问题(服务重启,没有捕获到日志)

    一 场景 线上项目device服务模块内存不断上涨导致CPU较高 导致触发脚本执行重启 接口自动化测试平台不断的报500拒绝连接等错误提示 排查 通过服务器日志查询并没有异常错误信息打印 查看docker容器的日志发现错误是打印控制台 无法
  • 简单工厂模式

    定义 定义一个工厂类 它可以根据传入的参数返回不同类的实例 被创建的类实例通常都具有相同的父类 因为在简单工厂模式中返回所创建的类实例的方法是静态方法 所以简单工厂模式也称为静态工厂模式 简单工厂方法的要点在于 你只需要传入一个正确的参数

随机推荐

  • 安装Yearning SQL审核平台和Inception(基于已闭源方式)

    这是我安装Yearning SQL审核平台和Inception 已闭源 总结的文档 1 安装centos7并配置网络为桥接模式 命令 vi etc sysconfig network scripts ifcfg ens33 内部配置如下 2
  • 硬件学习--不同硬盘类型速度对比

    SATA 串行ATA总线 SCSI 小型电脑输入输出接口 SAS 希捷研究出来的取代SCSI技术的接口 SSD 固态硬盘 容量小 读写快 接口速度是 SSD gt SAS gt SCSI gt SATA SAS Serial Attache
  • 通用Ajax设计

    利用Servlet和反射技术实现通用的Ajax调用设计 如下 一 调用规则 在JS代码 调用者只需按下面的规范 即可实现异步或同步java方法调用 在你的jsp或html页面中 导入通用异步调用方法文件 km js 自定义 然后写异步调用方
  • unity中使用c#钩子

    目的 解决在应用程序最小化后无法监听到系统按键事件的情况 解决问题的过程很好笑 我先找到了第一个方法 脚本一 使用方法 脚本挂在场景中物体上即可 using System using System Collections using Sys
  • 统计学习第四弹--随机变量的概率分布

    关于随机变量概率分布的重要概念 概率 对事件的发生的可能性大小的度量值 随机变量 事先不能确定其取值的变量 离散型随机变量 只能取有限个值的随机变量 连续型随机变量 可以取一个或多个区间中任何值的随机变量 期望值 随机变量的平均取值 求法是
  • Caltech数据使用详情

    Caltech官网 http www vision caltech edu Image Datasets CaltechPedestrians 以Caltech测试集为例 大概是4095个图片吧 1 下载数据 http www vision
  • 【华为OD机试】返回矩阵中非1的元素个数【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 存在一个m n的二维数组 其成员取值范围为0 1 2 其中值为1的元素具备同化特性 每经过1S 将上下左右值为0的元素同化为1 而值为2的元素 免疫同化 将数组所有成
  • C语言小知识-不定参数函数实现

    C语言不定参数的实现 C语言在定义函数参数时 允许参数的使用数量可变 这在C语言中称为 可变参数函数 variadic function 当然在C标准库中不乏可变参数函数的使用 例如 C标准函数 printf 的声明方式为 int prin
  • Qt之设置QWidget背景色(QStyleOption->drawPrimitive(QStyle::PE_Widget)

    QWidget是所有用户界面对象的基类 这意味着可以用同样的方法为其它子类控件改变背景颜色 Qt中窗口背景的设置 下面介绍三种方法 1 使用QPalette 2 使用Style Sheet 3 绘图事件 一般我不用QSS设置窗口背景 也不建
  • 在YOLOv5训练自己的数据集模型时删除预训练权重后发现报错

    上图是报错内容 找到general py 出错的位置 应该是YOLOv5版本的问题 就用一个可以正常空权重跑通的文件 将general py相应部分给复制下来 粘贴过去 报错内容是 acceptable suffix is pt
  • 【超简易版】基于Pytorch Fasterrcnn_resnet50_fpn的多车牌定位/车牌检测-基于CCPD2019数据集

    说明 本项目为本人初学torch框架练习项目 在此仅作个人经验分享 由于本人现大三 码code经验有限 难免存在瑕疵 望各位前辈批评指正 本项目在linux上训练模型并下载权重 pth文件在windows上进行测试 数据集来源参考 CCPD
  • 二叉树ADT的二叉链表求解

    假设二叉数的数据元素为字符 采用二叉链式存储结构 请编码实现二叉树ADT 其中包括创建二叉树 遍历二叉树 深度 广度 求二叉树的深度 高度 计算二叉树的元素个数 计算二叉树的叶子数 二叉树的格式输出等 根据输入的符号 执行相应的操作 如下
  • Destination Host Unreachable Ubuntu

    情况描述 物理机win10 192 168 1 102 虚拟机Ubuntu 18 192 168 190 128 docker环境 nat设置 物理机可以ping通虚拟机 虚拟机可以访问外网 但是不能ping通物理主机 虚拟机ping 19
  • unity行为树Behavior Designer插件学习

    本章资源百度网盘 链接 https pan baidu com s 16BFLcqIK6aKPc vxhuR0HA pwd d42s 提取码 d42s 1 准备 1 导入行为树插件包 Unity Behavior Designer v1 5
  • html仿苹果桌面导航js css,CSS简单实现弹出框、输入框等的背景幕布,模仿苹果官网导航块的半透明效果。...

    需求提要 我们如果想写一个效果类似弹出框的组件 首先简单分析一下弹出框的几个特性 弹出框肯定位于当前页面的最顶端 并且在弹出框关闭之前 其他控件都无法点击 focus等 为了更好突出弹出框的效果 除了弹出框以外的部分 我们可以加上一个幕布
  • Java集合(Collection、Iterator、Map、Collections)概述——Java第十三讲

    前言 本讲我们将继续来讲解Java的其他重要知识点 Java集合 Java集合框架是Java编程语言中一个重要的部分 它提供了一套预定义的类和接口 供程序员使用数据结构来存储和操作一组对象 Java集合框架主要包括两种类型 一种是集合 Co
  • LeetCode第一章数组

    977 有序数组的平方 题目链接 977 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums 返回 每个数字的平方 组成的新数组 要求也按 非递减顺序 排序 示例 1 输入 nums 4 1 0 3 10 输出 0 1 9 1
  • 使用SQL聚合函数,分组,完成数据合并,字段拼接或者字段追加

    在项目的开发过程中 我们会遇到一些特殊的业务需求 如接下来讲的业务需求 根据多个字段 如果多个字段相同就把两条数据合并为一条数据 但是两条数据的创建人的追加在一条数据中 返回给前端 话不多说上图解释该业务 当然也可以通过代码去完成 这次我们
  • 我在做layuiAdmin std 通用后台管理模板系统(iframe标准版)的动态侧边栏渲染

    1 layuiAdmin的根据请求获取数据 动态生成侧边栏 注意 请求地址一样 但携带的token不一样 会返回不一样的侧边栏 就是权限问题 在views index html页面上改造的前后 改造侧边栏的渲染代码前 div class l
  • 图像算法之高斯模糊(灰度图像)

    1 函数定义 高斯模糊 struct stPGMImage GaussianBlur struct stPGMImage image unsigned int radius 2 函数实现 struct stPGMImage Gaussian