![]() |
1
10
我想这个测试是为了避免0的乘法。跳过测试!乘以0要比 delays caused by a conditional jump . 另一种选择(发布实际代码而不是伪代码总是更好,这里让我猜猜您实现了什么!)您正在测试越界访问。这也非常昂贵。最好分解循环,这样就不需要对大多数像素进行此测试:
当然,这同样适用于列上的循环,导致内核值上的内部循环重复9次。很难看但是 方法 更快。 为了避免代码重复,您可以创建一个更大的图像,复制图像数据,在所有边上填充零。循环现在不需要担心访问越界,您有了更简单的代码。 接下来,某类内核可以 decomposed into 1D kernels . 例如,众所周知的Sobel核是由[1,1,1]和[1,0,-1]的卷积得到的 T . 对于3x3内核来说,这并不是一个大问题,但对于更大的内核来说,这是一个大问题。通常,对于NxN内核,可以从 2. 至2N次操作。 特别地, the Gaussian kernel is separable . 这是一个非常重要的平滑滤波器,也可用于计算导数。 除了明显的计算成本节约外,对于这些1D卷积,代码也要简单得多。对于1D过滤器,我们之前重复的9个代码块变成了3个。水平过滤器的相同代码可重复用于垂直过滤器。 最后,如中所述 MBo's answer ,可以通过DFT计算卷积。DFT可以使用 FFT in O(MN log MN)(对于大小为MxN的图像)。这需要将内核填充到图像的大小,将两者转换到傅立叶域,将它们相乘,然后对结果进行逆变换。共3次变换。这是否比直接计算更有效取决于内核的大小以及它是否可分离。 |
![]() |
2
3
对于较小的内核大小,简单的方法可能更快。还要注意的是 可分离核 (例如,高斯核是可分离的)如前所述,允许先按行再按列进行过滤,从而产生O(N^2*M)复杂度。
对于其他情况:存在
fast convolution based on FFT
(快速傅立叶变换)。它的复杂性是
当然,应用这种技术有一些特殊性,例如边缘效应,但在幼稚的实现中也需要考虑它们(尽管程度较低)。
请注意,您可以使用一些用于图像过滤的快速库,例如,
OpenCV
允许将内核应用于
|
![]() |
3
1
提高速度的一种方法可能是,根据目标平台的不同,明确获取内核中的每个值,然后在内存中存储图像的多个副本,内核中的每个不同值对应一个副本,并将图像的每个副本乘以其不同的内核值,最后乘以不同的内核值,然后移位、求和并将所有图像副本分割为一个图像。这可以在图形处理器上完成,例如内存充足的图形处理器,更适合这种紧凑的重复处理。图像的副本需要支持像素溢出,或者可以使用浮点值。 |
![]() |
AstralHex · 矩阵乘法代码工作不正常 4 月前 |
![]() |
Fishie · 作为类成员的智能指针是否仍然自动释放?[关闭] 5 月前 |
![]() |
Die4Toast · 递归调用成员箭头运算符-> 5 月前 |
![]() |
Anka Hanım · 关于结构和动态数组地址的问题 5 月前 |