您好,我在python中使用ctypes模块从python运行一些图像处理C代码,以优化我的代码,并缩短执行时间。
为此,我正在将图像读入一个numpy数组,然后使用内核将2D卷积应用于图像,从而生成过滤后的图像。我希望在C中实现相同,以节省一些执行时间。
因此,问题的第一部分是将numpy图像数组转换为ctype数组,以便我可以在C中执行卷积。 这是我的C代码,它现在什么都不做,但我只需要访问函数定义:
#import <math.h>
void convolution(int *array,int *kernel, int array_height, int array_width,
int kernel_height, int kernel_width) {
int i=0;
这是我的python代码,它为这个C函数添加了一个包装函数:
_convolution_ = ctypes.cdll.LoadLibrary(working_directory + 'libconvolution.so')
class two_dimensional_matrix_() :
def from_param(self,param) :
typename = type(param).__name__
if hasattr(self,'from_'+typename) :
return getattr(self,'from_'+typename)(param)
else :
raise TypeError('cant convert %s' %typename)
#for a list
def from_list(self,param) :
c_array = ((ctypes.c_int * len(param))*len(param[0]))()
for i in range(len(param)) :
for j in range(len(param[i])) :
c_array[i][j] = ctypes.c_int(param[i][j])
return c_array
#for a tuple
def from_tuple(self,param) :
return self.from_list(param)
#for a numpy array
def from_ndarray(self,param) :
c_array = ((ctypes.c_int * len(param))*len(param[0]))()
for i in range(len(param)) :
for j in range(len(param[i])) :
c_array[i][j] = ctypes.c_int(param[i][j])
return c_array
two_dimensional_matrix = two_dimensional_matrix_()
_convolution_.convolution.argtypes = [
two_dimensional_matrix, two_dimensional_matrix,
ctypes.c_int,ctypes.c_int,ctypes.c_int,ctypes.c_int
]
_convolution_.convolution.restypes = ctypes.c_void_p
即使这段代码完美无缺,但我想知道的是,是否有更有效的方法来执行从numpy数组或列表到ctypes数组的转换?因为我在python中使用C扩展来节省执行时间,所以我希望这个时间尽可能少。
编辑:
正如丹尼尔所建议的,我使用numpy.ascontiguousarray
,它适用于1D numpy数组,这就是我所做的:
c_array = numpy.ascontiguousarray(array,dtype=numpy.uint32)
但是当我尝试2D阵列的类似方法时,它不起作用,这是我试过的:
c_array = numpy.ascontiguousarray(array,dtype=numpy.ndarray)
当我使用它时,python崩溃了。我在这里做错了什么?
答案 0 :(得分:2)
最快的方法是,根本不需要转换数组。 此代码也适用于列表和元组:
c_array = numpy.ascontiguousarray(param, dtype=int)
pointer = c_array.ctypes.data_as(ctypes.c_void_p)