1

I'm wrapping a third party camera library interface with Cython so I can call it from a python program. For the most part things work very well, but I've hit a snag in my acquireImage() function. I've tried to create a contiguous numpy array, pass that to the library, and pick up the result after the library has finished populating it. Finally, I want to copy that array, reshape it and return it. (The reshape stuff hasn't been coded yet)

Here is my code:

cpixis.pxd:

ctypedef bint rs_bool
ctypedef unsigned short uns16
ctypedef short int16
ctypedef unsigned int uns32
ctypedef unsigned int* uns32_ptr
ctypedef void* void_ptr
ctypedef char* char_ptr
ctypedef short* int16_ptr
ctypedef struct rgn_type:
        short s1
        short s2
        short sbin
        short p1
        short p2
        short pbin
ctypedef rgn_type* rgn_const_ptr
ctypedef rgn_type* rgn_ptr

#cdef CAM_NAME_LEN 32

cdef extern from "/usr/local/pvcam/examples/pvcam.h":
    cdef enum cam_open:
        OPEN_EXCLUSIVE
    cdef enum exposure:
        TIMED_MODE, STROBED_MODE, BULB_MODE, TRIGGER_FIRST_MODE, FLASH_MODE, VARIABLE_TIMED_MODE, INT_STROBE_MODE
    cdef enum readout:
        READOUT_NOT_ACTIVE, EXPOSURE_IN_PROGRESS, READOUT_IN_PROGRESS, READOUT_COMPLETE, 
        FRAME_AVAILABLE = READOUT_COMPLETE, READOUT_FAILED, ACQUISITION_IN_PROGRESS, MAX_CAMERA_STATUS
    rs_bool pl_pvcam_init()
    rs_bool pl_pvcam_uninit()
    rs_bool pl_cam_get_name(int16 cam_num, char_ptr camera_name)
    rs_bool pl_cam_open(char_ptr camera_name, int16_ptr hcam, int16 o_mode)
    rs_bool pl_cam_close(int16 hcam)
    rs_bool pl_pvcam_uninit()
    rs_bool pl_exp_init_seq()
    rs_bool pl_exp_setup_seq (int16 hcam, uns16 exp_total,
                              uns16 rgn_total, rgn_const_ptr rgn_array,
                              int16 exp_mode, uns32 exposure_time,
                              uns32_ptr exp_bytes)
    rs_bool pl_exp_start_seq (int16 hcam, void_ptr pixel_stream)
    rs_bool pl_exp_check_status (int16 hcam, int16_ptr status, uns32_ptr bytes_arrived)
    int16 pl_error_code()
    rs_bool pl_exp_finish_seq (int16 hcam, void_ptr pixel_stream, int16 hbuf)
    rs_bool pl_exp_uninit_seq ()

pixis.pyx:

cimport cpixis
from cpython.mem cimport PyMem_Malloc, PyMem_Free
cimport numpy as np
import ctypes


cdef class Camera:
    cdef cpixis.rgn_type* _region
    cdef cpixis.int16 _cam_selection
    cdef cpixis.int16 _num_frames
    cdef cpixis.uns32 _exp_time
    cdef char _cam_name[32]
    cdef cpixis.int16 _hCam
    cdef cpixis.uns32 _size
    cdef cpixis.int16 _status
    cdef cpixis.uns32 _notNeeded
    #cdef cpixis.uns16* _frame



    def __cinit__(self):
        self._region = <cpixis.rgn_type *> PyMem_Malloc(sizeof(cpixis.rgn_type))
        if self._region is NULL:
            raise MemoryError()
        #self._frame = <cpixis.uns16 *> PyMem_Malloc( self._size *2 )
        if self._region is NULL:
            raise MemoryError()
        self._cam_selection = 0
        self._num_frames = 1
        self._exp_time = 100
    def __dealloc__(self):
        cpixis.pl_cam_close(self._hCam)
        cpixis.pl_pvcam_uninit()
        if self._region is not NULL:
            PyMem_Free(self._region)
        #if self._frame is not NULL:
        #   PyMem_Free(self._frame)
    def initCamera(self):
        if cpixis.pl_pvcam_init() == False:
            print "Camera failed to init"
            quit()
        if cpixis.pl_cam_get_name(self._cam_selection, self._cam_name) == False:
            print "Didn't get camera name"
            quit()
        if cpixis.pl_cam_open(self._cam_name, &self._hCam, cpixis.OPEN_EXCLUSIVE ) == False:
            print "Camera did not open"
            quit()
    def setRegionOfInterest(self, s1, s2, sbin, p1, p2, pbin):
        self._region.s1 = s1
        self._region.s2 = s2
        self._region.sbin = sbin
        self._region.p1 = p1
        self._region.p2 = p2
        self._region.pbin = pbin
    def acquireImage(self, exposureTime):
        cdef np.ndarray[np.uint16_t, ndim=1] _frame
        self._exp_time = exposureTime
        if cpixis.pl_exp_init_seq() == False:
            print "init_seq Failed"
        if cpixis.pl_exp_setup_seq( self._hCam, 1, 1, self._region, cpixis.TIMED_MODE, self._exp_time, &self._size ) == False:
            print "Experiment failed"
        self.image = np.ndarray(shape=(self._size), dtype=np.uint16, order='C')
        self._frame = np.ascontiguousarray(self.image, dtype=ctypes.c_ushort)
        cpixis.pl_exp_start_seq( self._hCam, &self._frame[0] ); # start image acqusition
        while cpixis.pl_exp_check_status(self._hCam, &self._status, &self._notNeeded) \
              and (self._status != cpixis.READOUT_COMPLETE and self._status != cpixis.READOUT_FAILED):
            pass
        cpixis.pl_exp_finish_seq(self._hCam, &self._frame[0], 0)
        cpixis.pl_exp_uninit_seq()
        self.image = np.copy(self._frame)
        return self.image

Lines 64 and 66 have the same error, which is "Cannot take address of Python variable." I've been working from another similar question here.

Is there a way to make this work, or should I approach this problem differently?

Thanks!

1 Answer 1

0

In the acquireImage() function, I was using the correct idea, but forgot to remove the "self" from the self._frame references. I had started out with _frame declared as a non local variable, but then forgot to update the references in the function when I moved it to a local scope. I removed the extra selfs and the problem went away.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.