简体   繁体   中英

Most efficient way to convert a multidimensional numpy array to ctypes array

Hello, I am using ctypes module in python to run some image processing C code from python, for the purpose of optimisation of my code, and reducing the execution time.

For this purpose, I am reading an image into a numpy array and then applying 2D convolution to the image with a kernel, producing a filtered image. I want achieve the same in C, in order to save some execution time.

So, the first part of the problem is converting the numpy image array, to ctype array, so that I can perform convolution in C. Here is my C code which does nothing right now, but I need it just to access the function definition :

#import <math.h>

void convolution(int *array,int *kernel, int array_height, int array_width,
                 int kernel_height, int kernel_width) {
    int i=0;

here is my python code, that adds a wrapper function for this C function :

_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

Even though this code works perfectly, what I want to know is that is there a more efficient way to perform the conversion from a numpy array or a list to ctypes array? Because I am using C extensions in python to save execution time, I want this time to be as little as possible.

:

as suggested by Daniel, I used numpy.ascontiguousarray , and it works well for 1D numpy array, here is what I did :

c_array = numpy.ascontiguousarray(array,dtype=numpy.uint32)

but when I try the similar method for 2D arrays, it does not work, here is what I tried :

c_array = numpy.ascontiguousarray(array,dtype=numpy.ndarray)

when I use this, python crashes. What am I doing wrong here?

The fastest way is, not the convert the array at all, if not necessary. This code works also for lists and tuples:

c_array = numpy.ascontiguousarray(param, dtype=int)
pointer = c_array.ctypes.data_as(ctypes.c_void_p)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM