我遇到问题使用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秒。
我的真实程序更复杂,使用线程并处理获取的图像。但是我已经将代码简化为一个最小的例子来重现问题并且我已经附加了。它的文本和图形输出如下所示。我的问题是:
这是我正在使用的代码:
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
绘制的图表是这样的(图像看起来与它应该的完全一样)。右图显示每帧的时间(秒)
评论:
time.sleep(x)
会增加需要0.5秒读取的帧数。睡眠时间越长,帧读取的时间越长。 time.sleep( exposure_time/1000000. )
提供空帧。readlock.acquire()
无关。