当前位置: 首页 > news >正文

使用 C++ 实现卷积运算:从理论到实践的详细指南

目录

    • 1. 前言
    • 2. 什么是卷积运算?
    • 3. 卷积的实现步骤
    • 4. C++ 实现代码
    • 5. 代码详解
    • 7. 结论

1. 前言

卷积(Convolution)是信号处理、图像处理以及深度学习等领域中的核心操作。它广泛应用于图像滤波、特征提取和卷积神经网络(CNN)等方面。本文将从卷积运算的基本原理出发,详细介绍如何用 C++ 实现卷积运算,并展示具体代码和示例。

2. 什么是卷积运算?

卷积运算是一种通过滑动窗口的方式,将一个卷积核(Kernel)应用到输入信号(如图像)的每个位置,进而计算出输出信号的方法。卷积运算的数学表达式如下:
在这里插入图片描述

3. 卷积的实现步骤

定义输入矩阵和卷积核:准备好待处理的图像数据(输入矩阵)和卷积核。
滑动窗口:将卷积核从输入矩阵的左上角开始,逐步滑动,计算每个位置的卷积结果。
边界处理:对于边界上的像素,常见的方法是用“零填充”或忽略边界。

4. C++ 实现代码

#include <iostream>
#include <vector>using namespace std;// 卷积函数
vector<vector<double>> Convolve(const vector<vector<double>>& input,const vector<vector<double>>& kernel,int stride = 1, int padding = 0) {int input_height = input.size();int input_width = input[0].size();int kernel_size = kernel.size();// 计算输出矩阵的高度和宽度int output_height = (input_height - kernel_size + 2 * padding) / stride + 1;int output_width = (input_width - kernel_size + 2 * padding) / stride + 1;// 初始化输出矩阵vector<vector<double>> output(output_height, vector<double>(output_width, 0.0));// 在输入矩阵周围进行零填充vector<vector<double>> padded_input(input_height + 2 * padding, vector<double>(input_width + 2 * padding, 0.0));for (int i = 0; i < input_height; ++i) {for (int j = 0; j < input_width; ++j) {padded_input[i + padding][j + padding] = input[i][j];}}// 执行卷积运算for (int i = 0; i < output_height; ++i) {for (int j = 0; j < output_width; ++j) {double sum = 0.0;for (int m = 0; m < kernel_size; ++m) {for (int n = 0; n < kernel_size; ++n) {sum += kernel[m][n] * padded_input[i * stride + m][j * stride + n];}}output[i][j] = sum;}}return output;
}// 打印矩阵函数
void PrintMatrix(const vector<vector<double>>& matrix) {for (const auto& row : matrix) {for (double value : row) {cout << value << "\t";}cout << endl;}
}// 主函数:测试卷积运算
int main() {// 定义输入矩阵vector<vector<double>> input = {{1, 2, 0, 1},{3, 1, 1, 0},{0, 1, 2, 3},{2, 0, 1, 1}};// 定义卷积核vector<vector<double>> kernel = {{1, 0, -1},{1, 0, -1},{1, 0, -1}};// 执行卷积vector<vector<double>> output = Convolve(input, kernel, 1, 1);// 输出结果cout << "Input Matrix:" << endl;PrintMatrix(input);cout << "\nKernel Matrix:" << endl;PrintMatrix(kernel);cout << "\nOutput Matrix:" << endl;PrintMatrix(output);return 0;
}

5. 代码详解

Convolve 函数:

接收输入矩阵 input、卷积核 kernel,步长 stride 和填充 padding。
首先计算输出矩阵的大小,初始化输出矩阵。
通过零填充扩展输入矩阵,处理边界问题。
执行嵌套循环,计算卷积结果,将结果存储到 output 矩阵中。
PrintMatrix 函数:用来打印矩阵,便于查看输入和输出结果。

主函数 main():

定义输入矩阵和卷积核,调用 Convolve 函数执行卷积运算,并打印结果。
6. 示例输出

Input Matrix:
1       2       0       1
3       1       1       0
0       1       2       3
2       0       1       1Kernel Matrix:
1       0       -1
1       0       -1
1       0       -1Output Matrix:
3       2       -1       0
3       4       1        -1
2       1       -2       -1
3       0        -1      1

7. 结论

通过以上实现,我们可以看到 C++ 是一种高效而灵活的编程语言,能够轻松实现卷积运算。无论是在图像处理、信号处理还是深度学习领域,卷积都是非常重要的操作。本文从理论到实践,详细讲解了卷积的原理,并展示了完整的 C++ 实现,希望对学习卷积和 C++ 编程的读者有所帮助。

相关文章:

  • 加密解密的艺术:探索Java中的DES算法
  • 关于BSV区块链覆盖网络的常见问题解答(上篇)
  • 为VRoidStudio制作的vrm格式模型制作blendshape
  • 【Linux实践】实验五:用户和组群账户管理
  • [极客大挑战 2019]RCE ME1
  • 计算机毕业设计 Java教务管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • React返回上一个页面,会重新挂载吗
  • 微信小程序-数据模型与动态赋值
  • 【AI驱动TDSQL-C Serverless数据库技术实战】 AI电商数据分析系统——探索Text2SQL下AI驱动代码进行实际业务
  • 智能网联汽车飞速发展,安全危机竟如影随形,如何破局?
  • ONVIF、GB28181技术特点和使用场景分析
  • 【教程】57帧! Mac电脑流畅运行黑神话悟空
  • docker的harbor仓库登录问题
  • APISIX 联动雷池 WAF 实现 Web 安全防护
  • 匈牙利算法模板
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • conda常用的命令
  • Github访问慢解决办法
  • JAVA并发编程--1.基础概念
  • JSONP原理
  • js中的正则表达式入门
  • Material Design
  • vue脚手架vue-cli
  • 分布式熔断降级平台aegis
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 基于web的全景—— Pannellum小试
  • 使用 QuickBI 搭建酷炫可视化分析
  • 学习使用ExpressJS 4.0中的新Router
  • 【干货分享】dos命令大全
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • 通过调用文摘列表API获取文摘
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​​​​​​​开发面试“八股文”:助力还是阻力?
  • ######## golang各章节终篇索引 ########
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (2024.6.23)最新版MAVEN的安装和配置教程(超详细)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (js)循环条件满足时终止循环
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (汇总)os模块以及shutil模块对文件的操作
  • (离散数学)逻辑连接词
  • (三)uboot源码分析
  • (十八)SpringBoot之发送QQ邮件
  • (转)nsfocus-绿盟科技笔试题目
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • *算法训练(leetcode)第三十九天 | 115. 不同的子序列、583. 两个字符串的删除操作、72. 编辑距离
  • ./和../以及/和~之间的区别