From fac2f7b87ebebf0a3255b9d02cddff24fa194226 Mon Sep 17 00:00:00 2001 From: morefigs Date: Fri, 22 Jun 2018 15:59:49 +1000 Subject: rename --- pymba/__init__.py | 2 +- pymba/tests/__init__.py | 0 pymba/tests/opencv_example.py | 76 ----- pymba/tests/opencv_liveview_example.py | 79 ----- pymba/tests/opencv_liveview_example_color.py | 89 ----- pymba/tests/test_cameras.py | 72 ---- pymba/tests/test_enumfeature.py | 25 -- pymba/tests/test_installation.py | 9 - pymba/tests/test_interfaces.py | 28 -- pymba/tests/test_systemfeature.py | 20 -- pymba/vimba.py | 12 +- pymba/vimba_camera.py | 129 +++++++ pymba/vimba_dll.py | 489 +++++++++++++++++++++++++++ pymba/vimba_exception.py | 61 ++++ pymba/vimba_feature.py | 341 +++++++++++++++++++ pymba/vimba_frame.py | 175 ++++++++++ pymba/vimba_interface.py | 47 +++ pymba/vimba_object.py | 232 +++++++++++++ pymba/vimba_structure.py | 106 ++++++ pymba/vimba_system.py | 22 ++ pymba/vimbacamera.py | 129 ------- pymba/vimbadll.py | 489 --------------------------- pymba/vimbaexception.py | 61 ---- pymba/vimbafeature.py | 341 ------------------- pymba/vimbaframe.py | 175 ---------- pymba/vimbainterface.py | 47 --- pymba/vimbaobject.py | 232 ------------- pymba/vimbastructure.py | 106 ------ pymba/vimbasystem.py | 24 -- tests/__init__.py | 0 tests/opencv_example.py | 76 +++++ tests/opencv_liveview_example.py | 79 +++++ tests/opencv_liveview_example_color.py | 89 +++++ tests/test_cameras.py | 72 ++++ tests/test_enumfeature.py | 25 ++ tests/test_installation.py | 9 + tests/test_interfaces.py | 28 ++ tests/test_systemfeature.py | 20 ++ 38 files changed, 2007 insertions(+), 2009 deletions(-) delete mode 100644 pymba/tests/__init__.py delete mode 100644 pymba/tests/opencv_example.py delete mode 100644 pymba/tests/opencv_liveview_example.py delete mode 100644 pymba/tests/opencv_liveview_example_color.py delete mode 100644 pymba/tests/test_cameras.py delete mode 100644 pymba/tests/test_enumfeature.py delete mode 100644 pymba/tests/test_installation.py delete mode 100644 pymba/tests/test_interfaces.py delete mode 100644 pymba/tests/test_systemfeature.py create mode 100644 pymba/vimba_camera.py create mode 100644 pymba/vimba_dll.py create mode 100644 pymba/vimba_exception.py create mode 100644 pymba/vimba_feature.py create mode 100644 pymba/vimba_frame.py create mode 100644 pymba/vimba_interface.py create mode 100644 pymba/vimba_object.py create mode 100644 pymba/vimba_structure.py create mode 100644 pymba/vimba_system.py delete mode 100644 pymba/vimbacamera.py delete mode 100644 pymba/vimbadll.py delete mode 100644 pymba/vimbaexception.py delete mode 100644 pymba/vimbafeature.py delete mode 100644 pymba/vimbaframe.py delete mode 100644 pymba/vimbainterface.py delete mode 100644 pymba/vimbaobject.py delete mode 100644 pymba/vimbastructure.py delete mode 100644 pymba/vimbasystem.py create mode 100644 tests/__init__.py create mode 100644 tests/opencv_example.py create mode 100644 tests/opencv_liveview_example.py create mode 100644 tests/opencv_liveview_example_color.py create mode 100644 tests/test_cameras.py create mode 100644 tests/test_enumfeature.py create mode 100644 tests/test_installation.py create mode 100644 tests/test_interfaces.py create mode 100644 tests/test_systemfeature.py diff --git a/pymba/__init__.py b/pymba/__init__.py index c6c69cd..c21ed07 100644 --- a/pymba/__init__.py +++ b/pymba/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import from .vimba import Vimba -from .vimbaexception import VimbaException +from .vimba_exception import VimbaException diff --git a/pymba/tests/__init__.py b/pymba/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pymba/tests/opencv_example.py b/pymba/tests/opencv_example.py deleted file mode 100644 index 238e8b4..0000000 --- a/pymba/tests/opencv_example.py +++ /dev/null @@ -1,76 +0,0 @@ -from __future__ import absolute_import, print_function, division -from pymba import * -import numpy as np -import cv2 -import time - -#very crude example, assumes your camera is PixelMode = BAYERRG8 - -# start Vimba -with Vimba() as vimba: - # get system object - system = vimba.getSystem() - - # list available cameras (after enabling discovery for GigE cameras) - if system.GeVTLIsPresent: - system.runFeatureCommand("GeVDiscoveryAllOnce") - time.sleep(0.2) - cameraIds = vimba.getCameraIds() - for cameraId in cameraIds: - print('Camera ID:', cameraId) - - # get and open a camera - camera0 = vimba.getCamera(cameraIds[0]) - camera0.openCamera() - - # list camera features - cameraFeatureNames = camera0.getFeatureNames() - for name in cameraFeatureNames: - print('Camera feature:', name) - - # read info of a camera feature - #featureInfo = camera0.getFeatureInfo('AcquisitionMode') - #for field in featInfo.getFieldNames(): - # print field, '--', getattr(featInfo, field) - - # get the value of a feature - print(camera0.AcquisitionMode) - - # set the value of a feature - camera0.AcquisitionMode = 'SingleFrame' - - # create new frames for the camera - frame0 = camera0.getFrame() # creates a frame - frame1 = camera0.getFrame() # creates a second frame - - # announce frame - frame0.announceFrame() - - # capture a camera image - count = 0 - while count < 10: - camera0.startCapture() - frame0.queueFrameCapture() - camera0.runFeatureCommand('AcquisitionStart') - camera0.runFeatureCommand('AcquisitionStop') - frame0.waitFrameCapture() - - # get image data... - imgData = frame0.getBufferByteData() - - moreUsefulImgData = np.ndarray(buffer = frame0.getBufferByteData(), - dtype = np.uint8, - shape = (frame0.height, - frame0.width, - 1)) - rgb = cv2.cvtColor(moreUsefulImgData, cv2.COLOR_BAYER_RG2RGB) - cv2.imwrite('foo{}.png'.format(count), rgb) - print("image {} saved".format(count)) - count += 1 - camera0.endCapture() - # clean up after capture - camera0.revokeAllFrames() - - # close camera - camera0.closeCamera() - diff --git a/pymba/tests/opencv_liveview_example.py b/pymba/tests/opencv_liveview_example.py deleted file mode 100644 index 78b6b67..0000000 --- a/pymba/tests/opencv_liveview_example.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Mon Jul 07 14:59:03 2014 - -@author: derricw -""" - -from __future__ import absolute_import, print_function, division -from pymba import * -import numpy as np -import cv2 -import time - -cv2.namedWindow("test") - -with Vimba() as vimba: - system = vimba.getSystem() - - system.runFeatureCommand("GeVDiscoveryAllOnce") - time.sleep(0.2) - - camera_ids = vimba.getCameraIds() - - for cam_id in camera_ids: - print("Camera found: ", cam_id) - - c0 = vimba.getCamera(camera_ids[0]) - c0.openCamera() - - try: - #gigE camera - print(c0.GevSCPSPacketSize) - print(c0.StreamBytesPerSecond) - c0.StreamBytesPerSecond = 100000000 - except: - #not a gigE camera - pass - - #set pixel format - c0.PixelFormat="Mono8" - #c0.ExposureTimeAbs=60000 - - frame = c0.getFrame() - frame.announceFrame() - - c0.startCapture() - - framecount = 0 - droppedframes = [] - - while 1: - try: - frame.queueFrameCapture() - success = True - except: - droppedframes.append(framecount) - success = False - c0.runFeatureCommand("AcquisitionStart") - c0.runFeatureCommand("AcquisitionStop") - frame.waitFrameCapture(1000) - frame_data = frame.getBufferByteData() - if success: - img = np.ndarray(buffer=frame_data, - dtype=np.uint8, - shape=(frame.height,frame.width,1)) - cv2.imshow("test",img) - framecount+=1 - k = cv2.waitKey(1) - if k == 0x1b: - cv2.destroyAllWindows() - print("Frames displayed: %i"%framecount) - print("Frames dropped: %s"%droppedframes) - break - - - c0.endCapture() - c0.revokeAllFrames() - - c0.closeCamera() diff --git a/pymba/tests/opencv_liveview_example_color.py b/pymba/tests/opencv_liveview_example_color.py deleted file mode 100644 index fd7a819..0000000 --- a/pymba/tests/opencv_liveview_example_color.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Mon Jul 07 14:59:03 2014 - -@author: derricw - -Same as the other liveview example, but displays in color. - -Obviously you want to use a camera that has a color mode like BGR8Packed - -OpenCV is expecting color images to be in BGR8Packed by default. It can work - with other formats as well as convert one to the other, but this example - just uses its default behavior. - -""" -from __future__ import absolute_import, print_function, division -from pymba import * -import numpy as np -import cv2 -import time -import sys - -cv2.namedWindow("test") - -with Vimba() as vimba: - system = vimba.getSystem() - - system.runFeatureCommand("GeVDiscoveryAllOnce") - time.sleep(0.2) - - camera_ids = vimba.getCameraIds() - - for cam_id in camera_ids: - print("Camera found: ", cam_id) - - c0 = vimba.getCamera(camera_ids[0]) - c0.openCamera() - - try: - #gigE camera - print("Packet size:", c0.GevSCPSPacketSize) - c0.StreamBytesPerSecond = 100000000 - print("BPS:", c0.StreamBytesPerSecond) - except: - #not a gigE camera - pass - - #set pixel format - c0.PixelFormat = "BGR8Packed" # OPENCV DEFAULT - time.sleep(0.2) - - frame = c0.getFrame() - frame.announceFrame() - - c0.startCapture() - - framecount = 0 - droppedframes = [] - - while 1: - try: - frame.queueFrameCapture() - success = True - except: - droppedframes.append(framecount) - success = False - c0.runFeatureCommand("AcquisitionStart") - c0.runFeatureCommand("AcquisitionStop") - frame.waitFrameCapture(1000) - frame_data = frame.getBufferByteData() - if success: - img = np.ndarray(buffer=frame_data, - dtype=np.uint8, - shape=(frame.height, frame.width, frame.pixel_bytes)) - cv2.imshow("test", img) - framecount += 1 - k = cv2.waitKey(1) - if k == 0x1b: - cv2.destroyAllWindows() - print("Frames displayed: %i" % framecount) - print("Frames dropped: %s" % droppedframes) - break - - - c0.endCapture() - c0.revokeAllFrames() - - c0.closeCamera() - diff --git a/pymba/tests/test_cameras.py b/pymba/tests/test_cameras.py deleted file mode 100644 index a5a4dd9..0000000 --- a/pymba/tests/test_cameras.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * -import time - - -def test_cameras(): - # start Vimba - with Vimba() as vimba: - # get system object - system = vimba.getSystem() - - # list available cameras (after enabling discovery for GigE cameras) - if system.GeVTLIsPresent: - system.runFeatureCommand("GeVDiscoveryAllOnce") - time.sleep(0.2) - - cameraIds = vimba.getCameraIds() - for cameraId in cameraIds: - print('Camera ID:', cameraId) - - # get and open a camera - camera0 = vimba.getCamera(cameraIds[0]) - camera0.openCamera() - - # list camera features - cameraFeatureNames = camera0.getFeatureNames() - for name in cameraFeatureNames: - print('Camera feature:', name) - - # get the value of a feature - print(camera0.AcquisitionMode) - - # set the value of a feature - camera0.AcquisitionMode = 'SingleFrame' - - # create new frames for the camera - frame0 = camera0.getFrame() # creates a frame - frame1 = camera0.getFrame() # creates a second frame - - # announce frame - frame0.announceFrame() - - # capture a camera image - camera0.startCapture() - frame0.queueFrameCapture() - camera0.runFeatureCommand('AcquisitionStart') - camera0.runFeatureCommand('AcquisitionStop') - frame0.waitFrameCapture() - - # get image data... - imgData = frame0.getBufferByteData() - - # ...or use NumPy for fast image display (for use with OpenCV, etc) - import numpy as np - - moreUsefulImgData = np.ndarray(buffer=frame0.getBufferByteData(), - dtype=np.uint8, - shape=(frame0.height, - frame0.width, - 1)) - - # clean up after capture - camera0.endCapture() - camera0.revokeAllFrames() - - # close camera - camera0.closeCamera() - - -if __name__ == '__main__': - test_cameras() \ No newline at end of file diff --git a/pymba/tests/test_enumfeature.py b/pymba/tests/test_enumfeature.py deleted file mode 100644 index 7f9dd4c..0000000 --- a/pymba/tests/test_enumfeature.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * - - -def test_enumfeature(): - # get system object - with Vimba() as vimba: - system = vimba.getSystem() - - # get enum value - print ("get enum value (DiscoveryCameraEvent): '%s'" % (system.DiscoveryCameraEvent)) - - # get enum range - range = system.getFeatureRange('DiscoveryCameraEvent') - print ("get enum value range (DiscoveryCameraEvent): '%s'" % (str(range))) - - # set enum value - #print ("setting enum value (DiscoveryCameraEvent)...") - #system.DiscoveryCameraEvent = 'Unreachable' - #print ("enum value (DiscoveryCameraEvent)set to '%s'." % (system.DiscoveryCameraEvent.value)) - - -if __name__ == '__main__': - test_enumfeature() \ No newline at end of file diff --git a/pymba/tests/test_installation.py b/pymba/tests/test_installation.py deleted file mode 100644 index 06af7d6..0000000 --- a/pymba/tests/test_installation.py +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import Vimba - - -def test_installation(): - with Vimba() as vimba: - version = vimba.getVersion() - assert version == '1.2.0' diff --git a/pymba/tests/test_interfaces.py b/pymba/tests/test_interfaces.py deleted file mode 100644 index 270d42c..0000000 --- a/pymba/tests/test_interfaces.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * -import time - - -def test_interfaces(): - # start Vimba - with Vimba() as vimba: - # get list of available interfaces - interfaceIds = vimba.getInterfaceIds() - for interfaceId in interfaceIds: - print('Interface ID:', interfaceId) - - # get interface object and open it - interface0 = vimba.getInterface(interfaceIds[0]) - interface0.openInterface() - - # list interface features - interfaceFeatureNames = interface0.getFeatureNames() - for name in interfaceFeatureNames: - print('Interface feature:', name) - - # close interface - interface0.closeInterface() - -if __name__ == '__main__': - test_interfaces() \ No newline at end of file diff --git a/pymba/tests/test_systemfeature.py b/pymba/tests/test_systemfeature.py deleted file mode 100644 index abb4da7..0000000 --- a/pymba/tests/test_systemfeature.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python -from __future__ import absolute_import, print_function, division -from pymba import * - - -def test_systemfeature(): - # get system object - with Vimba() as vimba: - system = vimba.getSystem() - - # list system features - for featureName in system.getFeatureNames(): - print('System feature:', featureName) - fInfo = system.getFeatureInfo(featureName) - for field in fInfo.getFieldNames(): - print("\t", featureName, ":", field, getattr(fInfo, field)) - - -if __name__ == '__main__': - test_systemfeature() \ No newline at end of file diff --git a/pymba/vimba.py b/pymba/vimba.py index a1ffeaa..475dedd 100644 --- a/pymba/vimba.py +++ b/pymba/vimba.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import -from . import vimbastructure as structs -from .vimbadll import VimbaDLL -from .vimbaexception import VimbaException -from .vimbasystem import VimbaSystem -from .vimbacamera import VimbaCamera -from .vimbainterface import VimbaInterface +from . import vimba_structure as structs +from .vimba_dll import VimbaDLL +from .vimba_exception import VimbaException +from .vimba_system import VimbaSystem +from .vimba_camera import VimbaCamera +from .vimba_interface import VimbaInterface from ctypes import * diff --git a/pymba/vimba_camera.py b/pymba/vimba_camera.py new file mode 100644 index 0000000..5e131a1 --- /dev/null +++ b/pymba/vimba_camera.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from . import vimba_structure as structs +from .vimba_object import VimbaObject +from .vimba_exception import VimbaException +from .vimba_frame import VimbaFrame +from .vimba_dll import VimbaDLL +from ctypes import * + +# camera features are automatically readable as object attributes. + + +class VimbaCamera(VimbaObject): + + """ + A Vimba camera object. This class provides the minimal access + to Vimba functions required to control the camera. + """ + + @property + def cameraIdString(self): + return self._cameraIdString.decode() + + # own handle is inherited as self._handle + def __init__(self, cameraIdString): + + # call super constructor + super(VimbaCamera, self).__init__() + + # set ID + self._cameraIdString = cameraIdString.encode() + + # set own info + self._info = self._getInfo() + + def getInfo(self): + """ + Get info of the camera. Does not require + the camera to be opened. + + :returns: VimbaCameraInfo object -- camera information. + """ + return self._info + + def _getInfo(self): + """ + Get info of the camera. Does not require + the camera to be opened. + + :returns: VimbaCameraInfo object -- camera information. + """ + # args for Vimba call + cameraInfo = structs.VimbaCameraInfo() + + # Vimba DLL will return an error code + errorCode = VimbaDLL.cameraInfoQuery(self._cameraIdString, + byref(cameraInfo), + sizeof(cameraInfo)) + if errorCode != 0: + raise VimbaException(errorCode) + + return cameraInfo + + def openCamera(self, cameraAccessMode=1): + """ + Open the camera with requested access mode + Available access modes: + 0 : VmbAccessModeNone + 1 : VmbAccessModeFull + 2 : VmbAccessModeRead + 3 : VmbAccessModeConfig + 4 : VmbAccessModeLite + """ + # args for Vimba call + errorCode = VimbaDLL.cameraOpen(self._cameraIdString, + cameraAccessMode, + byref(self._handle)) + if errorCode != 0: + raise VimbaException(errorCode) + + def closeCamera(self): + """ + Close the camera. + """ + errorCode = VimbaDLL.cameraClose(self._handle) + if errorCode != 0: + raise VimbaException(errorCode) + + def revokeAllFrames(self): + """ + Revoke all frames assigned to the camera. + """ + errorCode = VimbaDLL.frameRevokeAll(self._handle) + if errorCode != 0: + raise VimbaException(errorCode) + + def startCapture(self): + """ + Prepare the API for incoming frames. + """ + errorCode = VimbaDLL.captureStart(self._handle) + if errorCode != 0: + raise VimbaException(errorCode) + + def endCapture(self): + """ + Stop the API from being able to receive frames. + """ + errorCode = VimbaDLL.captureEnd(self._handle) + if errorCode != 0: + raise VimbaException(errorCode) + + def flushCaptureQueue(self): + """ + Flush the capture queue. + """ + errorCode = VimbaDLL.captureQueueFlush(self._handle) + if errorCode != 0: + raise VimbaException(errorCode) + + # method for easy frame creation + def getFrame(self): + """ + Creates and returns a new frame object. Multiple frames + per camera can therefore be returned. + + :returns: VimbaFrame object -- the new frame. + """ + return VimbaFrame(self) diff --git a/pymba/vimba_dll.py b/pymba/vimba_dll.py new file mode 100644 index 0000000..a62b087 --- /dev/null +++ b/pymba/vimba_dll.py @@ -0,0 +1,489 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +from sys import platform as sys_plat +import platform +import os +from ctypes import * + +from . import vimba_structure as structs +from .vimba_exception import VimbaException + +if sys_plat == "win32": + + def find_win_dll(arch): + """ Finds the highest versioned windows dll for the specified architecture. """ + bases = [ + r'C:\Program Files\Allied Vision Technologies\AVTVimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll', + r'C:\Program Files\Allied Vision\Vimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll' + ] + dlls = [] + for base in bases: + for major in range(3): + for minor in range(10): + candidate = base % (major, minor, arch) + if os.path.isfile(candidate): + dlls.append(candidate) + if not dlls: + if 'VIMBA_HOME' in os.environ: + candidate = os.environ ['VIMBA_HOME'] + '\VimbaC\Bin\Win%i\VimbaC.dll' % (arch) + if os.path.isfile(candidate): + dlls.append(candidate) + if not dlls: + raise IOError("VimbaC.dll not found.") + return dlls[-1] + + if '64' in platform.architecture()[0]: + vimbaC_path = find_win_dll(64) + else: + vimbaC_path = find_win_dll(32) + dll_loader = windll +else: + + dll_loader = cdll + + if 'x86_64' in os.uname()[4]: + assert os.environ.get( + "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_64bit/libVimbaC.so" + elif 'x86_32' in os.uname()[4]: + print("Warning: x86_32 reached!") + assert os.environ.get( + "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_32bit/libVimbaC.so" + elif 'arm' in os.uname()[4]: + assert os.environ.get( + "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_32bit/libVimbaC.so" + elif 'aarch64' in os.uname()[4]: + assert os.environ.get( + "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" + tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] + vimba_dir = "/".join(tlPath.split("/")[1:-3]) + vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_64bit/libVimbaC.so" + else: + raise ValueError("Pymba currently doesn't support %s" % os.uname()[4]) + + +# Callback Function Type +if sys_plat == "win32": + CB_FUNCTYPE = WINFUNCTYPE +else: + # Untested! + CB_FUNCTYPE = CFUNCTYPE + + +class VimbaDLL(object): + + """ + ctypes directives to make the wrapper class work cleanly, + talks to VimbaC.dll + """ + # a full list of Vimba API methods + # (only double dashed methods have been implemented so far) + # + # -- VmbVersionQuery() + # + # -- VmbStartup() + # -- VmbShutdown() + # + # -- VmbCamerasList() + # -- VmbCameraInfoQuery() + # -- VmbCameraOpen() + # -- VmbCameraClose() + # + # -- VmbFeaturesList() + # -- VmbFeatureInfoQuery() + # VmbFeatureListAffected() + # VmbFeatureListSelected() + # VmbFeatureAccessQuery() + # + # -- VmbFeatureIntGet() + # -- VmbFeatureIntSet() + # -- VmbFeatureIntRangeQuery() + # VmbFeatureIntIncrementQuery() + # + # -- VmbFeatureFloatGet() + # -- VmbFeatureFloatSet() + # -- VmbFeatureFloatRangeQuery() + # + # -- VmbFeatureEnumGet() + # -- VmbFeatureEnumSet() + # -- VmbFeatureEnumRangeQuery() + # VmbFeatureEnumIsAvailable() + # VmbFeatureEnumAsInt() + # VmbFeatureEnumAsString() + # VmbFeatureEnumEntryGet() + # + # -- VmbFeatureStringGet() + # -- VmbFeatureStringSet() + # VmbFeatureStringMaxlengthQuery() + # + # -- VmbFeatureBoolGet() + # -- VmbFeatureBoolSet() + # + # -- VmbFeatureCommandRun() + # VmbFeatureCommandIsDone() + # + # VmbFeatureRawGet() + # VmbFeatureRawSet() + # VmbFeatureRawLengthQuery() + # + # VmbFeatureInvalidationRegister() + # VmbFeatureInvalidationUnregister() + # + # -- VmbFrameAnnounce() + # -- VmbFrameRevoke() + # -- VmbFrameRevokeAll() + # -- VmbCaptureStart() + # -- VmbCaptureEnd() + # -- VmbCaptureFrameQueue() + # -- VmbCaptureFrameWait() + # -- VmbCaptureQueueFlush() + # + # -- VmbInterfacesList() + # -- VmbInterfaceOpen() + # -- VmbInterfaceClose() + # + # VmbAncillaryDataOpen() + # VmbAncillaryDataClose() + # + # VmbMemoryRead() + # VmbMemoryWrite() + # -- VmbRegistersRead() + # -- VmbRegistersWrite() + + # Vimba C API DLL + _vimbaDLL = dll_loader.LoadLibrary(vimbaC_path) + + # version query + versionQuery = _vimbaDLL.VmbVersionQuery + # returned error code + versionQuery.restype = c_int32 + versionQuery.argtypes = (POINTER(structs.VimbaVersion), # pointer to version structure + c_uint32) # version structure size + + # startup + startup = _vimbaDLL.VmbStartup + # returned error code + startup.restype = c_int32 + + # shutdown + shutdown = _vimbaDLL.VmbShutdown + + # list cameras + camerasList = _vimbaDLL.VmbCamerasList + # returned error code + camerasList.restype = c_int32 + camerasList.argtypes = (POINTER(structs.VimbaCameraInfo), # pointer to camera info structure + # length of list + c_uint32, + # pointer to number of cameras + POINTER(c_uint32), + c_uint32) # camera info structure size + + # camera info query + cameraInfoQuery = _vimbaDLL.VmbCameraInfoQuery + cameraInfoQuery.restype = c_int32 + cameraInfoQuery.argtypes = (c_char_p, # camera unique id + # pointer to camera info structure + POINTER(structs.VimbaCameraInfo), + c_uint32) # size of structure + + # camera open + cameraOpen = _vimbaDLL.VmbCameraOpen + # returned error code + cameraOpen.restype = c_int32 + cameraOpen.argtypes = (c_char_p, # camera unique id + # access mode + c_uint32, + c_void_p) # camera handle, pointer to a pointer + + # camera close + cameraClose = _vimbaDLL.VmbCameraClose + # returned error code + cameraClose.restype = c_int32 + # camera handle + cameraClose.argtypes = (c_void_p,) + + # list features + featuresList = _vimbaDLL.VmbFeaturesList + featuresList.restype = c_int32 + featuresList.argtypes = (c_void_p, # handle, in this case camera handle + # pointer to feature info structure + POINTER(structs.VimbaFeatureInfo), + # list length + c_uint32, + # pointer to num features found + POINTER(c_uint32), + c_uint32) # feature info size + + # feature info query + featureInfoQuery = _vimbaDLL.VmbFeatureInfoQuery + featureInfoQuery.restype = c_int32 + featureInfoQuery.argtypes = (c_void_p, # handle, in this case camera handle + # name of feature + c_char_p, + # pointer to feature info structure + POINTER(structs.VimbaFeatureInfo), + c_uint32) # size of structure + + # get the int value of a feature + featureIntGet = _vimbaDLL.VmbFeatureIntGet + featureIntGet.restype = c_int32 + featureIntGet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + POINTER(c_int64)) # value to get + + # set the int value of a feature + featureIntSet = _vimbaDLL.VmbFeatureIntSet + featureIntSet.restype = c_int32 + featureIntSet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + c_int64) # value to set # get the value of an integer feature + + # query the range of values of the feature + featureIntRangeQuery = _vimbaDLL.VmbFeatureIntRangeQuery + featureIntRangeQuery.restype = c_int32 + featureIntRangeQuery.argtypes = (c_void_p, # handle + # name of the feature + c_char_p, + # min range + POINTER(c_int64), + POINTER(c_int64)) # max range + + # get the float value of a feature + featureFloatGet = _vimbaDLL.VmbFeatureFloatGet + featureFloatGet.restype = c_int32 + featureFloatGet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + POINTER(c_double)) # value to get + + # set the float value of a feature + featureFloatSet = _vimbaDLL.VmbFeatureFloatSet + featureFloatSet.restype = c_int32 + featureFloatSet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + c_double) # value to set + + # query the range of values of the feature + featureFloatRangeQuery = _vimbaDLL.VmbFeatureFloatRangeQuery + featureFloatRangeQuery.restype = c_int32 + featureFloatRangeQuery.argtypes = (c_void_p, # handle + # name of the feature + c_char_p, + # min range + POINTER(c_double), + POINTER(c_double)) # max range + + # get the enum value of a feature + featureEnumGet = _vimbaDLL.VmbFeatureEnumGet + featureEnumGet.restype = c_int32 + featureEnumGet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + POINTER(c_char_p)) # value to get + + # set the enum value of a feature + featureEnumSet = _vimbaDLL.VmbFeatureEnumSet + featureEnumSet.restype = c_int32 + featureEnumSet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + c_char_p) # value to set + + # query the range of values of the feature + featureEnumRangeQuery = _vimbaDLL.VmbFeatureEnumRangeQuery + featureEnumRangeQuery.restype = c_int32 + featureEnumRangeQuery.argtypes = (c_void_p, # handle + # name of the feature + c_char_p, + # pointer to enum names (array) + POINTER(c_char_p), + # array length + c_uint32, + # pointer to num enum names found + POINTER(c_uint32)) + + # get the string value of a feature + featureStringGet = _vimbaDLL.VmbFeatureStringGet + featureStringGet.restype = c_int32 + featureStringGet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + # string buffer to fill + c_char_p, + # size of the input buffer + c_uint32, + POINTER(c_uint32)) # string buffer to fill + + # set the string value of a feature + featureStringSet = _vimbaDLL.VmbFeatureStringSet + featureStringSet.restype = c_int32 + featureStringSet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + c_char_p) # value to set + + # get the boolean value of a feature + featureBoolGet = _vimbaDLL.VmbFeatureBoolGet + featureBoolGet.restype = c_int32 + featureBoolGet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + POINTER(c_bool)) # value to get + + # set the boolean value of a feature + featureBoolSet = _vimbaDLL.VmbFeatureBoolSet + featureBoolSet.restype = c_int32 + featureBoolSet.argtypes = (c_void_p, # handle, in this case camera handle + # name of the feature + c_char_p, + c_bool) # value to set + + # run a feature command + featureCommandRun = _vimbaDLL.VmbFeatureCommandRun + featureCommandRun.restype = c_int32 + featureCommandRun.argtypes = (c_void_p, # handle for a module that exposes features + c_char_p) # name of the command feature + + # Check if a feature command is done + featureCommandIsDone = _vimbaDLL.VmbFeatureCommandIsDone + featureCommandIsDone.restype = c_int32 + featureCommandIsDone.argtypes = (c_void_p, # handle + c_char_p, # name of the command feature + POINTER(c_bool)) # pointer to a result bool + + # announce frames to the API that may be queued for frame capturing later + frameAnnounce = _vimbaDLL.VmbFrameAnnounce + frameAnnounce.restype = c_int32 + frameAnnounce.argtypes = (c_void_p, # camera handle + # pointer to frame + POINTER(structs.VimbaFrame), + c_uint32) # size of frame + + # callback for frame queue + frameDoneCallback = CB_FUNCTYPE(c_void_p, # Return Type + c_void_p, # Camera Hanlde + POINTER(structs.VimbaFrame)) # Pointer to frame + + # revoke a frame from the API + frameRevoke = _vimbaDLL.VmbFrameRevoke + frameRevoke.restype = c_int32 + frameRevoke.argtypes = (c_void_p, # camera handle + POINTER(structs.VimbaFrame)) # pointer to frame + + # revoke all frames assigned to a certain camera + frameRevokeAll = _vimbaDLL.VmbFrameRevokeAll + frameRevokeAll.restype = c_int32 + # camera handle + frameRevokeAll.argtypes = (c_void_p,) + + # prepare the API for incoming frames + captureStart = _vimbaDLL.VmbCaptureStart + captureStart.restype = c_int32 + # camera handle + captureStart.argtypes = (c_void_p,) + + # stop the API from being able to receive frames + captureEnd = _vimbaDLL.VmbCaptureEnd + captureEnd.restype = c_int32 + # camera handle + captureEnd.argtypes = (c_void_p,) + + # queue frames that may be filled during frame capturing + captureFrameQueue = _vimbaDLL.VmbCaptureFrameQueue + captureFrameQueue.restype = c_int32 + captureFrameQueue.argtypes = (c_void_p, + POINTER(structs.VimbaFrame), + c_void_p) # callback + + # wait for a queued frame to be filled (or dequeued) + captureFrameWait = _vimbaDLL.VmbCaptureFrameWait + captureFrameWait.restype = c_int32 + captureFrameWait.argtypes = (c_void_p, # camera handle + POINTER(structs.VimbaFrame), + c_uint32) # timeout + + # flush the capture queue + captureQueueFlush = _vimbaDLL.VmbCaptureQueueFlush + captureQueueFlush.restype = c_int32 + # camera handle + captureQueueFlush.argtypes = (c_void_p,) + + # list interfaces + interfacesList = _vimbaDLL.VmbInterfacesList + interfacesList.restype = c_int32 + interfacesList.argtypes = (POINTER(structs.VimbaInterfaceInfo), # pointer to interface info structure + # length of list + c_uint32, + # pointer to number of interfaces + POINTER(c_uint32), + c_uint32) + + # open interface + interfaceOpen = _vimbaDLL.VmbInterfaceOpen + interfaceOpen.restype = c_int32 + interfaceOpen.argtypes = (c_char_p, # unique id + c_void_p) # handle + + # close interface + interfaceClose = _vimbaDLL.VmbInterfaceClose + interfaceClose.restype = c_int32 + interfaceClose.argtypes = (c_void_p,) # handle + + # read from register + registersRead = _vimbaDLL.VmbRegistersRead + registersRead.restype = c_int32 + registersRead.argtypes = (c_void_p, # handle + # read count + c_uint32, + # pointer to address array + POINTER(c_uint64), + # pointer to data array + POINTER(c_uint64), + POINTER(c_uint32)) # pointer to num complete reads + + # write to register + registersWrite = _vimbaDLL.VmbRegistersWrite + registersWrite.restype = c_int32 + registersWrite.argtypes = (c_void_p, # handle + # write count + c_uint32, + # pointer to address array + POINTER(c_uint64), + # pointer to data array + POINTER(c_uint64), + POINTER(c_uint32)) # pointer to num complete write + + +class VimbaC_MemoryBlock(object): + + """ + Just a memory block object for dealing + neatly with C memory allocations. + """ + + @property + def block(self): + return c_void_p(addressof(self._block)) + + def __init__(self, blockSize): + self._block = create_string_buffer(blockSize) + + # this seems to be None if too much memory is requested + if self._block is None: + raise VimbaException(-51) + + def __del__(self): + del self._block diff --git a/pymba/vimba_exception.py b/pymba/vimba_exception.py new file mode 100644 index 0000000..6269543 --- /dev/null +++ b/pymba/vimba_exception.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + + +class VimbaException(Exception): + + """ + An exception for the AVT Vimba API. It contains a message + property which is a string indicating what went wrong. + + :param errorCode: Error code to be used to look up error message. + """ + + @property + def message(self): + return self._errorCodes[self.errorCode] + + @property + def errorCode(self): + return self._errorCode + + _errorCodes = { # Vimba C API specific errors + 0: 'No error.', + -1: 'Unexpected fault in VimbaC or driver.', + -2: 'VmbStartup() was not called before the current command.', + -3: 'The designated instance (camera, feature etc.) cannot be found.', + -4: 'The given handle is not valid, ensure device open.', + -5: 'Device was not opened for usage.', + -6: 'Operation is invalid with the current access mode.', + -7: 'One of the parameters was invalid (usually an illegal pointer).', + -8: 'The given struct size is not valid for this version of the API.', + -9: 'More data was returned in a string/list than space was provided.', + -10: 'The feature type for this access function was wrong.', + -11: 'The value was not valid; either out of bounds or not an increment of the minimum.', + -12: 'Timeout during wait.', + -13: 'Other error.', + -14: 'Resources not available (e.g. memory).', + -15: 'Call is invalid in the current context (e.g. callback).', + -16: 'No transport layers were found.', + -17: 'API feature is not implemented.', + -18: 'API feature is not supported.', + -19: 'A multiple registers read or write was partially completed.', + + # Custom errors + -50: 'Could not find the specified camera.', + -51: 'Not enough memory to assign frame buffer.', + -52: 'Invalid input.', + -53: 'Could not find the specified feature.', + -54: 'Could not find the specified interface.', + + # Miscellaneous errors + -1000: 'Oops, unknown internal error code!', + -1001: 'Oops, this VimbaFeature function is not yet implemented in pymba!'} + + def __init__(self, errorCode): + # if error code does not match expected codes then assign invalid code + if errorCode in self._errorCodes: + self._errorCode = errorCode + else: + self._errorCode = -1000 + + super(VimbaException, self).__init__(self.message) diff --git a/pymba/vimba_feature.py b/pymba/vimba_feature.py new file mode 100644 index 0000000..16c4169 --- /dev/null +++ b/pymba/vimba_feature.py @@ -0,0 +1,341 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from . import vimba_structure as structs +from .vimba_exception import VimbaException +from .vimba_dll import VimbaDLL +from ctypes import * + +# class may extend a generic Vimba entity class one day... + + +class VimbaFeature(object): + + """ + A feature of a Vimba object. + """ + + @property + def name(self): + return self._name.decode() + + @property + def handle(self): + return self._handle + + # lookup relevant function for feature type and pass to that function + @property + def value(self): + return self._getSetTypeFuncs[self._info.featureDataType][0]() + + @value.setter + def value(self, val): + self._getSetTypeFuncs[self._info.featureDataType][1](val) + + @property + def range(self): + return self._rangeQueryTypeFuncs[self._info.featureDataType]() + + def __init__(self, name, handle): + + # set name and handle + self._name = name.encode() + self._handle = handle + + # set own info + self._info = self._getInfo() + + # type functions dict for looking up correct get/set function to use + self._getSetTypeFuncs = {0: (self._notYetImplemented, self._notYetImplemented), # todo + 1: (self._getIntFeature, self._setIntFeature), + 2: (self._getFloatFeature, self._setFloatFeature), + 3: (self._getEnumFeature, self._setEnumFeature), + 4: (self._getStringFeature, self._setStringFeature), + 5: (self._getBoolFeature, self._setBoolFeature), + # todo + 6: (self._notYetImplemented, self._notYetImplemented), + # todo + 7: (self._notYetImplemented, self._notYetImplemented), + 8: (self._notYetImplemented, self._notYetImplemented)} # todo + + # type functions dict for looking up correct range function to use + self._rangeQueryTypeFuncs = {0: self._unknownRange, + 1: self._rangeQueryIntFeature, + 2: self._rangeQueryFloatFeature, + 3: self._rangeQueryEnumFeature, + 4: self._unknownRange, + 5: self._unknownRange, + 6: self._unknownRange, + 7: self._unknownRange, + 8: self._unknownRange} + + def getInfo(self): + """ + Get info of the feature. + + :returns: VimbaFeatureInfo object -- feature information.. + """ + return self._info + + def _getInfo(self): + """ + Get info of the feature. + + :returns: VimbaFeatureInfo object -- feature information.. + """ + # args for Vimba call + featureInfo = structs.VimbaFeatureInfo() + + # Vimba DLL will return an error code + errorCode = VimbaDLL.featureInfoQuery(self._handle, + self._name, + byref(featureInfo), + sizeof(featureInfo)) + if errorCode != 0: + raise VimbaException(errorCode) + + return featureInfo + + def _notYetImplemented(self, val=None): + """ + Raises exception if feature value type is not yet defined. + """ + raise VimbaException(-1001) + + def _getIntFeature(self): + """ + Get the value of an integer feature. + + :returns: int -- value of the specified feature. + """ + + # create args + valueToGet = c_int64() + + errorCode = VimbaDLL.featureIntGet(self._handle, + self._name, + byref(valueToGet)) + if errorCode != 0: + raise VimbaException(errorCode) + + return valueToGet.value + + def _setIntFeature(self, valueToSet): + """ + Set the value of an integer feature. + + :param valueToSet: the int value to set for the feature. + """ + + errorCode = VimbaDLL.featureIntSet(self._handle, + self._name, + valueToSet) + if errorCode != 0: + raise VimbaException(errorCode) + + def _getFloatFeature(self): + """ + Get the value of a float feature. + + :returns: float -- value of the specified feature. + """ + + # create args + valueToGet = c_double() + + errorCode = VimbaDLL.featureFloatGet(self._handle, + self._name, + byref(valueToGet)) + if errorCode != 0: + raise VimbaException(errorCode) + + return valueToGet.value + + def _setFloatFeature(self, valueToSet): + """ + Set the value of a float feature. + + :param valueToSet: the float value to set for the feature. + """ + + errorCode = VimbaDLL.featureFloatSet(self._handle, + self._name, + valueToSet) + if errorCode != 0: + raise VimbaException(errorCode) + + def _getEnumFeature(self): + """ + Get the value of an enum feature. + + :returns: enum -- value of the specified feature. + """ + + # create args + valueToGet = c_char_p() + + errorCode = VimbaDLL.featureEnumGet(self._handle, + self._name, + byref(valueToGet)) + if errorCode != 0: + raise VimbaException(errorCode) + + return valueToGet.value.decode() + + def _setEnumFeature(self, valueToSet): + """ + Set the value of an enum feature. + + :param valueToSet: the enum value to set for the feature. + """ + + errorCode = VimbaDLL.featureEnumSet(self._handle, + self._name, + valueToSet.encode()) + if errorCode != 0: + raise VimbaException(errorCode) + + def _getStringFeature(self): + """ + Get the value of a string feature. + + :returns: string -- value of the specified feature. + """ + + # create args + bufferSize = 256 + valueToGet = create_string_buffer('\000' * bufferSize) + sizeFilled = c_uint32() + + errorCode = VimbaDLL.featureStringGet(self._handle, + self._name, + valueToGet, + bufferSize, + byref(sizeFilled)) + if errorCode != 0: + raise VimbaException(errorCode) + return valueToGet.value.decode() + + def _setStringFeature(self, valueToSet): + """ + Set the value of a string feature. + + :param valueToSet: the string value to set for the feature. + """ + + errorCode = VimbaDLL.featureStringSet(self._handle, + self._name, + valueToSet.encode()) + if errorCode != 0: + raise VimbaException(errorCode) + + def _getBoolFeature(self): + """ + Get the value of a bool feature. + + :returns: bool -- value of the specified feature. + """ + + # create args + valueToGet = c_bool() + + errorCode = VimbaDLL.featureBoolGet(self._handle, + self._name, + byref(valueToGet)) + if errorCode != 0: + raise VimbaException(errorCode) + + return valueToGet.value + + def _setBoolFeature(self, valueToSet): + """ + Set the value of a bool feature. + + :param valueToSet: the bool value to set for the feature. + """ + + errorCode = VimbaDLL.featureBoolSet(self._handle, + self._name, + valueToSet) + if errorCode != 0: + raise VimbaException(errorCode) + + def _unknownRange(self): + """ + Returns empty for ranges that have not been implemented. + """ + return '' + + def _rangeQueryIntFeature(self): + """ + Get the range of an int feature. + + :returns: tuple -- min and max range. + """ + + # create args + minToGet = c_int64() + maxToGet = c_int64() + + errorCode = VimbaDLL.featureIntRangeQuery(self._handle, + self._name, + byref(minToGet), + byref(maxToGet)) + if errorCode != 0: + raise VimbaException(errorCode) + + return (int(str(minToGet.value)), int(str(maxToGet.value))) + + def _rangeQueryFloatFeature(self): + """ + Get the range of a float feature. + + :returns: tuple -- min and max range. + """ + + # create args + minToGet = c_double() + maxToGet = c_double() + + errorCode = VimbaDLL.featureFloatRangeQuery(self._handle, + self._name, + byref(minToGet), + byref(maxToGet)) + if errorCode != 0: + raise VimbaException(errorCode) + + return (minToGet.value, maxToGet.value) + + def _rangeQueryEnumFeature(self): + """ + Get the range of an enum feature. + :returns: list -- enum names for the given feature. + """ + + # call once to get number of available enum names + # Vimba DLL will return an error code + numFound = c_uint32(-1) + errorCode = VimbaDLL.featureEnumRangeQuery(self._handle, + self._name, + None, + 0, + byref(numFound)) + if errorCode != 0: + raise VimbaException(errorCode) + + # number of names specified by Vimba + numEnumNames = numFound.value + + # args + enumNamesArray = (c_char_p * numEnumNames)() + + # call again to get the enum names + # Vimba DLL will return an error code + errorCode = VimbaDLL.featureEnumRangeQuery(self._handle, + self._name, + enumNamesArray, + numEnumNames, + byref(numFound)) + if errorCode != 0: + raise VimbaException(errorCode) + + return list(enumName.decode() for enumName in enumNamesArray) diff --git a/pymba/vimba_frame.py b/pymba/vimba_frame.py new file mode 100644 index 0000000..fd37aed --- /dev/null +++ b/pymba/vimba_frame.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from . import vimba_structure as structs +from .vimba_exception import VimbaException +from .vimba_dll import VimbaDLL +from .vimba_dll import VimbaC_MemoryBlock +from ctypes import * +import warnings +try: + import numpy as np +except ImportError: + warnings.warn('numpy not found, some VimbaFrame methods will not be available') + + +""" +Map pixel formats to bytes per pixel. + The packed formats marked with "?" have not been tested. +""" +PIXEL_FORMATS = { + "Mono8": 1, + "Mono12": 2, + "Mono12Packed": 1.5, # ? + "Mono14": 2, + "Mono16": 2, + "RGB8": 3, + "RGB8Packed": 3, + "BGR8Packed": 3, + "RGBA8Packed": 4, + "BGRA8Packed": 4, + "YUV411Packed": 4/3.0, # ? + "YUV422Packed": 2, + "YUV444Packed": 3, + "BayerRG8": 1, + "BayerRG12": 2, + "BayerGR8": 1, + "BayerGR12": 2, + "BayerGR12Packed": 1.5, # ? +} + + +class VimbaFrame(object): + """ + A Vimba frame. + """ + def __init__(self, camera): + self._camera = camera + self._handle = camera.handle + + # get frame sizes + self.payloadSize = self._camera.PayloadSize + self.width = self._camera.Width + self.height = self._camera.Height + self.pixel_bytes = PIXEL_FORMATS[self._camera.PixelFormat] + + # frame structure + self._frame = structs.VimbaFrame() + + def announceFrame(self): + """ + Announce frames to the API that may be queued for frame capturing later. + + Runs VmbFrameAnnounce + + Should be called after the frame is created. Call startCapture + after this method. + """ + # size of expected frame + sizeOfFrame = self.payloadSize + + # keep this reference to keep block alive for life of frame + self._cMem = VimbaC_MemoryBlock(sizeOfFrame) + # set buffer to have length of expected payload size + self._frame.buffer = self._cMem.block + + # set buffer size to expected payload size + self._frame.bufferSize = sizeOfFrame + + errorCode = VimbaDLL.frameAnnounce(self._handle, + byref(self._frame), + sizeof(self._frame)) + + if errorCode != 0: + raise VimbaException(errorCode) + + def revokeFrame(self): + """ + Revoke a frame from the API. + """ + errorCode = VimbaDLL.frameRevoke(self._handle, + byref(self._frame)) + + if errorCode != 0: + raise VimbaException(errorCode) + + def queueFrameCapture(self, frameCallback = None): + """ + Queue frames that may be filled during frame capturing. + Runs VmbCaptureFrameQueue + + Call after announceFrame and startCapture + + Callback must accept argument of type frame. Remember to requeue the + frame by calling frame.queueFrameCapture(frameCallback) at the end of + your callback function. + """ + # remember the given callback function + self._frameCallback = frameCallback + + # define a callback wrapper here so it doesn't bind self + def frameCallbackWrapper(cam_handle, p_frame): + # call the user's callback with the self bound outside the wrapper + # ignore the frame pointer since we already know the callback + # refers to this frame + self._frameCallback(self) + + if self._frameCallback is None: + self._frameCallbackWrapper_C = None + else: + # keep a reference to prevent gc issues + self._frameCallbackWrapper_C = VimbaDLL.frameDoneCallback(frameCallbackWrapper) + + errorCode = VimbaDLL.captureFrameQueue(self._handle, + byref(self._frame), + self._frameCallbackWrapper_C) + if errorCode != 0: + raise VimbaException(errorCode) + + def waitFrameCapture(self, timeout=2000): + """ + Wait for a queued frame to be filled (or dequeued). Returns Errorcode + upon completion. + Runs VmbCaptureFrameWait + + timeout - int, milliseconds default(timeout, 2000) + + Call after an acquisition command + """ + errorCode = VimbaDLL.captureFrameWait(self._handle, + byref(self._frame), + timeout) + + # errorCode to be processed by the end user for this function. + # Prevents system for breaking for example on a hardware trigger + # timeout + #if errorCode != 0: + #raise VimbaException(errorCode) + return errorCode + + # custom method for simplified usage + def getBufferByteData(self): + """ + Retrieve buffer data in a useful format. + + :returns: array -- buffer data. + """ + + # cast frame buffer memory contents to a usable type + data = cast(self._frame.buffer, + POINTER(c_ubyte * self.payloadSize)) + + # make array of c_ubytes from buffer + array = (c_ubyte * int(self.height*self.pixel_bytes) * + int(self.width*self.pixel_bytes)).from_address(addressof( + data.contents)) + + return array + + def getImage(self): + cframe = self._frame + data = cast(cframe.buffer, POINTER(c_ubyte * cframe.imageSize)) + try: + return np.ndarray(buffer=data.contents, dtype=np.uint8, shape=(cframe.height, cframe.width)) + except NameError as e: + print('install numpy to use this method or use getBufferByteData instead') + raise e diff --git a/pymba/vimba_interface.py b/pymba/vimba_interface.py new file mode 100644 index 0000000..df5acdc --- /dev/null +++ b/pymba/vimba_interface.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from . import vimba_structure as structs +from .vimba_object import VimbaObject +from .vimba_exception import VimbaException +from .vimba_dll import VimbaDLL +from ctypes import * + +# interface features are automatically readable as object attributes. + + +class VimbaInterface(VimbaObject): + + """ + A Vimba interface object. This class provides the minimal access + to Vimba functions required to control the interface. + """ + + @property + def interfaceIdString(self): + return self._interfaceIdString + + # own handle is inherited as self._handle + def __init__(self, interfaceIdString): + + # call super constructor + super(VimbaInterface, self).__init__() + + # set ID + self._interfaceIdString = interfaceIdString + + def openInterface(self): + """ + Open the interface. + """ + errorCode = VimbaDLL.interfaceOpen(self._interfaceIdString, + byref(self._handle)) + if errorCode != 0: + raise VimbaException(errorCode) + + def closeInterface(self): + """ + Close the interface. + """ + errorCode = VimbaDLL.interfaceClose(self._handle) + if errorCode != 0: + raise VimbaException(errorCode) diff --git a/pymba/vimba_object.py b/pymba/vimba_object.py new file mode 100644 index 0000000..f75aa75 --- /dev/null +++ b/pymba/vimba_object.py @@ -0,0 +1,232 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from . import vimba_structure as structs +from .vimba_exception import VimbaException +from .vimba_feature import VimbaFeature +from .vimba_dll import VimbaDLL +from ctypes import * + + +class VimbaObject(object): + + """ + A Vimba object has a handle and features associated with it. + Objects include System, Camera, Interface and AncillaryData. + """ + + @property + def handle(self): + return self._handle + + def __init__(self): + # create own handle + self._handle = c_void_p() + + # list of VimbaFeatureInfo objects + # can't set yet as the object (e.g. a camera) won't be + # opened yet, therefore no event for object opening + # so will have it populate by user interaction + # and blame them if the object is not opened then + self._featureInfos = None + + # override getattr for undefined attributes + def __getattr__(self, attr): + + # if a feature value requested (requires object (camera) open) + if attr in self.getFeatureNames(): + return VimbaFeature(attr, self._handle).value + + # otherwise don't know about it + raise AttributeError(''.join(["'VimbaObject' has no attribute '", + attr, + "'"])) + + # override setattr for undefined attributes + def __setattr__(self, attr, val): + + # set privates as normal + # check this first to allow all privates to set normally + # and avoid recursion errors + if attr.startswith('_'): + super(VimbaObject, self).__setattr__(attr, val) + + # if it's an actual camera feature (requires camera open) + elif attr in self.getFeatureNames(): + VimbaFeature(attr, self._handle).value = val + + # otherwise just set the attribute value as normal + else: + super(VimbaObject, self).__setattr__(attr, val) + + def _getFeatureInfos(self): + """ + Gets feature info of all available features. Will + cause error if object/camera is not opened. + + :returns: list -- feature info for available features. + """ + # check it's populated as can't populate it in __init__ + if self._featureInfos is None: + # args + dummyFeatureInfo = structs.VimbaFeatureInfo() + numFound = c_uint32(-1) + + # call once to get number of available features + # Vimba DLL will return an error code + errorCode = VimbaDLL.featuresList(self._handle, + None, + 0, + byref(numFound), + sizeof(dummyFeatureInfo)) + if errorCode != 0: + raise VimbaException(errorCode) + + # number of features specified by Vimba + numFeatures = numFound.value + + # args + featureInfoArray = (structs.VimbaFeatureInfo * numFeatures)() + + # call again to get the features + # Vimba DLL will return an error code + errorCode = VimbaDLL.featuresList(self._handle, + featureInfoArray, + numFeatures, + byref(numFound), + sizeof(dummyFeatureInfo)) + if errorCode != 0: + raise VimbaException(errorCode) + + self._featureInfos = list( + featInfo for featInfo in featureInfoArray) + return self._featureInfos + + def getFeatureNames(self): + """ + Get names of all available features. + + :returns: list -- feature names for available features. + """ + return list(featInfo.name.decode() for featInfo in self._getFeatureInfos()) + + def getFeatureInfo(self, featureName): + """ + Gets feature info object of specified feature. + + :param featureName: the name of the feature. + + :returns: VimbaFeatureInfo object -- the feature info object specified. + """ + # don't do this live as we already have this info + # return info object, if it exists + for featInfo in self._getFeatureInfos(): + if featInfo.name.decode() == featureName: + return featInfo + # otherwise raise error + raise VimbaException(-53) + + # don't think we ever need to return a feature object... + # def getFeature(self, featureName): + + def getFeatureRange(self, featureName): + """ + Get valid range of feature values. + + :param featureName: name of the feature to query. + + :returns: tuple -- range as (feature min value, feature max value, for int or float features only). + list -- names of possible enum values (for enum features only). + """ + # can't cache this, need to look it up live + return VimbaFeature(featureName.encode(), self._handle).range + + def runFeatureCommand(self, featureName): + """ + Run a feature command. + + :param featureName: the name of the feature. + """ + # run a command + errorCode = VimbaDLL.featureCommandRun(self._handle, + featureName.encode()) + if errorCode != 0: + raise VimbaException(errorCode) + + def featureCommandIsDone(self, featureName): + isDone = c_bool() + errorCode = VimbaDLL.featureCommandIsDone(self._handle, + featureName.encode(), + byref(isDone)) + + if errorCode != 0: + raise VimbaException(errorCode) + + return isDone.value + + + def readRegister(self, address): + # note that the underlying Vimba function allows reading of an array + # of registers, but only one address/value at a time is implemented + # here + """ + Read from a register of the module (camera). + + :param address: the address of the register to read. + + :returns: int -- value of register. + """ + readCount = 1 + + # check address validity + try: + regAddress = c_uint64(int(address, 16)) + except: + raise VimbaException(-52) + + regData = c_uint64() + numCompleteReads = c_uint32() + + errorCode = VimbaDLL.registersRead(self.handle, + readCount, + byref(regAddress), + byref(regData), + byref(numCompleteReads)) + + if errorCode != 0: + raise VimbaException(errorCode) + + return regData.value + + def writeRegister(self, address, value): + # note that the underlying Vimba function allows writing of an array + # of registers, but only one address/value at a time is implemented + # here + """ + Read from a register of the module (camera). + + :param address: the address of the register to read. + :param value: the value to set in hex. + """ + writeCount = 1 + + # check address validity + try: + regAddress = c_uint64(int(address, 16)) + except: + raise VimbaException(-52) + + # check value validity + try: + regData = c_uint64(int(value, 16)) + except: + raise VimbaException(-52) + + numCompleteWrites = c_uint32() + + errorCode = VimbaDLL.registersWrite(self.handle, + writeCount, + byref(regAddress), + byref(regData), + byref(numCompleteWrites)) + if errorCode != 0: + raise VimbaException(errorCode) diff --git a/pymba/vimba_structure.py b/pymba/vimba_structure.py new file mode 100644 index 0000000..73c4e96 --- /dev/null +++ b/pymba/vimba_structure.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +from ctypes import * + + +class VimbaVersion(Structure): + _fields_ = [('major', c_uint32), + ('minor', c_uint32), + ('patch', c_uint32)] + + +class VimbaInterfaceInfo(Structure): + _fields_ = [('interfaceIdString', c_char_p), # Unique identifier for each interface + # Interface type, see VmbInterfaceType + ('interfaceType', c_uint32), + # Interface name, given by the transport layer + ('interfaceName', c_char_p), + ('serialString', c_char_p), # Serial number + ('permittedAccess', c_uint32)] # Used access mode, see VmbAccessModeType + + def getFieldNames(self): + """ + Get field names. + """ + return [field[0] for field in self._fields_] + + +class VimbaCameraInfo(Structure): + _fields_ = [('cameraIdString', c_char_p), # Unique identifier for each camera + ('cameraName', c_char_p), # Name of the camera + ('modelName', c_char_p), # Model name + ('serialString', c_char_p), # Serial number + # Used access mode, see VmbAccessModeType + ('permittedAccess', c_uint32), + ('interfaceIdString', c_char_p)] # Unique value for each interface or bus + + def getFieldNames(self): + """ + Get field names. + """ + return [field[0] for field in self._fields_] + + +class VimbaFeatureInfo(Structure): + + _fields_ = [('name', c_char_p), + ('featureDataType', c_uint32), + ('featureFlags', c_uint32), + ('category', c_char_p), + ('displayName', c_char_p), + ('pollingTime', c_uint32), + ('unit', c_char_p), + ('representation', c_char_p), + ('visibility', c_uint32), + ('tooltip', c_char_p), + ('description', c_char_p), + ('sfncNamespace', c_char_p), + ('isStreamable', c_bool), + ('hasAffectedFeatures', c_bool), + ('hasSelectedFeatures', c_bool)] + + def getFieldNames(self): + """ + Get field names. + """ + return [field[0] for field in self._fields_] + + +class VimbaFrame(Structure): + + # IN + _fields_ = [('buffer', c_void_p), # Comprises image and ancillary data + ('bufferSize', c_uint32), # Size of the data buffer + + # User context filled during queuing + ('context', c_void_p * 4), + + # OUT + # Resulting status of the receive operation + ('receiveStatus', c_int32), + # Resulting flags of the receive operation + ('receiveFlags', c_uint32), + + # Size of the image data inside the data buffer + ('imageSize', c_uint32), + # Size of the ancillary data inside the data buffer + ('ancillarySize', c_uint32), + + # Pixel format of the image + ('pixelFormat', c_uint32), + + ('width', c_uint32), # Width of an image + ('height', c_uint32), # Height of an image + # Horizontal offset of an image + ('offsetX', c_uint32), + # Vertical offset of an image + ('offsetY', c_uint32), + + # Unique ID of this frame in this stream + ('frameID', c_uint64), + ('timestamp', c_uint64)] # Timestamp of the data transfer + + def getFieldNames(self): + """ + Get field names. + """ + return [field[0] for field in self._fields_] diff --git a/pymba/vimba_system.py b/pymba/vimba_system.py new file mode 100644 index 0000000..f4d0c54 --- /dev/null +++ b/pymba/vimba_system.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import +from .vimba_object import VimbaObject +from ctypes import c_void_p + +# system features are automatically readable as attributes. + + +class VimbaSystem(VimbaObject): + + """ + A Vimba system object. This class provides the minimal access + to Vimba functions required to control the system. + """ + + # own handle is inherited as self._handle + + def __init__(self): + super(VimbaSystem, self).__init__() + + # set own handle manually + self._handle = c_void_p(1) diff --git a/pymba/vimbacamera.py b/pymba/vimbacamera.py deleted file mode 100644 index 0a96a71..0000000 --- a/pymba/vimbacamera.py +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimbastructure as structs -from .vimbaobject import VimbaObject -from .vimbaexception import VimbaException -from .vimbaframe import VimbaFrame -from .vimbadll import VimbaDLL -from ctypes import * - -# camera features are automatically readable as object attributes. - - -class VimbaCamera(VimbaObject): - - """ - A Vimba camera object. This class provides the minimal access - to Vimba functions required to control the camera. - """ - - @property - def cameraIdString(self): - return self._cameraIdString.decode() - - # own handle is inherited as self._handle - def __init__(self, cameraIdString): - - # call super constructor - super(VimbaCamera, self).__init__() - - # set ID - self._cameraIdString = cameraIdString.encode() - - # set own info - self._info = self._getInfo() - - def getInfo(self): - """ - Get info of the camera. Does not require - the camera to be opened. - - :returns: VimbaCameraInfo object -- camera information. - """ - return self._info - - def _getInfo(self): - """ - Get info of the camera. Does not require - the camera to be opened. - - :returns: VimbaCameraInfo object -- camera information. - """ - # args for Vimba call - cameraInfo = structs.VimbaCameraInfo() - - # Vimba DLL will return an error code - errorCode = VimbaDLL.cameraInfoQuery(self._cameraIdString, - byref(cameraInfo), - sizeof(cameraInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - - return cameraInfo - - def openCamera(self, cameraAccessMode=1): - """ - Open the camera with requested access mode - Available access modes: - 0 : VmbAccessModeNone - 1 : VmbAccessModeFull - 2 : VmbAccessModeRead - 3 : VmbAccessModeConfig - 4 : VmbAccessModeLite - """ - # args for Vimba call - errorCode = VimbaDLL.cameraOpen(self._cameraIdString, - cameraAccessMode, - byref(self._handle)) - if errorCode != 0: - raise VimbaException(errorCode) - - def closeCamera(self): - """ - Close the camera. - """ - errorCode = VimbaDLL.cameraClose(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) - - def revokeAllFrames(self): - """ - Revoke all frames assigned to the camera. - """ - errorCode = VimbaDLL.frameRevokeAll(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) - - def startCapture(self): - """ - Prepare the API for incoming frames. - """ - errorCode = VimbaDLL.captureStart(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) - - def endCapture(self): - """ - Stop the API from being able to receive frames. - """ - errorCode = VimbaDLL.captureEnd(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) - - def flushCaptureQueue(self): - """ - Flush the capture queue. - """ - errorCode = VimbaDLL.captureQueueFlush(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) - - # method for easy frame creation - def getFrame(self): - """ - Creates and returns a new frame object. Multiple frames - per camera can therefore be returned. - - :returns: VimbaFrame object -- the new frame. - """ - return VimbaFrame(self) diff --git a/pymba/vimbadll.py b/pymba/vimbadll.py deleted file mode 100644 index a6b9f3c..0000000 --- a/pymba/vimbadll.py +++ /dev/null @@ -1,489 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import - -from sys import platform as sys_plat -import platform -import os -from ctypes import * - -from . import vimbastructure as structs -from .vimbaexception import VimbaException - -if sys_plat == "win32": - - def find_win_dll(arch): - """ Finds the highest versioned windows dll for the specified architecture. """ - bases = [ - r'C:\Program Files\Allied Vision Technologies\AVTVimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll', - r'C:\Program Files\Allied Vision\Vimba_%i.%i\VimbaC\Bin\Win%i\VimbaC.dll' - ] - dlls = [] - for base in bases: - for major in range(3): - for minor in range(10): - candidate = base % (major, minor, arch) - if os.path.isfile(candidate): - dlls.append(candidate) - if not dlls: - if 'VIMBA_HOME' in os.environ: - candidate = os.environ ['VIMBA_HOME'] + '\VimbaC\Bin\Win%i\VimbaC.dll' % (arch) - if os.path.isfile(candidate): - dlls.append(candidate) - if not dlls: - raise IOError("VimbaC.dll not found.") - return dlls[-1] - - if '64' in platform.architecture()[0]: - vimbaC_path = find_win_dll(64) - else: - vimbaC_path = find_win_dll(32) - dll_loader = windll -else: - - dll_loader = cdll - - if 'x86_64' in os.uname()[4]: - assert os.environ.get( - "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_64bit/libVimbaC.so" - elif 'x86_32' in os.uname()[4]: - print("Warning: x86_32 reached!") - assert os.environ.get( - "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/x86_32bit/libVimbaC.so" - elif 'arm' in os.uname()[4]: - assert os.environ.get( - "GENICAM_GENTL32_PATH"), "you need your GENICAM_GENTL32_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL32_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_32bit/libVimbaC.so" - elif 'aarch64' in os.uname()[4]: - assert os.environ.get( - "GENICAM_GENTL64_PATH"), "you need your GENICAM_GENTL64_PATH environment set. Make sure you have Vimba installed, and you have loaded the /etc/profile.d/ scripts" - tlPath = [p for p in os.environ.get("GENICAM_GENTL64_PATH").split(":") if p][0] - vimba_dir = "/".join(tlPath.split("/")[1:-3]) - vimbaC_path = "/" + vimba_dir + "/VimbaC/DynamicLib/arm_64bit/libVimbaC.so" - else: - raise ValueError("Pymba currently doesn't support %s" % os.uname()[4]) - - -# Callback Function Type -if sys_plat == "win32": - CB_FUNCTYPE = WINFUNCTYPE -else: - # Untested! - CB_FUNCTYPE = CFUNCTYPE - - -class VimbaDLL(object): - - """ - ctypes directives to make the wrapper class work cleanly, - talks to VimbaC.dll - """ - # a full list of Vimba API methods - # (only double dashed methods have been implemented so far) - # - # -- VmbVersionQuery() - # - # -- VmbStartup() - # -- VmbShutdown() - # - # -- VmbCamerasList() - # -- VmbCameraInfoQuery() - # -- VmbCameraOpen() - # -- VmbCameraClose() - # - # -- VmbFeaturesList() - # -- VmbFeatureInfoQuery() - # VmbFeatureListAffected() - # VmbFeatureListSelected() - # VmbFeatureAccessQuery() - # - # -- VmbFeatureIntGet() - # -- VmbFeatureIntSet() - # -- VmbFeatureIntRangeQuery() - # VmbFeatureIntIncrementQuery() - # - # -- VmbFeatureFloatGet() - # -- VmbFeatureFloatSet() - # -- VmbFeatureFloatRangeQuery() - # - # -- VmbFeatureEnumGet() - # -- VmbFeatureEnumSet() - # -- VmbFeatureEnumRangeQuery() - # VmbFeatureEnumIsAvailable() - # VmbFeatureEnumAsInt() - # VmbFeatureEnumAsString() - # VmbFeatureEnumEntryGet() - # - # -- VmbFeatureStringGet() - # -- VmbFeatureStringSet() - # VmbFeatureStringMaxlengthQuery() - # - # -- VmbFeatureBoolGet() - # -- VmbFeatureBoolSet() - # - # -- VmbFeatureCommandRun() - # VmbFeatureCommandIsDone() - # - # VmbFeatureRawGet() - # VmbFeatureRawSet() - # VmbFeatureRawLengthQuery() - # - # VmbFeatureInvalidationRegister() - # VmbFeatureInvalidationUnregister() - # - # -- VmbFrameAnnounce() - # -- VmbFrameRevoke() - # -- VmbFrameRevokeAll() - # -- VmbCaptureStart() - # -- VmbCaptureEnd() - # -- VmbCaptureFrameQueue() - # -- VmbCaptureFrameWait() - # -- VmbCaptureQueueFlush() - # - # -- VmbInterfacesList() - # -- VmbInterfaceOpen() - # -- VmbInterfaceClose() - # - # VmbAncillaryDataOpen() - # VmbAncillaryDataClose() - # - # VmbMemoryRead() - # VmbMemoryWrite() - # -- VmbRegistersRead() - # -- VmbRegistersWrite() - - # Vimba C API DLL - _vimbaDLL = dll_loader.LoadLibrary(vimbaC_path) - - # version query - versionQuery = _vimbaDLL.VmbVersionQuery - # returned error code - versionQuery.restype = c_int32 - versionQuery.argtypes = (POINTER(structs.VimbaVersion), # pointer to version structure - c_uint32) # version structure size - - # startup - startup = _vimbaDLL.VmbStartup - # returned error code - startup.restype = c_int32 - - # shutdown - shutdown = _vimbaDLL.VmbShutdown - - # list cameras - camerasList = _vimbaDLL.VmbCamerasList - # returned error code - camerasList.restype = c_int32 - camerasList.argtypes = (POINTER(structs.VimbaCameraInfo), # pointer to camera info structure - # length of list - c_uint32, - # pointer to number of cameras - POINTER(c_uint32), - c_uint32) # camera info structure size - - # camera info query - cameraInfoQuery = _vimbaDLL.VmbCameraInfoQuery - cameraInfoQuery.restype = c_int32 - cameraInfoQuery.argtypes = (c_char_p, # camera unique id - # pointer to camera info structure - POINTER(structs.VimbaCameraInfo), - c_uint32) # size of structure - - # camera open - cameraOpen = _vimbaDLL.VmbCameraOpen - # returned error code - cameraOpen.restype = c_int32 - cameraOpen.argtypes = (c_char_p, # camera unique id - # access mode - c_uint32, - c_void_p) # camera handle, pointer to a pointer - - # camera close - cameraClose = _vimbaDLL.VmbCameraClose - # returned error code - cameraClose.restype = c_int32 - # camera handle - cameraClose.argtypes = (c_void_p,) - - # list features - featuresList = _vimbaDLL.VmbFeaturesList - featuresList.restype = c_int32 - featuresList.argtypes = (c_void_p, # handle, in this case camera handle - # pointer to feature info structure - POINTER(structs.VimbaFeatureInfo), - # list length - c_uint32, - # pointer to num features found - POINTER(c_uint32), - c_uint32) # feature info size - - # feature info query - featureInfoQuery = _vimbaDLL.VmbFeatureInfoQuery - featureInfoQuery.restype = c_int32 - featureInfoQuery.argtypes = (c_void_p, # handle, in this case camera handle - # name of feature - c_char_p, - # pointer to feature info structure - POINTER(structs.VimbaFeatureInfo), - c_uint32) # size of structure - - # get the int value of a feature - featureIntGet = _vimbaDLL.VmbFeatureIntGet - featureIntGet.restype = c_int32 - featureIntGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_int64)) # value to get - - # set the int value of a feature - featureIntSet = _vimbaDLL.VmbFeatureIntSet - featureIntSet.restype = c_int32 - featureIntSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_int64) # value to set # get the value of an integer feature - - # query the range of values of the feature - featureIntRangeQuery = _vimbaDLL.VmbFeatureIntRangeQuery - featureIntRangeQuery.restype = c_int32 - featureIntRangeQuery.argtypes = (c_void_p, # handle - # name of the feature - c_char_p, - # min range - POINTER(c_int64), - POINTER(c_int64)) # max range - - # get the float value of a feature - featureFloatGet = _vimbaDLL.VmbFeatureFloatGet - featureFloatGet.restype = c_int32 - featureFloatGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_double)) # value to get - - # set the float value of a feature - featureFloatSet = _vimbaDLL.VmbFeatureFloatSet - featureFloatSet.restype = c_int32 - featureFloatSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_double) # value to set - - # query the range of values of the feature - featureFloatRangeQuery = _vimbaDLL.VmbFeatureFloatRangeQuery - featureFloatRangeQuery.restype = c_int32 - featureFloatRangeQuery.argtypes = (c_void_p, # handle - # name of the feature - c_char_p, - # min range - POINTER(c_double), - POINTER(c_double)) # max range - - # get the enum value of a feature - featureEnumGet = _vimbaDLL.VmbFeatureEnumGet - featureEnumGet.restype = c_int32 - featureEnumGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_char_p)) # value to get - - # set the enum value of a feature - featureEnumSet = _vimbaDLL.VmbFeatureEnumSet - featureEnumSet.restype = c_int32 - featureEnumSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_char_p) # value to set - - # query the range of values of the feature - featureEnumRangeQuery = _vimbaDLL.VmbFeatureEnumRangeQuery - featureEnumRangeQuery.restype = c_int32 - featureEnumRangeQuery.argtypes = (c_void_p, # handle - # name of the feature - c_char_p, - # pointer to enum names (array) - POINTER(c_char_p), - # array length - c_uint32, - # pointer to num enum names found - POINTER(c_uint32)) - - # get the string value of a feature - featureStringGet = _vimbaDLL.VmbFeatureStringGet - featureStringGet.restype = c_int32 - featureStringGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - # string buffer to fill - c_char_p, - # size of the input buffer - c_uint32, - POINTER(c_uint32)) # string buffer to fill - - # set the string value of a feature - featureStringSet = _vimbaDLL.VmbFeatureStringSet - featureStringSet.restype = c_int32 - featureStringSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_char_p) # value to set - - # get the boolean value of a feature - featureBoolGet = _vimbaDLL.VmbFeatureBoolGet - featureBoolGet.restype = c_int32 - featureBoolGet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - POINTER(c_bool)) # value to get - - # set the boolean value of a feature - featureBoolSet = _vimbaDLL.VmbFeatureBoolSet - featureBoolSet.restype = c_int32 - featureBoolSet.argtypes = (c_void_p, # handle, in this case camera handle - # name of the feature - c_char_p, - c_bool) # value to set - - # run a feature command - featureCommandRun = _vimbaDLL.VmbFeatureCommandRun - featureCommandRun.restype = c_int32 - featureCommandRun.argtypes = (c_void_p, # handle for a module that exposes features - c_char_p) # name of the command feature - - # Check if a feature command is done - featureCommandIsDone = _vimbaDLL.VmbFeatureCommandIsDone - featureCommandIsDone.restype = c_int32 - featureCommandIsDone.argtypes = (c_void_p, # handle - c_char_p, # name of the command feature - POINTER(c_bool)) # pointer to a result bool - - # announce frames to the API that may be queued for frame capturing later - frameAnnounce = _vimbaDLL.VmbFrameAnnounce - frameAnnounce.restype = c_int32 - frameAnnounce.argtypes = (c_void_p, # camera handle - # pointer to frame - POINTER(structs.VimbaFrame), - c_uint32) # size of frame - - # callback for frame queue - frameDoneCallback = CB_FUNCTYPE(c_void_p, # Return Type - c_void_p, # Camera Hanlde - POINTER(structs.VimbaFrame)) # Pointer to frame - - # revoke a frame from the API - frameRevoke = _vimbaDLL.VmbFrameRevoke - frameRevoke.restype = c_int32 - frameRevoke.argtypes = (c_void_p, # camera handle - POINTER(structs.VimbaFrame)) # pointer to frame - - # revoke all frames assigned to a certain camera - frameRevokeAll = _vimbaDLL.VmbFrameRevokeAll - frameRevokeAll.restype = c_int32 - # camera handle - frameRevokeAll.argtypes = (c_void_p,) - - # prepare the API for incoming frames - captureStart = _vimbaDLL.VmbCaptureStart - captureStart.restype = c_int32 - # camera handle - captureStart.argtypes = (c_void_p,) - - # stop the API from being able to receive frames - captureEnd = _vimbaDLL.VmbCaptureEnd - captureEnd.restype = c_int32 - # camera handle - captureEnd.argtypes = (c_void_p,) - - # queue frames that may be filled during frame capturing - captureFrameQueue = _vimbaDLL.VmbCaptureFrameQueue - captureFrameQueue.restype = c_int32 - captureFrameQueue.argtypes = (c_void_p, - POINTER(structs.VimbaFrame), - c_void_p) # callback - - # wait for a queued frame to be filled (or dequeued) - captureFrameWait = _vimbaDLL.VmbCaptureFrameWait - captureFrameWait.restype = c_int32 - captureFrameWait.argtypes = (c_void_p, # camera handle - POINTER(structs.VimbaFrame), - c_uint32) # timeout - - # flush the capture queue - captureQueueFlush = _vimbaDLL.VmbCaptureQueueFlush - captureQueueFlush.restype = c_int32 - # camera handle - captureQueueFlush.argtypes = (c_void_p,) - - # list interfaces - interfacesList = _vimbaDLL.VmbInterfacesList - interfacesList.restype = c_int32 - interfacesList.argtypes = (POINTER(structs.VimbaInterfaceInfo), # pointer to interface info structure - # length of list - c_uint32, - # pointer to number of interfaces - POINTER(c_uint32), - c_uint32) - - # open interface - interfaceOpen = _vimbaDLL.VmbInterfaceOpen - interfaceOpen.restype = c_int32 - interfaceOpen.argtypes = (c_char_p, # unique id - c_void_p) # handle - - # close interface - interfaceClose = _vimbaDLL.VmbInterfaceClose - interfaceClose.restype = c_int32 - interfaceClose.argtypes = (c_void_p,) # handle - - # read from register - registersRead = _vimbaDLL.VmbRegistersRead - registersRead.restype = c_int32 - registersRead.argtypes = (c_void_p, # handle - # read count - c_uint32, - # pointer to address array - POINTER(c_uint64), - # pointer to data array - POINTER(c_uint64), - POINTER(c_uint32)) # pointer to num complete reads - - # write to register - registersWrite = _vimbaDLL.VmbRegistersWrite - registersWrite.restype = c_int32 - registersWrite.argtypes = (c_void_p, # handle - # write count - c_uint32, - # pointer to address array - POINTER(c_uint64), - # pointer to data array - POINTER(c_uint64), - POINTER(c_uint32)) # pointer to num complete write - - -class VimbaC_MemoryBlock(object): - - """ - Just a memory block object for dealing - neatly with C memory allocations. - """ - - @property - def block(self): - return c_void_p(addressof(self._block)) - - def __init__(self, blockSize): - self._block = create_string_buffer(blockSize) - - # this seems to be None if too much memory is requested - if self._block is None: - raise VimbaException(-51) - - def __del__(self): - del self._block diff --git a/pymba/vimbaexception.py b/pymba/vimbaexception.py deleted file mode 100644 index 6269543..0000000 --- a/pymba/vimbaexception.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- - - -class VimbaException(Exception): - - """ - An exception for the AVT Vimba API. It contains a message - property which is a string indicating what went wrong. - - :param errorCode: Error code to be used to look up error message. - """ - - @property - def message(self): - return self._errorCodes[self.errorCode] - - @property - def errorCode(self): - return self._errorCode - - _errorCodes = { # Vimba C API specific errors - 0: 'No error.', - -1: 'Unexpected fault in VimbaC or driver.', - -2: 'VmbStartup() was not called before the current command.', - -3: 'The designated instance (camera, feature etc.) cannot be found.', - -4: 'The given handle is not valid, ensure device open.', - -5: 'Device was not opened for usage.', - -6: 'Operation is invalid with the current access mode.', - -7: 'One of the parameters was invalid (usually an illegal pointer).', - -8: 'The given struct size is not valid for this version of the API.', - -9: 'More data was returned in a string/list than space was provided.', - -10: 'The feature type for this access function was wrong.', - -11: 'The value was not valid; either out of bounds or not an increment of the minimum.', - -12: 'Timeout during wait.', - -13: 'Other error.', - -14: 'Resources not available (e.g. memory).', - -15: 'Call is invalid in the current context (e.g. callback).', - -16: 'No transport layers were found.', - -17: 'API feature is not implemented.', - -18: 'API feature is not supported.', - -19: 'A multiple registers read or write was partially completed.', - - # Custom errors - -50: 'Could not find the specified camera.', - -51: 'Not enough memory to assign frame buffer.', - -52: 'Invalid input.', - -53: 'Could not find the specified feature.', - -54: 'Could not find the specified interface.', - - # Miscellaneous errors - -1000: 'Oops, unknown internal error code!', - -1001: 'Oops, this VimbaFeature function is not yet implemented in pymba!'} - - def __init__(self, errorCode): - # if error code does not match expected codes then assign invalid code - if errorCode in self._errorCodes: - self._errorCode = errorCode - else: - self._errorCode = -1000 - - super(VimbaException, self).__init__(self.message) diff --git a/pymba/vimbafeature.py b/pymba/vimbafeature.py deleted file mode 100644 index 88275ce..0000000 --- a/pymba/vimbafeature.py +++ /dev/null @@ -1,341 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimbastructure as structs -from .vimbaexception import VimbaException -from .vimbadll import VimbaDLL -from ctypes import * - -# class may extend a generic Vimba entity class one day... - - -class VimbaFeature(object): - - """ - A feature of a Vimba object. - """ - - @property - def name(self): - return self._name.decode() - - @property - def handle(self): - return self._handle - - # lookup relevant function for feature type and pass to that function - @property - def value(self): - return self._getSetTypeFuncs[self._info.featureDataType][0]() - - @value.setter - def value(self, val): - self._getSetTypeFuncs[self._info.featureDataType][1](val) - - @property - def range(self): - return self._rangeQueryTypeFuncs[self._info.featureDataType]() - - def __init__(self, name, handle): - - # set name and handle - self._name = name.encode() - self._handle = handle - - # set own info - self._info = self._getInfo() - - # type functions dict for looking up correct get/set function to use - self._getSetTypeFuncs = {0: (self._notYetImplemented, self._notYetImplemented), # todo - 1: (self._getIntFeature, self._setIntFeature), - 2: (self._getFloatFeature, self._setFloatFeature), - 3: (self._getEnumFeature, self._setEnumFeature), - 4: (self._getStringFeature, self._setStringFeature), - 5: (self._getBoolFeature, self._setBoolFeature), - # todo - 6: (self._notYetImplemented, self._notYetImplemented), - # todo - 7: (self._notYetImplemented, self._notYetImplemented), - 8: (self._notYetImplemented, self._notYetImplemented)} # todo - - # type functions dict for looking up correct range function to use - self._rangeQueryTypeFuncs = {0: self._unknownRange, - 1: self._rangeQueryIntFeature, - 2: self._rangeQueryFloatFeature, - 3: self._rangeQueryEnumFeature, - 4: self._unknownRange, - 5: self._unknownRange, - 6: self._unknownRange, - 7: self._unknownRange, - 8: self._unknownRange} - - def getInfo(self): - """ - Get info of the feature. - - :returns: VimbaFeatureInfo object -- feature information.. - """ - return self._info - - def _getInfo(self): - """ - Get info of the feature. - - :returns: VimbaFeatureInfo object -- feature information.. - """ - # args for Vimba call - featureInfo = structs.VimbaFeatureInfo() - - # Vimba DLL will return an error code - errorCode = VimbaDLL.featureInfoQuery(self._handle, - self._name, - byref(featureInfo), - sizeof(featureInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - - return featureInfo - - def _notYetImplemented(self, val=None): - """ - Raises exception if feature value type is not yet defined. - """ - raise VimbaException(-1001) - - def _getIntFeature(self): - """ - Get the value of an integer feature. - - :returns: int -- value of the specified feature. - """ - - # create args - valueToGet = c_int64() - - errorCode = VimbaDLL.featureIntGet(self._handle, - self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return valueToGet.value - - def _setIntFeature(self, valueToSet): - """ - Set the value of an integer feature. - - :param valueToSet: the int value to set for the feature. - """ - - errorCode = VimbaDLL.featureIntSet(self._handle, - self._name, - valueToSet) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getFloatFeature(self): - """ - Get the value of a float feature. - - :returns: float -- value of the specified feature. - """ - - # create args - valueToGet = c_double() - - errorCode = VimbaDLL.featureFloatGet(self._handle, - self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return valueToGet.value - - def _setFloatFeature(self, valueToSet): - """ - Set the value of a float feature. - - :param valueToSet: the float value to set for the feature. - """ - - errorCode = VimbaDLL.featureFloatSet(self._handle, - self._name, - valueToSet) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getEnumFeature(self): - """ - Get the value of an enum feature. - - :returns: enum -- value of the specified feature. - """ - - # create args - valueToGet = c_char_p() - - errorCode = VimbaDLL.featureEnumGet(self._handle, - self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return valueToGet.value.decode() - - def _setEnumFeature(self, valueToSet): - """ - Set the value of an enum feature. - - :param valueToSet: the enum value to set for the feature. - """ - - errorCode = VimbaDLL.featureEnumSet(self._handle, - self._name, - valueToSet.encode()) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getStringFeature(self): - """ - Get the value of a string feature. - - :returns: string -- value of the specified feature. - """ - - # create args - bufferSize = 256 - valueToGet = create_string_buffer('\000' * bufferSize) - sizeFilled = c_uint32() - - errorCode = VimbaDLL.featureStringGet(self._handle, - self._name, - valueToGet, - bufferSize, - byref(sizeFilled)) - if errorCode != 0: - raise VimbaException(errorCode) - return valueToGet.value.decode() - - def _setStringFeature(self, valueToSet): - """ - Set the value of a string feature. - - :param valueToSet: the string value to set for the feature. - """ - - errorCode = VimbaDLL.featureStringSet(self._handle, - self._name, - valueToSet.encode()) - if errorCode != 0: - raise VimbaException(errorCode) - - def _getBoolFeature(self): - """ - Get the value of a bool feature. - - :returns: bool -- value of the specified feature. - """ - - # create args - valueToGet = c_bool() - - errorCode = VimbaDLL.featureBoolGet(self._handle, - self._name, - byref(valueToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return valueToGet.value - - def _setBoolFeature(self, valueToSet): - """ - Set the value of a bool feature. - - :param valueToSet: the bool value to set for the feature. - """ - - errorCode = VimbaDLL.featureBoolSet(self._handle, - self._name, - valueToSet) - if errorCode != 0: - raise VimbaException(errorCode) - - def _unknownRange(self): - """ - Returns empty for ranges that have not been implemented. - """ - return '' - - def _rangeQueryIntFeature(self): - """ - Get the range of an int feature. - - :returns: tuple -- min and max range. - """ - - # create args - minToGet = c_int64() - maxToGet = c_int64() - - errorCode = VimbaDLL.featureIntRangeQuery(self._handle, - self._name, - byref(minToGet), - byref(maxToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return (int(str(minToGet.value)), int(str(maxToGet.value))) - - def _rangeQueryFloatFeature(self): - """ - Get the range of a float feature. - - :returns: tuple -- min and max range. - """ - - # create args - minToGet = c_double() - maxToGet = c_double() - - errorCode = VimbaDLL.featureFloatRangeQuery(self._handle, - self._name, - byref(minToGet), - byref(maxToGet)) - if errorCode != 0: - raise VimbaException(errorCode) - - return (minToGet.value, maxToGet.value) - - def _rangeQueryEnumFeature(self): - """ - Get the range of an enum feature. - :returns: list -- enum names for the given feature. - """ - - # call once to get number of available enum names - # Vimba DLL will return an error code - numFound = c_uint32(-1) - errorCode = VimbaDLL.featureEnumRangeQuery(self._handle, - self._name, - None, - 0, - byref(numFound)) - if errorCode != 0: - raise VimbaException(errorCode) - - # number of names specified by Vimba - numEnumNames = numFound.value - - # args - enumNamesArray = (c_char_p * numEnumNames)() - - # call again to get the enum names - # Vimba DLL will return an error code - errorCode = VimbaDLL.featureEnumRangeQuery(self._handle, - self._name, - enumNamesArray, - numEnumNames, - byref(numFound)) - if errorCode != 0: - raise VimbaException(errorCode) - - return list(enumName.decode() for enumName in enumNamesArray) diff --git a/pymba/vimbaframe.py b/pymba/vimbaframe.py deleted file mode 100644 index a95f6a7..0000000 --- a/pymba/vimbaframe.py +++ /dev/null @@ -1,175 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimbastructure as structs -from .vimbaexception import VimbaException -from .vimbadll import VimbaDLL -from .vimbadll import VimbaC_MemoryBlock -from ctypes import * -import warnings -try: - import numpy as np -except ImportError: - warnings.warn('numpy not found, some VimbaFrame methods will not be available') - - -""" -Map pixel formats to bytes per pixel. - The packed formats marked with "?" have not been tested. -""" -PIXEL_FORMATS = { - "Mono8": 1, - "Mono12": 2, - "Mono12Packed": 1.5, # ? - "Mono14": 2, - "Mono16": 2, - "RGB8": 3, - "RGB8Packed": 3, - "BGR8Packed": 3, - "RGBA8Packed": 4, - "BGRA8Packed": 4, - "YUV411Packed": 4/3.0, # ? - "YUV422Packed": 2, - "YUV444Packed": 3, - "BayerRG8": 1, - "BayerRG12": 2, - "BayerGR8": 1, - "BayerGR12": 2, - "BayerGR12Packed": 1.5, # ? -} - - -class VimbaFrame(object): - """ - A Vimba frame. - """ - def __init__(self, camera): - self._camera = camera - self._handle = camera.handle - - # get frame sizes - self.payloadSize = self._camera.PayloadSize - self.width = self._camera.Width - self.height = self._camera.Height - self.pixel_bytes = PIXEL_FORMATS[self._camera.PixelFormat] - - # frame structure - self._frame = structs.VimbaFrame() - - def announceFrame(self): - """ - Announce frames to the API that may be queued for frame capturing later. - - Runs VmbFrameAnnounce - - Should be called after the frame is created. Call startCapture - after this method. - """ - # size of expected frame - sizeOfFrame = self.payloadSize - - # keep this reference to keep block alive for life of frame - self._cMem = VimbaC_MemoryBlock(sizeOfFrame) - # set buffer to have length of expected payload size - self._frame.buffer = self._cMem.block - - # set buffer size to expected payload size - self._frame.bufferSize = sizeOfFrame - - errorCode = VimbaDLL.frameAnnounce(self._handle, - byref(self._frame), - sizeof(self._frame)) - - if errorCode != 0: - raise VimbaException(errorCode) - - def revokeFrame(self): - """ - Revoke a frame from the API. - """ - errorCode = VimbaDLL.frameRevoke(self._handle, - byref(self._frame)) - - if errorCode != 0: - raise VimbaException(errorCode) - - def queueFrameCapture(self, frameCallback = None): - """ - Queue frames that may be filled during frame capturing. - Runs VmbCaptureFrameQueue - - Call after announceFrame and startCapture - - Callback must accept argument of type frame. Remember to requeue the - frame by calling frame.queueFrameCapture(frameCallback) at the end of - your callback function. - """ - # remember the given callback function - self._frameCallback = frameCallback - - # define a callback wrapper here so it doesn't bind self - def frameCallbackWrapper(cam_handle, p_frame): - # call the user's callback with the self bound outside the wrapper - # ignore the frame pointer since we already know the callback - # refers to this frame - self._frameCallback(self) - - if self._frameCallback is None: - self._frameCallbackWrapper_C = None - else: - # keep a reference to prevent gc issues - self._frameCallbackWrapper_C = VimbaDLL.frameDoneCallback(frameCallbackWrapper) - - errorCode = VimbaDLL.captureFrameQueue(self._handle, - byref(self._frame), - self._frameCallbackWrapper_C) - if errorCode != 0: - raise VimbaException(errorCode) - - def waitFrameCapture(self, timeout=2000): - """ - Wait for a queued frame to be filled (or dequeued). Returns Errorcode - upon completion. - Runs VmbCaptureFrameWait - - timeout - int, milliseconds default(timeout, 2000) - - Call after an acquisition command - """ - errorCode = VimbaDLL.captureFrameWait(self._handle, - byref(self._frame), - timeout) - - # errorCode to be processed by the end user for this function. - # Prevents system for breaking for example on a hardware trigger - # timeout - #if errorCode != 0: - #raise VimbaException(errorCode) - return errorCode - - # custom method for simplified usage - def getBufferByteData(self): - """ - Retrieve buffer data in a useful format. - - :returns: array -- buffer data. - """ - - # cast frame buffer memory contents to a usable type - data = cast(self._frame.buffer, - POINTER(c_ubyte * self.payloadSize)) - - # make array of c_ubytes from buffer - array = (c_ubyte * int(self.height*self.pixel_bytes) * - int(self.width*self.pixel_bytes)).from_address(addressof( - data.contents)) - - return array - - def getImage(self): - cframe = self._frame - data = cast(cframe.buffer, POINTER(c_ubyte * cframe.imageSize)) - try: - return np.ndarray(buffer=data.contents, dtype=np.uint8, shape=(cframe.height, cframe.width)) - except NameError as e: - print('install numpy to use this method or use getBufferByteData instead') - raise e diff --git a/pymba/vimbainterface.py b/pymba/vimbainterface.py deleted file mode 100644 index 82a0c2e..0000000 --- a/pymba/vimbainterface.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimbastructure as structs -from .vimbaobject import VimbaObject -from .vimbaexception import VimbaException -from .vimbadll import VimbaDLL -from ctypes import * - -# interface features are automatically readable as object attributes. - - -class VimbaInterface(VimbaObject): - - """ - A Vimba interface object. This class provides the minimal access - to Vimba functions required to control the interface. - """ - - @property - def interfaceIdString(self): - return self._interfaceIdString - - # own handle is inherited as self._handle - def __init__(self, interfaceIdString): - - # call super constructor - super(VimbaInterface, self).__init__() - - # set ID - self._interfaceIdString = interfaceIdString - - def openInterface(self): - """ - Open the interface. - """ - errorCode = VimbaDLL.interfaceOpen(self._interfaceIdString, - byref(self._handle)) - if errorCode != 0: - raise VimbaException(errorCode) - - def closeInterface(self): - """ - Close the interface. - """ - errorCode = VimbaDLL.interfaceClose(self._handle) - if errorCode != 0: - raise VimbaException(errorCode) diff --git a/pymba/vimbaobject.py b/pymba/vimbaobject.py deleted file mode 100644 index 695a011..0000000 --- a/pymba/vimbaobject.py +++ /dev/null @@ -1,232 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from . import vimbastructure as structs -from .vimbaexception import VimbaException -from .vimbafeature import VimbaFeature -from .vimbadll import VimbaDLL -from ctypes import * - - -class VimbaObject(object): - - """ - A Vimba object has a handle and features associated with it. - Objects include System, Camera, Interface and AncillaryData. - """ - - @property - def handle(self): - return self._handle - - def __init__(self): - # create own handle - self._handle = c_void_p() - - # list of VimbaFeatureInfo objects - # can't set yet as the object (e.g. a camera) won't be - # opened yet, therefore no event for object opening - # so will have it populate by user interaction - # and blame them if the object is not opened then - self._featureInfos = None - - # override getattr for undefined attributes - def __getattr__(self, attr): - - # if a feature value requested (requires object (camera) open) - if attr in self.getFeatureNames(): - return VimbaFeature(attr, self._handle).value - - # otherwise don't know about it - raise AttributeError(''.join(["'VimbaObject' has no attribute '", - attr, - "'"])) - - # override setattr for undefined attributes - def __setattr__(self, attr, val): - - # set privates as normal - # check this first to allow all privates to set normally - # and avoid recursion errors - if attr.startswith('_'): - super(VimbaObject, self).__setattr__(attr, val) - - # if it's an actual camera feature (requires camera open) - elif attr in self.getFeatureNames(): - VimbaFeature(attr, self._handle).value = val - - # otherwise just set the attribute value as normal - else: - super(VimbaObject, self).__setattr__(attr, val) - - def _getFeatureInfos(self): - """ - Gets feature info of all available features. Will - cause error if object/camera is not opened. - - :returns: list -- feature info for available features. - """ - # check it's populated as can't populate it in __init__ - if self._featureInfos is None: - # args - dummyFeatureInfo = structs.VimbaFeatureInfo() - numFound = c_uint32(-1) - - # call once to get number of available features - # Vimba DLL will return an error code - errorCode = VimbaDLL.featuresList(self._handle, - None, - 0, - byref(numFound), - sizeof(dummyFeatureInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - - # number of features specified by Vimba - numFeatures = numFound.value - - # args - featureInfoArray = (structs.VimbaFeatureInfo * numFeatures)() - - # call again to get the features - # Vimba DLL will return an error code - errorCode = VimbaDLL.featuresList(self._handle, - featureInfoArray, - numFeatures, - byref(numFound), - sizeof(dummyFeatureInfo)) - if errorCode != 0: - raise VimbaException(errorCode) - - self._featureInfos = list( - featInfo for featInfo in featureInfoArray) - return self._featureInfos - - def getFeatureNames(self): - """ - Get names of all available features. - - :returns: list -- feature names for available features. - """ - return list(featInfo.name.decode() for featInfo in self._getFeatureInfos()) - - def getFeatureInfo(self, featureName): - """ - Gets feature info object of specified feature. - - :param featureName: the name of the feature. - - :returns: VimbaFeatureInfo object -- the feature info object specified. - """ - # don't do this live as we already have this info - # return info object, if it exists - for featInfo in self._getFeatureInfos(): - if featInfo.name.decode() == featureName: - return featInfo - # otherwise raise error - raise VimbaException(-53) - - # don't think we ever need to return a feature object... - # def getFeature(self, featureName): - - def getFeatureRange(self, featureName): - """ - Get valid range of feature values. - - :param featureName: name of the feature to query. - - :returns: tuple -- range as (feature min value, feature max value, for int or float features only). - list -- names of possible enum values (for enum features only). - """ - # can't cache this, need to look it up live - return VimbaFeature(featureName.encode(), self._handle).range - - def runFeatureCommand(self, featureName): - """ - Run a feature command. - - :param featureName: the name of the feature. - """ - # run a command - errorCode = VimbaDLL.featureCommandRun(self._handle, - featureName.encode()) - if errorCode != 0: - raise VimbaException(errorCode) - - def featureCommandIsDone(self, featureName): - isDone = c_bool() - errorCode = VimbaDLL.featureCommandIsDone(self._handle, - featureName.encode(), - byref(isDone)) - - if errorCode != 0: - raise VimbaException(errorCode) - - return isDone.value - - - def readRegister(self, address): - # note that the underlying Vimba function allows reading of an array - # of registers, but only one address/value at a time is implemented - # here - """ - Read from a register of the module (camera). - - :param address: the address of the register to read. - - :returns: int -- value of register. - """ - readCount = 1 - - # check address validity - try: - regAddress = c_uint64(int(address, 16)) - except: - raise VimbaException(-52) - - regData = c_uint64() - numCompleteReads = c_uint32() - - errorCode = VimbaDLL.registersRead(self.handle, - readCount, - byref(regAddress), - byref(regData), - byref(numCompleteReads)) - - if errorCode != 0: - raise VimbaException(errorCode) - - return regData.value - - def writeRegister(self, address, value): - # note that the underlying Vimba function allows writing of an array - # of registers, but only one address/value at a time is implemented - # here - """ - Read from a register of the module (camera). - - :param address: the address of the register to read. - :param value: the value to set in hex. - """ - writeCount = 1 - - # check address validity - try: - regAddress = c_uint64(int(address, 16)) - except: - raise VimbaException(-52) - - # check value validity - try: - regData = c_uint64(int(value, 16)) - except: - raise VimbaException(-52) - - numCompleteWrites = c_uint32() - - errorCode = VimbaDLL.registersWrite(self.handle, - writeCount, - byref(regAddress), - byref(regData), - byref(numCompleteWrites)) - if errorCode != 0: - raise VimbaException(errorCode) diff --git a/pymba/vimbastructure.py b/pymba/vimbastructure.py deleted file mode 100644 index 73c4e96..0000000 --- a/pymba/vimbastructure.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -from ctypes import * - - -class VimbaVersion(Structure): - _fields_ = [('major', c_uint32), - ('minor', c_uint32), - ('patch', c_uint32)] - - -class VimbaInterfaceInfo(Structure): - _fields_ = [('interfaceIdString', c_char_p), # Unique identifier for each interface - # Interface type, see VmbInterfaceType - ('interfaceType', c_uint32), - # Interface name, given by the transport layer - ('interfaceName', c_char_p), - ('serialString', c_char_p), # Serial number - ('permittedAccess', c_uint32)] # Used access mode, see VmbAccessModeType - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] - - -class VimbaCameraInfo(Structure): - _fields_ = [('cameraIdString', c_char_p), # Unique identifier for each camera - ('cameraName', c_char_p), # Name of the camera - ('modelName', c_char_p), # Model name - ('serialString', c_char_p), # Serial number - # Used access mode, see VmbAccessModeType - ('permittedAccess', c_uint32), - ('interfaceIdString', c_char_p)] # Unique value for each interface or bus - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] - - -class VimbaFeatureInfo(Structure): - - _fields_ = [('name', c_char_p), - ('featureDataType', c_uint32), - ('featureFlags', c_uint32), - ('category', c_char_p), - ('displayName', c_char_p), - ('pollingTime', c_uint32), - ('unit', c_char_p), - ('representation', c_char_p), - ('visibility', c_uint32), - ('tooltip', c_char_p), - ('description', c_char_p), - ('sfncNamespace', c_char_p), - ('isStreamable', c_bool), - ('hasAffectedFeatures', c_bool), - ('hasSelectedFeatures', c_bool)] - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] - - -class VimbaFrame(Structure): - - # IN - _fields_ = [('buffer', c_void_p), # Comprises image and ancillary data - ('bufferSize', c_uint32), # Size of the data buffer - - # User context filled during queuing - ('context', c_void_p * 4), - - # OUT - # Resulting status of the receive operation - ('receiveStatus', c_int32), - # Resulting flags of the receive operation - ('receiveFlags', c_uint32), - - # Size of the image data inside the data buffer - ('imageSize', c_uint32), - # Size of the ancillary data inside the data buffer - ('ancillarySize', c_uint32), - - # Pixel format of the image - ('pixelFormat', c_uint32), - - ('width', c_uint32), # Width of an image - ('height', c_uint32), # Height of an image - # Horizontal offset of an image - ('offsetX', c_uint32), - # Vertical offset of an image - ('offsetY', c_uint32), - - # Unique ID of this frame in this stream - ('frameID', c_uint64), - ('timestamp', c_uint64)] # Timestamp of the data transfer - - def getFieldNames(self): - """ - Get field names. - """ - return [field[0] for field in self._fields_] diff --git a/pymba/vimbasystem.py b/pymba/vimbasystem.py deleted file mode 100644 index d1f9603..0000000 --- a/pymba/vimbasystem.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import -from .vimbaobject import VimbaObject -from ctypes import c_void_p - -# system features are automatically readable as attributes. - - -class VimbaSystem(VimbaObject): - - """ - A Vimba system object. This class provides the minimal access - to Vimba functions required to control the system. - """ - - # own handle is inherited as self._handle - - def __init__(self): - - # call super constructor - super(VimbaSystem, self).__init__() - - # set own handle manually - self._handle = c_void_p(1) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/opencv_example.py b/tests/opencv_example.py new file mode 100644 index 0000000..238e8b4 --- /dev/null +++ b/tests/opencv_example.py @@ -0,0 +1,76 @@ +from __future__ import absolute_import, print_function, division +from pymba import * +import numpy as np +import cv2 +import time + +#very crude example, assumes your camera is PixelMode = BAYERRG8 + +# start Vimba +with Vimba() as vimba: + # get system object + system = vimba.getSystem() + + # list available cameras (after enabling discovery for GigE cameras) + if system.GeVTLIsPresent: + system.runFeatureCommand("GeVDiscoveryAllOnce") + time.sleep(0.2) + cameraIds = vimba.getCameraIds() + for cameraId in cameraIds: + print('Camera ID:', cameraId) + + # get and open a camera + camera0 = vimba.getCamera(cameraIds[0]) + camera0.openCamera() + + # list camera features + cameraFeatureNames = camera0.getFeatureNames() + for name in cameraFeatureNames: + print('Camera feature:', name) + + # read info of a camera feature + #featureInfo = camera0.getFeatureInfo('AcquisitionMode') + #for field in featInfo.getFieldNames(): + # print field, '--', getattr(featInfo, field) + + # get the value of a feature + print(camera0.AcquisitionMode) + + # set the value of a feature + camera0.AcquisitionMode = 'SingleFrame' + + # create new frames for the camera + frame0 = camera0.getFrame() # creates a frame + frame1 = camera0.getFrame() # creates a second frame + + # announce frame + frame0.announceFrame() + + # capture a camera image + count = 0 + while count < 10: + camera0.startCapture() + frame0.queueFrameCapture() + camera0.runFeatureCommand('AcquisitionStart') + camera0.runFeatureCommand('AcquisitionStop') + frame0.waitFrameCapture() + + # get image data... + imgData = frame0.getBufferByteData() + + moreUsefulImgData = np.ndarray(buffer = frame0.getBufferByteData(), + dtype = np.uint8, + shape = (frame0.height, + frame0.width, + 1)) + rgb = cv2.cvtColor(moreUsefulImgData, cv2.COLOR_BAYER_RG2RGB) + cv2.imwrite('foo{}.png'.format(count), rgb) + print("image {} saved".format(count)) + count += 1 + camera0.endCapture() + # clean up after capture + camera0.revokeAllFrames() + + # close camera + camera0.closeCamera() + diff --git a/tests/opencv_liveview_example.py b/tests/opencv_liveview_example.py new file mode 100644 index 0000000..78b6b67 --- /dev/null +++ b/tests/opencv_liveview_example.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon Jul 07 14:59:03 2014 + +@author: derricw +""" + +from __future__ import absolute_import, print_function, division +from pymba import * +import numpy as np +import cv2 +import time + +cv2.namedWindow("test") + +with Vimba() as vimba: + system = vimba.getSystem() + + system.runFeatureCommand("GeVDiscoveryAllOnce") + time.sleep(0.2) + + camera_ids = vimba.getCameraIds() + + for cam_id in camera_ids: + print("Camera found: ", cam_id) + + c0 = vimba.getCamera(camera_ids[0]) + c0.openCamera() + + try: + #gigE camera + print(c0.GevSCPSPacketSize) + print(c0.StreamBytesPerSecond) + c0.StreamBytesPerSecond = 100000000 + except: + #not a gigE camera + pass + + #set pixel format + c0.PixelFormat="Mono8" + #c0.ExposureTimeAbs=60000 + + frame = c0.getFrame() + frame.announceFrame() + + c0.startCapture() + + framecount = 0 + droppedframes = [] + + while 1: + try: + frame.queueFrameCapture() + success = True + except: + droppedframes.append(framecount) + success = False + c0.runFeatureCommand("AcquisitionStart") + c0.runFeatureCommand("AcquisitionStop") + frame.waitFrameCapture(1000) + frame_data = frame.getBufferByteData() + if success: + img = np.ndarray(buffer=frame_data, + dtype=np.uint8, + shape=(frame.height,frame.width,1)) + cv2.imshow("test",img) + framecount+=1 + k = cv2.waitKey(1) + if k == 0x1b: + cv2.destroyAllWindows() + print("Frames displayed: %i"%framecount) + print("Frames dropped: %s"%droppedframes) + break + + + c0.endCapture() + c0.revokeAllFrames() + + c0.closeCamera() diff --git a/tests/opencv_liveview_example_color.py b/tests/opencv_liveview_example_color.py new file mode 100644 index 0000000..fd7a819 --- /dev/null +++ b/tests/opencv_liveview_example_color.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +""" +Created on Mon Jul 07 14:59:03 2014 + +@author: derricw + +Same as the other liveview example, but displays in color. + +Obviously you want to use a camera that has a color mode like BGR8Packed + +OpenCV is expecting color images to be in BGR8Packed by default. It can work + with other formats as well as convert one to the other, but this example + just uses its default behavior. + +""" +from __future__ import absolute_import, print_function, division +from pymba import * +import numpy as np +import cv2 +import time +import sys + +cv2.namedWindow("test") + +with Vimba() as vimba: + system = vimba.getSystem() + + system.runFeatureCommand("GeVDiscoveryAllOnce") + time.sleep(0.2) + + camera_ids = vimba.getCameraIds() + + for cam_id in camera_ids: + print("Camera found: ", cam_id) + + c0 = vimba.getCamera(camera_ids[0]) + c0.openCamera() + + try: + #gigE camera + print("Packet size:", c0.GevSCPSPacketSize) + c0.StreamBytesPerSecond = 100000000 + print("BPS:", c0.StreamBytesPerSecond) + except: + #not a gigE camera + pass + + #set pixel format + c0.PixelFormat = "BGR8Packed" # OPENCV DEFAULT + time.sleep(0.2) + + frame = c0.getFrame() + frame.announceFrame() + + c0.startCapture() + + framecount = 0 + droppedframes = [] + + while 1: + try: + frame.queueFrameCapture() + success = True + except: + droppedframes.append(framecount) + success = False + c0.runFeatureCommand("AcquisitionStart") + c0.runFeatureCommand("AcquisitionStop") + frame.waitFrameCapture(1000) + frame_data = frame.getBufferByteData() + if success: + img = np.ndarray(buffer=frame_data, + dtype=np.uint8, + shape=(frame.height, frame.width, frame.pixel_bytes)) + cv2.imshow("test", img) + framecount += 1 + k = cv2.waitKey(1) + if k == 0x1b: + cv2.destroyAllWindows() + print("Frames displayed: %i" % framecount) + print("Frames dropped: %s" % droppedframes) + break + + + c0.endCapture() + c0.revokeAllFrames() + + c0.closeCamera() + diff --git a/tests/test_cameras.py b/tests/test_cameras.py new file mode 100644 index 0000000..a5a4dd9 --- /dev/null +++ b/tests/test_cameras.py @@ -0,0 +1,72 @@ +#!/usr/bin/python +from __future__ import absolute_import, print_function, division +from pymba import * +import time + + +def test_cameras(): + # start Vimba + with Vimba() as vimba: + # get system object + system = vimba.getSystem() + + # list available cameras (after enabling discovery for GigE cameras) + if system.GeVTLIsPresent: + system.runFeatureCommand("GeVDiscoveryAllOnce") + time.sleep(0.2) + + cameraIds = vimba.getCameraIds() + for cameraId in cameraIds: + print('Camera ID:', cameraId) + + # get and open a camera + camera0 = vimba.getCamera(cameraIds[0]) + camera0.openCamera() + + # list camera features + cameraFeatureNames = camera0.getFeatureNames() + for name in cameraFeatureNames: + print('Camera feature:', name) + + # get the value of a feature + print(camera0.AcquisitionMode) + + # set the value of a feature + camera0.AcquisitionMode = 'SingleFrame' + + # create new frames for the camera + frame0 = camera0.getFrame() # creates a frame + frame1 = camera0.getFrame() # creates a second frame + + # announce frame + frame0.announceFrame() + + # capture a camera image + camera0.startCapture() + frame0.queueFrameCapture() + camera0.runFeatureCommand('AcquisitionStart') + camera0.runFeatureCommand('AcquisitionStop') + frame0.waitFrameCapture() + + # get image data... + imgData = frame0.getBufferByteData() + + # ...or use NumPy for fast image display (for use with OpenCV, etc) + import numpy as np + + moreUsefulImgData = np.ndarray(buffer=frame0.getBufferByteData(), + dtype=np.uint8, + shape=(frame0.height, + frame0.width, + 1)) + + # clean up after capture + camera0.endCapture() + camera0.revokeAllFrames() + + # close camera + camera0.closeCamera() + + +if __name__ == '__main__': + test_cameras() \ No newline at end of file diff --git a/tests/test_enumfeature.py b/tests/test_enumfeature.py new file mode 100644 index 0000000..7f9dd4c --- /dev/null +++ b/tests/test_enumfeature.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +from __future__ import absolute_import, print_function, division +from pymba import * + + +def test_enumfeature(): + # get system object + with Vimba() as vimba: + system = vimba.getSystem() + + # get enum value + print ("get enum value (DiscoveryCameraEvent): '%s'" % (system.DiscoveryCameraEvent)) + + # get enum range + range = system.getFeatureRange('DiscoveryCameraEvent') + print ("get enum value range (DiscoveryCameraEvent): '%s'" % (str(range))) + + # set enum value + #print ("setting enum value (DiscoveryCameraEvent)...") + #system.DiscoveryCameraEvent = 'Unreachable' + #print ("enum value (DiscoveryCameraEvent)set to '%s'." % (system.DiscoveryCameraEvent.value)) + + +if __name__ == '__main__': + test_enumfeature() \ No newline at end of file diff --git a/tests/test_installation.py b/tests/test_installation.py new file mode 100644 index 0000000..06af7d6 --- /dev/null +++ b/tests/test_installation.py @@ -0,0 +1,9 @@ +#!/usr/bin/python +from __future__ import absolute_import, print_function, division +from pymba import Vimba + + +def test_installation(): + with Vimba() as vimba: + version = vimba.getVersion() + assert version == '1.2.0' diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py new file mode 100644 index 0000000..270d42c --- /dev/null +++ b/tests/test_interfaces.py @@ -0,0 +1,28 @@ +#!/usr/bin/python +from __future__ import absolute_import, print_function, division +from pymba import * +import time + + +def test_interfaces(): + # start Vimba + with Vimba() as vimba: + # get list of available interfaces + interfaceIds = vimba.getInterfaceIds() + for interfaceId in interfaceIds: + print('Interface ID:', interfaceId) + + # get interface object and open it + interface0 = vimba.getInterface(interfaceIds[0]) + interface0.openInterface() + + # list interface features + interfaceFeatureNames = interface0.getFeatureNames() + for name in interfaceFeatureNames: + print('Interface feature:', name) + + # close interface + interface0.closeInterface() + +if __name__ == '__main__': + test_interfaces() \ No newline at end of file diff --git a/tests/test_systemfeature.py b/tests/test_systemfeature.py new file mode 100644 index 0000000..abb4da7 --- /dev/null +++ b/tests/test_systemfeature.py @@ -0,0 +1,20 @@ +#!/usr/bin/python +from __future__ import absolute_import, print_function, division +from pymba import * + + +def test_systemfeature(): + # get system object + with Vimba() as vimba: + system = vimba.getSystem() + + # list system features + for featureName in system.getFeatureNames(): + print('System feature:', featureName) + fInfo = system.getFeatureInfo(featureName) + for field in fInfo.getFieldNames(): + print("\t", featureName, ":", field, getattr(fInfo, field)) + + +if __name__ == '__main__': + test_systemfeature() \ No newline at end of file -- cgit v1.2.3