news 2026/6/10 16:02:55

可分离滤波-高斯滤波

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
可分离滤波-高斯滤波

一、概述

采用一维高斯滤波(可分离高斯滤波)的核心原因在于:在保持与二维高斯滤波完全相同数学效果的前提下,大幅降低计算复杂度并提升工程效率。由于二维高斯核可以严格分解为两个相互独立的一维高斯核(横向 × 纵向),可大大降低计算量,对于大小为M×n的图像和大小为m×n的核,实现卷积操作需要MNmn次乘法核加分运算(计算公式如下3.35),但是如果滤波核是可分离的,对于w1(行)卷积核,第一次卷积只需要MNm次乘法和加分运算,因为w1卷积核的大小为m×1,对于w2(列)卷积核,第二次卷积只需要MNn次乘法和加分运算,所以共需要MN(m+n)次乘法和加分运算,因此可分离的核执行卷积运算可以大大减少计算量,滤波核越大越明显(可见如下公式3.44)。

二、二维高斯滤波

首先我们讲解一下二维高斯滤波核的生成,这里根据高斯函数可直接生成高斯滤波核,代码如下:

// 二维高斯滤波核 std::vector<std::vector<double>> GaussianKernelGenerate(int kSize, double sigma) { int k = kSize / 2; std::vector<std::vector<double>> kernel(kSize, std::vector<double>(kSize)); double sum = 0.0; const double PI = 3.14159265358979323846; for (int i = -k; i <= k; ++i) { for (int j = -k; j <= k; ++j) { double value = static_cast<double>((1.0 / (2 * PI * sigma * sigma)) * (exp(-(i * i + j * j) / (2 * sigma * sigma)))); kernel[i + k][j + k] = value; sum += value; } } // 归一化 for (int i = 0; i < kSize; ++i) { for (int j = 0; j < kSize; ++j) { kernel[i][j] /= sum; } } return kernel; }

三、一维高斯滤波

同理,由高斯函数可知,我们可以分解为两个一维的滤波进行卷积计算,分离式滤波核正是opencv获得高斯滤波核的底层实现原理,这里我们也用底层代码实现,我们生成一维的卷积核,先用一维卷积核对图像行向量进行卷积,再用该滤波对图像的列向量进行卷积即可。代码如下:

// 分离式高斯滤波核 std::vector<double> GenerateSeparateGaussianKernel(int kSize, double sigma) { int k = kSize / 2; double sum = 0.0; std::vector<double>kernel(kSize, 0); const double PI = 3.14159265358979323846; for (int i = -k; i <= k; ++i) { double value = static_cast<double>((1.0 / (sqrt(2 * PI) * sigma)) * exp(-(i * i) / (sqrt(2) * sigma))); kernel[i + k] = value; sum += value; } // 归一化 for (int i = 0; i < kSize; ++i) { kernel[i] /= sum; } return kernel; }

四、滤波分离

这里我们重点讲解一下滤波分离,首先我们是知道高斯函数是可分离的。那对于一般的滤波核呢?我们不可以直接进行一维滤波计算,首先是否可分离,需要满足矩阵可分离性质,即满足矩阵 = 行 × 列,也就是秩为1。如果我们在计算位置滤波核的时候,不确定这个矩阵的秩是否为1,我们可以先用 SVD 计算一下它的秩,或者观察它的奇异值。如果除了第一个奇异值外,其他奇异值不为 0(或接近 0),那就不能分离。如果秩为1,我们可以采用以下方法对其进行分解,在核中找到任何一个非0元素,并将其值表示为E,形成行向量r和列向量c,他们分别等于E元素所在的那一行和那一列,这个时候这个r和c就是分离出来的行滤波核和列滤波核,原理如下。

代码如下:

// 将滤波核进行分离 void splitGaussianKernel(const std::vector<std::vector<double>>& GaussianKernel, std::vector<double>& c, std::vector<double>& r) { // 获取高斯核的行和列 int rows = GaussianKernel.size(); int cols = GaussianKernel[0].size(); r.resize(rows); c.resize(cols); // 找到非零元素,高斯核的中心就是最稳定的非零元素 double center = GaussianKernel[rows / 2][cols / 2]; // 提取非零元素所在行 for (int i = 0; i < rows; ++i) { r[i] = GaussianKernel[i][center]; } // 提取非零元素列 for (int j = 0; j < cols; ++j) { c[j] = GaussianKernel[center][j]; } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 6:48:10

AI绘画大赛联动:用LobeChat生成创意提示词参赛

AI绘画大赛联动&#xff1a;用LobeChat生成创意提示词参赛 在AI艺术创作的浪潮中&#xff0c;一场无声的变革正在发生。越来越多的设计师、艺术家和开发者发现&#xff0c;真正决定一幅AI生成图像质量的&#xff0c;往往不是模型本身&#xff0c;而是那短短几行“咒语”——提示…

作者头像 李华
网站建设 2026/6/10 13:29:55

LobeChat ISO27001体系建设建议

LobeChat 与 ISO27001&#xff1a;构建可信企业级 AI 聊天系统的实践路径 在当今企业加速智能化转型的背景下&#xff0c;AI 聊天系统已不再是简单的“对话接口”&#xff0c;而是承载知识服务、业务流程甚至核心决策支持的关键平台。随着大语言模型&#xff08;LLM&#xff09…

作者头像 李华
网站建设 2026/6/10 5:18:08

vue基于Springboot框架的流浪猫救助系统 流浪宠物领养系统

目录已开发项目效果实现截图开发技术系统开发工具&#xff1a;核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度系统测试总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&…

作者头像 李华
网站建设 2026/6/10 12:26:50

vue基于Springboot框架的考研咨询平台系统实现 没论文_c30c3um4

目录 已开发项目效果实现截图开发技术系统开发工具&#xff1a; 核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度系统测试总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&am…

作者头像 李华
网站建设 2026/6/10 11:00:04

空间智能:中国数字基建的新引擎与产业变革的深层逻辑

智能演进的必然跃迁&#xff1a;空间智能引领AI发展新纪元 人工智能技术发展已进入从感知智能向认知智能、决策智能的深度演进阶段。从文本处理、图像识别到视频生成&#xff0c;AI技术正逐步突破二维边界&#xff0c;向三维物理世界纵深发展。中央科技工作会议明确指出&#x…

作者头像 李华
网站建设 2026/6/9 23:03:26

基于单片机的智能小区安防系统

基于单片机的智能小区安防系统设计 一、系统总体设计 基于单片机的智能小区安防系统以“全域监测、快速响应、联动防控”为核心目标&#xff0c;整合出入口管理、公共区域监测、住户防护等功能&#xff0c;解决传统小区安防分散、响应滞后的问题。系统采用分布式架构&#xff0…

作者头像 李华