提问人:Gustavo Stahl 提问时间:11/29/2022 更新时间:11/29/2022 访问量:103
如何使用 ArrayFire 批量 2D 卷积
How to use ArrayFire batched 2D convolution
问:
通读 ArrayFire 文档,我注意到该库在使用 2D 卷积时支持批处理操作。因此,我需要使用 C++ API 将 N 个过滤器应用于图像。
为了便于测试,我决定创建一个简单的 Python 脚本来断言卷积结果。但是,在使用 >1 滤波器并将它们与 OpenCV 的 2D 卷积单独进行比较时,我无法获得正确的结果。以下是我的 Python 脚本:
import arrayfire as af
import cv2
import numpy as np
np.random.seed(1)
np.set_printoptions(precision=3)
af.set_backend('cuda')
n_kernels = 2
image = np.random.randn(512,512).astype(np.float32)
kernels_list = [np.random.randn(7,7).astype(np.float32) for _ in range(n_kernels)]
conv_cv_list = [cv2.filter2D(image, -1, cv2.flip(kernel,-1), borderType=cv2.BORDER_CONSTANT) for kernel in kernels_list]
image_gpu = af.array.Array(image.ctypes.data, image.shape, image.dtype.char)
kernels = np.stack(kernels_list, axis=-1) if n_kernels > 1 else kernels_list[0]
kernels_gpu = af.array.Array(kernels.ctypes.data, kernels.shape, kernels.dtype.char)
conv_af_gpu = af.convolve2(image_gpu, kernels_gpu)
conv_af = conv_af_gpu.to_ndarray()
if n_kernels == 1:
conv_af = conv_af[..., None]
for kernel_idx in range(n_kernels):
print("CV conv:", conv_cv_list[kernel_idx][0, 0])
print("AF conv", conv_af[0, 0, kernel_idx])
也就是说,我想知道如何正确使用ArrayFire批处理支持。
答:
1赞
arrayfire
11/29/2022
#1
ArrayFire 是列优先的,而 OpenCV 和 NumPy 是行优先的。这可能会导致问题。我们提供了一个互操作函数来为您处理这个问题,如下所示。
import arrayfire as af
import cv2
import numpy as np
np.random.seed(1)
np.set_printoptions(precision=3)
af.set_backend('cuda')
n_kernels = 2
image = np.random.randn(512,512).astype(np.float32)
kernels_list = [np.random.randn(7,7).astype(np.float32) for _ in range(n_kernels)]
conv_cv_list = [cv2.filter2D(image, -1, cv2.flip(kernel,-1), borderType=cv2.BORDER_CONSTANT) for kernel in kernels_list]
image_gpu = af.interop.from_ndarray(image) # CHECK OUT THIS
kernels = np.stack(kernels_list, axis=-1) if n_kernels > 1 else kernels_list[0]
kernels_gpu = af.interop.from_ndarray(kernels) # CHECK OUT THIS
conv_af_gpu = af.convolve2(image_gpu, kernels_gpu)
conv_af = conv_af_gpu.to_ndarray()
if n_kernels == 1:
conv_af = conv_af[..., None]
for kernel_idx in range(n_kernels):
print("CV conv:", conv_cv_list[kernel_idx][0, 0])
print("AF conv", conv_af[0, 0, kernel_idx])
我们正在开发一个更新版本的 ArrayFire Python,它将解决这个问题。
祝你好运!
评论
1赞
Gustavo Stahl
11/29/2022
C++ API 中是否有任何内容可以解决这些按行 ➙ 并列的转换?
1赞
Gustavo Stahl
11/30/2022
回答我上面的评论,在 C++ API 中处理逐行 ➙ 并列转换的一个选项是转置矩阵。在这种情况下,要转换 7 x 7 x 2 内核,我必须切换前两个维度(例如,3 x 5 x 2 张量 ➙ 5 x 3 x 2 张量)。一个简单的人就可以解决这个问题。af::transpose
评论