0

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.

EDIT :

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?

ironstein
  • 416
  • 8
  • 23

1 Answers1

2

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)
Daniel
  • 42,087
  • 4
  • 55
  • 81
  • Thank you for your reply. What I wanted to know that according to the documents for numpy, the numpy.ascontiguousarray function returns a column major C contiguous array. How would that affect the execution of my program ? – ironstein Oct 29 '15 at 02:05
  • `c_array.ctypes` has an `_as_parameter_` attribute that's a `c_void_p` instance, so just return `c_array.ctypes`. – Eryk Sun Oct 29 '15 at 13:49
  • @eryksun could you please give me an example pertaining 2d numpy array with elements as integers, been trying it for a while now and getting nowhere. I tried ` c_array = numpy.ascontiguousarray([numpy.ascontiguousarray(element,dtype=int) for element in array]) but when I use this, python seems to crash` – ironstein Oct 29 '15 at 15:46
  • @Daniel could you please give me an example pertaining 2d numpy array with elements as integers, been trying it for a while now and getting nowhere. I tried ` c_array = numpy.ascontiguousarray([numpy.ascontiguousarray(element,dtype=int) for element in array]) ` but when I use this, python seems to crash – ironstein Oct 29 '15 at 15:51
  • @ironstein: you create one 2d-numpy-array (`numpy.zeros(shape=(a,b), dtype=int)`), the `ascontiguousarray` is only necessary, if you like to use any array or subarray. – Daniel Oct 29 '15 at 18:55