Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 73 additions & 29 deletions cython/factory.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import numpy as np

from pylon_def cimport *

cdef extern from "pylon/PylonIncludes.h" namespace 'Pylon':

cpdef enum EGrabStrategy:
GrabStrategy_OneByOne,
GrabStrategy_LatestImageOnly,
GrabStrategy_LatestImages,
GrabStrategy_UpcomingImage

cdef class DeviceInfo:
cdef:
Expand Down Expand Up @@ -195,26 +202,34 @@ cdef class Camera:
self.camera.Close()
elif not self.opened and opened:
self.camera.Open()

property is_grabbing:
def __get__(self):
return self.camera.IsGrabbing()

def open(self):
self.camera.Open()

def close(self):
self.camera.Close()

def stop_grabbing(self):
if self.camera.IsGrabbing():
self.camera.StopGrabbing()

def __del__(self):
self.stop_grabbing()
self.close()
self.camera.DetachDevice()

def __repr__(self):
return '<Camera {0} open={1}>'.format(self.device_info.friendly_name, self.opened)

def grab_images(self, int nr_images, unsigned int timeout=5000):
def grab_images(self, int nr_images = -1, EGrabStrategy grab_strategy=GrabStrategy_OneByOne, unsigned int timeout=5000):

if not self.opened:
raise RuntimeError('Camera not opened')

self.camera.StartGrabbing(nr_images)

cdef CGrabResultPtr ptr_grab_result
cdef IImage* img

Expand All @@ -224,44 +239,73 @@ cdef class Camera:
assert image_format.startswith('Mono'), 'Only mono images allowed at this point'
assert not image_format.endswith('p'), 'Packed data not supported at this point'

while self.camera.IsGrabbing():
try:
if nr_images < 1:
self.camera.StartGrabbing(grab_strategy)
else:
self.camera.StartGrabbing(nr_images, grab_strategy)

while self.camera.IsGrabbing():

with nogil:
# Blocking call into native Pylon C++ SDK code, release GIL so other python threads can run
self.camera.RetrieveResult(timeout, ptr_grab_result)

with nogil:
# Blocking call into native Pylon C++ SDK code, release GIL so other python threads can run
self.camera.RetrieveResult(timeout, ptr_grab_result)
if not ACCESS_CGrabResultPtr_GrabSucceeded(ptr_grab_result):
error_desc = (<string>(ACCESS_CGrabResultPtr_GetErrorDescription(ptr_grab_result))).decode()
raise RuntimeError(error_desc)

if not ACCESS_CGrabResultPtr_GrabSucceeded(ptr_grab_result):
error_desc = (<string>(ACCESS_CGrabResultPtr_GetErrorDescription(ptr_grab_result))).decode()
raise RuntimeError(error_desc)
img = &(<IImage&>ptr_grab_result)
if not img.IsValid():
raise RuntimeError('Graped IImage is not valid.')

img = &(<IImage&>ptr_grab_result)
if not img.IsValid():
raise RuntimeError('Graped IImage is not valid.')
if img.GetImageSize() % img.GetHeight():
print('This image buffer is wired. Probably you will see an error soonish.')
print('\tBytes:', img.GetImageSize())
print('\tHeight:', img.GetHeight())
print('\tWidth:', img.GetWidth())
print('\tGetPaddingX:', img.GetPaddingX())

if img.GetImageSize() % img.GetHeight():
print('This image buffer is wired. Probably you will see an error soonish.')
print('\tBytes:', img.GetImageSize())
print('\tHeight:', img.GetHeight())
print('\tWidth:', img.GetWidth())
print('\tGetPaddingX:', img.GetPaddingX())
assert not img.GetPaddingX(), 'Image padding not supported.'
# TODO: Check GetOrientation to fix oritentation of image if required.

assert not img.GetPaddingX(), 'Image padding not supported.'
# TODO: Check GetOrientation to fix oritentation of image if required.
img_data = np.frombuffer((<char*>img.GetBuffer())[:img.GetImageSize()], dtype='uint'+bits_per_pixel_prop[3:])

img_data = np.frombuffer((<char*>img.GetBuffer())[:img.GetImageSize()], dtype='uint'+bits_per_pixel_prop[3:])
# TODO: How to handle multi-byte data here?
img_data = img_data.reshape((img.GetHeight(), -1))
# img_data = img_data[:img.GetHeight(), :img.GetWidth()]
yield img_data

# TODO: How to handle multi-byte data here?
img_data = img_data.reshape((img.GetHeight(), -1))
# img_data = img_data[:img.GetHeight(), :img.GetWidth()]
yield img_data
except:
self.stop_grabbing()
raise

