使用ctypes从相机读取帧缓冲区

2024-09-30 20:29:06 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

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

  1. 有人遇到过类似的相机问题吗?在
  2. 有没有人使用过Xenics相机,通过python中的ctypes连接到它,并能提供一个工作示例吗?在
  3. 我(和/或lantz_驱动程序)使用dll的方式是否存在一些明显或隐藏的问题?在

这是我使用的代码:

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()

典型的输出如下所示,其中time是复制帧缓冲区所需的时间。

^{pr2}$

绘制的图形是这样的(图像看起来就像它应该的那样)。右图显示每帧的时间(以秒为单位)

enter image description here

评论:

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

Tags: importidtimelib时间sleepctypes缓冲区