2D image convolution(二维图像卷积)

本文详细解析了二维图像卷积的概念,包括卷积核的作用、图像填充以及卷积过程的数学表述。通过实例展示了如何对3*3图像应用3*3卷积核进行卷积运算,并指出在CNN中卷积实际是相关运算的用法。
在学习cnn的过程中,对convolution的概念真的很是模糊,本来在学习图像处理的过程中,已对convolution有所了解,它与correlation是有不同的,因为convolution = correlation + filp over in both horizontal + vertical

但在CNN中,明明只是进行了correlation,但却称之为convolution,实在不解

下面, 将图像处理中的convolution重新整理记录

因为网络关于这部分的解释很多,这里直接借用其他 参考

“A convolution is done by multiplying a pixel's and its neighboring pixels color value by a matrix”, 这里的matrix就是convoluiton kernel (usually a small matrix of numbers)

这里假设图像是3*3,kernel也是3*3,实际计算中,有时为了使得卷积结果与原图像一致,会对原图像进行padding操作

原图像x:

具体数值:

0 0 0 0 0
0 1 2 3 0
0 4 5 6 0
0 7 8 9 0
二维图像的卷积操作是数字图像处理中的一项基础技术,广泛应用于边缘检测、模糊化、锐化等图像增强任务。其核心原理是通过一个称为“卷积核”或“滤波器”的小矩阵对图像中的每个像素进行加权求和,从而生成新的图像。 ### 卷积的基本原理 在二维图像中,卷积操作涉及将卷积核与图像局部区域进行逐元素相乘并求和的过程。具体来说,卷积核会在图像上滑动,每次覆盖一个局部区域,然后计算该区域与卷积核之间的点积。这个过程可以表示为: ```math (I * K)(i, j) = \sum_{m} \sum_{n} I(i+m, j+n) \cdot K(m, n) ``` 其中 $I$ 是输入图像,$K$ 是卷积核,$(i, j)$ 表示图像上的位置,而 $(m, n)$ 则遍历卷积核的所有位置[^2]。 ### 实现方法 为了实现二维图像的卷积操作,通常需要考虑以下几个步骤: 1. **边界填充**:由于卷积核可能会超出图像边界,因此通常会对图像进行零填充(padding),以保持输出图像尺寸不变或者根据需求调整。 2. **卷积计算**:对于图像中的每一个像素,应用卷积核,并计算加权和。 3. **输出结果**:将计算得到的结果存储在一个新的图像矩阵中。 下面是一个使用 C++ 和 `std::vector` 来实现二维卷积的例子: ```cpp #include <iostream> #include <vector> class Convolution { public: template<typename T> static std::vector<std::vector<T>> conv_2d(const std::vector<std::vector<T>>& image, const std::vector<std::vector<T>>& kernel) { int img_rows = image.size(); int img_cols = image[0].size(); int krn_rows = kernel.size(); int krn_cols = kernel[0].size(); // 计算输出图像的大小 int out_rows = img_rows - krn_rows + 1; int out_cols = img_cols - krn_cols + 1; std::vector<std::vector<T>> output(out_rows, std::vector<T>(out_cols, 0)); for (int i = 0; i < out_rows; ++i) { for (int j = 0; j < out_cols; ++j) { T sum = 0; for (int ki = 0; ki < krn_rows; ++ki) { for (int kj = 0; kj < krn_cols; ++kj) { sum += image[i + ki][j + kj] * kernel[ki][kj]; } } output[i][j] = sum; } } return output; } }; int main() { // 示例图像 std::vector<std::vector<int>> image = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; // 示例卷积核 std::vector<std::vector<int>> kernel = { {0, 1, 0}, {1, -4, 1}, {0, 1, 0} }; auto result = Convolution::conv_2d(image, kernel); for (const auto& row : result) { for (int val : row) { std::cout << val << " "; } std::cout << std::endl; } return 0; } ``` ### 注意事项 - 在实际应用中,可能还需要处理边界情况,例如通过填充来保持输出图像的尺寸一致。 - 可以利用模板技术使卷积函数支持不同类型的数据(如 `float`, `double` 等)。 - 面向对象的设计有助于代码组织和复用。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值