使用ctypes

时间:2016-10-27 21:09:03

标签: python camera driver ctypes framebuffer

我遇到问题使用python 读出相机的帧缓冲区。相机(Xenics)通过USB连接,相机随附一个dll。我使用ctypes访问这个DLL。我使用的代码主要受到lantz(lantz_drivers_xenics)的python模块的启发 dll提供了我用来将帧缓冲区复制到numpy数组的函数XC_CopyFrameBuffer

虽然原则上采集工作正常,但问题是以中速或高速连续读取帧缓冲。 相机附带的编译软件能够以24 fps的速度读出相机。在我的程序中,我想在5到25 fps之间读取帧缓冲。但是,我无法达到此值,因为调用XC_CopyFrameBuffer函数所需的时间在0到0.5秒之间变化;它大部分是低的,但大约每隔三帧左右0.5秒。

我的真实程序更复杂,使用线程并处理获取的图像。但是我已经将代码简化为一个最小的例子来重现问题并且我已经附加了。它的文本和图形输出如下所示。我的问题是:

  1. 有没有人遇到类似的相机问题?
  2. 有没有人使用过Xenics相机,通过python中的ctypes连接到它,可以提供一个有效的例子吗?
  3. 我(和/或lantz_drivers_xenics)使用dll的方式是否存在明显或隐藏的问题?
  4. 这是我正在使用的代码:

    import time
    import ctypes 
    import threading
    import numpy as np
    from numpy.ctypeslib import ndpointer
    
    
    calibration_file =  r"C:\Path\to\some\calibrationfile.xca"
    dll = "C:\\Programme\\X-Control\\xcamera.dll"
    lib = ctypes.WinDLL(dll) #for xcamera we need ctypes.WinDLL
    
    exposure_time = 300 #microseconds (us)
    readlock = threading.Lock()
    
    #add types    
    lib.XC_OpenCamera.argtypes = [ctypes.c_uint]
    lib.XC_CloseCamera.argtypes = [ctypes.c_uint]
    lib.XC_IsInitialised.argtypes = [ctypes.c_uint]
    lib.XC_LoadFromFile.argtypes = [ctypes.c_uint, ctypes.c_char_p]
    lib.XC_LoadCalibrationPack.argtypes = [ctypes.c_uint, ctypes.c_char_p]
    lib.XC_SetGainCamera.argtypes = [ctypes.c_uint, ctypes.c_double]
    lib.XC_SetIntegrationTime.argtypes = [ctypes.c_uint, ctypes.c_ulong]
    
    lib.XC_SetFan.argtypes = [ctypes.c_uint, ctypes.c_bool]
    lib.XC_StartCapture.argtypes = [ctypes.c_uint]
    lib.XC_StopCapture.argtypes = [ctypes.c_uint]
    lib.XC_GetFrameSizeInBytes.argtypes = [ctypes.c_uint]
    lib.XC_CloseCamera.restype = ctypes.c_void_p
    lib.XC_StopCapture.restype = ctypes.c_void_p
    
    xcamera_id = lib.XC_OpenCamera(0)
    
    #lib.XC_LoadFromFile(xcamera_id,  self.config_file)
    lib.XC_LoadCalibrationPack(xcamera_id,  calibration_file)
    height = lib.XC_GetHeight(xcamera_id)
    width = lib.XC_GetWidth(xcamera_id)
    shape = (height, width)
    lib.XC_CopyFrameBuffer.argtypes = [ctypes.c_uint, ndpointer(dtype=np.uint16, shape=shape),ctypes.c_uint]
    frame_size = lib.XC_GetFrameSizeInBytes(xcamera_id)
    fbuffer = np.zeros(shape=shape, dtype=np.uint16)
    
    lib.XC_SetIntegrationTime(xcamera_id, exposure_time)
    lib.XC_SetFan(xcamera_id,  True)
    
    lib.XC_StartCapture(xcamera_id)
    
    times = []
    
    for i in range(150):
    
        time.sleep( exposure_time/1000000. ) #  1./25
        if readlock.acquire() : 
            start_time = time.time()
            (lib.XC_CopyFrameBuffer(xcamera_id, fbuffer, frame_size) )
            #time.sleep(0.0002)
            now = time.time()
            readlock.release()
    
            print "Frame {nr}\ttime: {time}".format(time=now-start_time, nr=i)
            times.append(now-start_time)
        else:
            time.sleep(0.001)
            print "Try again" #This gets never printed, so readlock works fine.
    
    
    ###### CLOSING ###########
    lib.XC_StopCapture(xcamera_id)
    lib.XC_SetFan(xcamera_id,  False)
    lib.XC_CloseCamera(xcamera_id)                                         
    
    ###### Plot ###########
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = fig.add_subplot(121)
    ax.imshow(fbuffer, interpolation="none")
    ax2 = fig.add_subplot(122)
    ax2.plot(times)
    plt.savefig("testing/readout.png")
    plt.show()
    

    典型输出看起来像这样,其中时间是复制帧缓冲区所需的时间。

    Frame 72    time: 0.0
    Frame 73    time: 0.0
    Frame 74    time: 0.000999927520752
    Frame 75    time: 0.512000083923
    Frame 76    time: 0.000999927520752
    Frame 77    time: 0.0
    Frame 78    time: 0.516000032425
    Frame 79    time: 0.0
    Frame 80    time: 0.000999927520752
    Frame 81    time: 0.516000032425
    Frame 82    time: 0.0
    Frame 83    time: 0.0
    Frame 84    time: 0.514000177383
    Frame 85    time: 0.0
    Frame 86    time: 0.0759999752045
    

    绘制的图表是这样的(图像看起来与它应该的完全一样)。右图显示每帧的时间(秒)

    enter image description here

    评论:

    • 我在python 2.7
    • 工作
    • 我玩了一些参数:
      • 在循环中的不同位置为x添加具有不同值的time.sleep(x)会增加需要0.5秒读取的帧数。睡眠时间越长,帧读取的时间越长。
      • 提及time.sleep( exposure_time/1000000. )提供空帧。
      • 问题与我是否使用readlock.acquire()无关。
      • 问题与循环次数无关。

0 个答案:

没有答案