def grab_image(self, unsigned int timeout=5000):
return next(self.grab_images(1, timeout))
def grab_image(self, EGrabStrategy grab_strategy=GrabStrategy_OneByOne, unsigned int timeout=5000):
return next(self.grab_images(1, grab_strategy, timeout))

property properties:
def __get__(self):
return _PropertyMap.create(&self.camera.GetNodeMap())

# Configuration properties associated with various grab strategies
property max_num_buffer:
def __get__(self):
return self.camera.MaxNumBuffer.GetValue()
def __set__(self, value):
self.camera.MaxNumBuffer.SetValue(value)

property max_num_queued_buffer:
def __get__(self):
return self.camera.MaxNumQueuedBuffer.GetValue()
def __set__(self, value):
self.camera.MaxNumQueuedBuffer.SetValue(value)

property output_queue_size:
def __get__(self):
return self.camera.OutputQueueSize.GetValue()
def __set__(self, value):
self.camera.OutputQueueSize.SetValue(value)


cdef class Factory:
def __cinit__(self):
Expand All @@ -288,4 +332,4 @@ cdef class Factory:

def create_device(self, DeviceInfo dev_info):
cdef CTlFactory* tl_factory = &GetInstance()
return Camera.create(tl_factory.CreateDevice(dev_info.dev_info))
return Camera.create(tl_factory.CreateDevice(dev_info.dev_info))
20 changes: 18 additions & 2 deletions cython/pylon_def.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,37 @@ cdef extern from "pylon/PylonIncludes.h" namespace 'Pylon':
String_t GetVendorName() except +
String_t GetDeviceClass() except +

cdef enum EGrabStrategy:
GrabStrategy_OneByOne,
GrabStrategy_LatestImageOnly,
GrabStrategy_LatestImages,
GrabStrategy_UpcomingImage

cdef cppclass CInstantCamera:
CInstantCamera()
void Attach(IPylonDevice*)
CDeviceInfo& GetDeviceInfo() except +
void IsCameraDeviceRemoved()
void Open() except +
void Close() except +
void StopGrabbing() except +
bool IsOpen() except +
IPylonDevice* DetachDevice() except +
void StartGrabbing(size_t maxImages) except + #FIXME: implement different strategies
void StartGrabbing(EGrabStrategy strategy) except +
void StartGrabbing(size_t maxImages, EGrabStrategy strategy) except +
bool IsGrabbing()
# RetrieveResult() is blocking call into C++ native SDK, allow it to be called without GIL
bool RetrieveResult(unsigned int timeout_ms, CGrabResultPtr& grab_result) nogil except + # FIXME: Timout handling
INodeMap& GetNodeMap()

# From CInstantCameraParams_Params base class
IInteger &MaxNumBuffer;
IInteger &MaxNumQueuedBuffer;
IInteger &OutputQueueSize;




cdef cppclass DeviceInfoList_t:
cppclass iterator:
CDeviceInfo operator*()
Expand All @@ -148,4 +164,4 @@ cdef extern from "pylon/PylonIncludes.h" namespace 'Pylon::CTlFactory':
cdef extern from 'hacks.h':
bool ACCESS_CGrabResultPtr_GrabSucceeded(CGrabResultPtr ptr)
String_t ACCESS_CGrabResultPtr_GetErrorDescription(CGrabResultPtr ptr)
uint32_t ACCESS_CGrabResultPtr_GetErrorCode(CGrabResultPtr ptr)
uint32_t ACCESS_CGrabResultPtr_GetErrorCode(CGrabResultPtr ptr)
23 changes: 22 additions & 1 deletion pypylon/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
from pypylon.cython.factory import Factory
from pypylon.cython.version import PylonVersion

# With earlier versions of python that don't support PEP 435 enums (discovered on an Ubuntu 14.04 with stock python 2.7.6) cython
# seems to silently drop the EGrabStrategy enum. declared with cpdef directive in factory.pyx, so have to define it manually.
GrabStrategy_OneByOne = 0
GrabStrategy_LatestImageOnly = 1
GrabStrategy_LatestImages = 2
GrabStrategy_UpcomingImage = 3

try:
# If running on python version where EGrabStrategy is sucessfully exported, sanity check that values match our manual
# definitions
from pypylon.cython.factory import EGrabStrategy

assert GrabStrategy_OneByOne == EGrabStrategy.GrabStrategy_OneByOne
assert GrabStrategy_LatestImageOnly == EGrabStrategy.GrabStrategy_LatestImageOnly
assert GrabStrategy_LatestImages == EGrabStrategy.GrabStrategy_LatestImages
assert GrabStrategy_UpcomingImage == EGrabStrategy.GrabStrategy_UpcomingImage

except ImportError:
pass


factory = Factory()
pylon_version = PylonVersion()
pylon_version = PylonVersion()