aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormorefigs <morefigs@gmail.com>2019-01-30 15:12:13 +1100
committermorefigs <morefigs@gmail.com>2019-01-30 15:12:13 +1100
commit8001a079833ff96b855cb6f618b1c23a5b05ad7d (patch)
treec145667c5e9d32d90655689549d1072c0af1a61b
parent87a55df00f138e0b3f5b8469c2a43f868704426c (diff)
parent7a915f3af6af7a3a8ef6c9d28aeb87392df3c8b4 (diff)
downloadpymba-8001a079833ff96b855cb6f618b1c23a5b05ad7d.tar.gz
pymba-8001a079833ff96b855cb6f618b1c23a5b05ad7d.zip
v0.2 to master
-rw-r--r--.gitignore3
-rw-r--r--README.md168
-rw-r--r--examples/camera/get_camera_object.py9
-rw-r--r--examples/camera/list_camera_ids.py7
-rw-r--r--examples/camera/list_feature_infos.py14
-rw-r--r--examples/camera/list_feature_names.py13
-rw-r--r--examples/camera/list_feature_values_and_ranges.py34
-rw-r--r--examples/camera/opencv_capture_image.py34
-rw-r--r--examples/camera/opencv_capture_image_with_callback.py44
-rw-r--r--examples/camera/write_feature_value.py22
-rw-r--r--examples/interface/get_interface_object.py9
-rw-r--r--examples/interface/list_feature_infos.py14
-rw-r--r--examples/interface/list_feature_names.py13
-rw-r--r--examples/interface/list_feature_values_and_ranges.py33
-rw-r--r--examples/interface/list_interface_ids.py7
-rw-r--r--examples/interface/write_feature_value.py22
-rw-r--r--examples/show_version.py6
-rw-r--r--examples/system/get_system_object.py8
-rw-r--r--examples/system/list_feature_values_and_ranges.py30
-rw-r--r--pymba/__init__.py7
-rw-r--r--pymba/camera.py161
-rw-r--r--pymba/feature.py234
-rw-r--r--pymba/frame.py127
-rw-r--r--pymba/interface.py92
-rw-r--r--pymba/system.py9
-rw-r--r--pymba/vimba.py296
-rw-r--r--pymba/vimba_c.py430
-rw-r--r--pymba/vimba_camera.py129
-rw-r--r--pymba/vimba_dll.py489
-rw-r--r--pymba/vimba_exception.py111
-rw-r--r--pymba/vimba_feature.py341
-rw-r--r--pymba/vimba_frame.py180
-rw-r--r--pymba/vimba_interface.py47
-rw-r--r--pymba/vimba_object.py336
-rw-r--r--pymba/vimba_structure.py106
-rw-r--r--pymba/vimba_system.py22
-rw-r--r--setup.py45
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/opencv_example.py76
-rw-r--r--tests/opencv_liveview_example.py79
-rw-r--r--tests/opencv_liveview_example_color.py89
-rw-r--r--tests/test_cameras.py72
-rw-r--r--tests/test_enumfeature.py25
-rw-r--r--tests/test_installation.py9
-rw-r--r--tests/test_interfaces.py28
-rw-r--r--tests/test_systemfeature.py20
-rw-r--r--tests/test_vimba.py52
47 files changed, 1755 insertions, 2347 deletions
diff --git a/.gitignore b/.gitignore
index 692ad13..55ff08c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,6 @@ nosetests.xml
# PyCharm
.idea/
.cache/
+
+venv*
+scrap/
diff --git a/README.md b/README.md
index 7d30c08..bf5c017 100644
--- a/README.md
+++ b/README.md
@@ -1,157 +1,47 @@
# Pymba
-
-
Pymba is a Python wrapper for Allied Vision's Vimba C API. It wraps the VimbaC library file included in the Vimba installation to provide a simple Python interface for Allied Vision cameras. It currently supports most of the functionality provided by Vimba.
-## Installation
-
-Download the Vimba SDK from Allied Vision: https://www.alliedvision.com/en/products/software.html.
+## Requirements
+
+### Vimba SDK
+
+* Download and run the Vimba SDK installer from Allied Vision from https://www.alliedvision.com/en/products/software.html.
+* Select "Custom Selection".
+* Select (at least) the following options:
+ * A transport layer that matches your hardware (e.g. "Vimba USB Transport Layer" for USB cameras)
+ * Core components
+ * Register GenICam Path variable
+ * Vimba SDK
+ * Core components
+ * Register environment variables
+ * C API runtime components
+ * C API development components
+ * Driver Installer
+ * Vimba Viewer
+* Run `VimbaDriverInstaller.exe` and install the relevant driver.
+* Test the driver installation by running `VimbaViewer.exe`.
-Run the AVTDriverInstaller tool and install the AVT Vimba SDK drivers.
+## Installation
-Install pymba.
+Install Pymba via PIP.
-## Usage
+ pip install pymba
-### Testing installation
+## Testing installation
If Vimba and pymba are installed correctly, then the following code examples should give the installed Vimba version. No camera is needed.
-Checking the version using a context manager:
-
- from pymba import *
-
- with Vimba() as vimba:
- print(vimba.getVersion())
-
-Or without using a context manager:
-
- from pymba import *
-
- vimba = Vimba()
- vimba.startup()
- print(vimba.getVersion())
- vimba.shutdown()
-
-### Interacting with cameras
-
-Discover, open, manipulate, and capture frames from a camera.
-
- from pymba import *
- import time
-
- # 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(cameraId)
-
- # get and open a camera
- camera0 = vimba.getCamera(cameraIds[0])
- camera0.openCamera()
-
- # list camera features
- cameraFeatureNames = camera0.getFeatureNames()
- for name in cameraFeatureNames:
- print(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
-
-### Interacting with the Vimba system
-
-Get a reference to the Vimba system object and list available system features.
-
- from pymba import *
-
- with Vimba() as vimba:
- # get system object
- system = vimba.getSystem()
-
- # list system features
- for featureName in system.getFeatureNames():
- print(featureName)
-
-### Interacting with transport layer interfaces
-
-Get a reference to an interface object and list available interface features.
+ from pymba import Vimba
- from pymba import *
+ print(Vimba.version())
- with Vimba() as vimba:
- # get list of available interfaces
- interfaceIds = vimba.getInterfaceIds()
- for interfaceId in interfaceIds:
- print(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(name)
-
- # close interface
- interface0.closeInterface()
-
-
-
-### Handling Vimba exceptions
-
- from pymba import *
-
- try:
- with Vimba() as vimba:
- except VimbaException as e:
- print(e.message)
+## Usage examples
-
+Usage examples can be found in [examples/](examples/).
## Known issues
-* Not all API functions are wrapped (most are). For full list see vimbadll.py.
+* Not all API functions are supported.
+* Not all camera pixel formats are currently supported.
diff --git a/examples/camera/get_camera_object.py b/examples/camera/get_camera_object.py
new file mode 100644
index 0000000..7a830f7
--- /dev/null
+++ b/examples/camera/get_camera_object.py
@@ -0,0 +1,9 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ # provide camera index or id
+ camera = vimba.camera(0)
+ print(camera)
diff --git a/examples/camera/list_camera_ids.py b/examples/camera/list_camera_ids.py
new file mode 100644
index 0000000..670d71f
--- /dev/null
+++ b/examples/camera/list_camera_ids.py
@@ -0,0 +1,7 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ print(vimba.camera_ids())
diff --git a/examples/camera/list_feature_infos.py b/examples/camera/list_feature_infos.py
new file mode 100644
index 0000000..03ad935
--- /dev/null
+++ b/examples/camera/list_feature_infos.py
@@ -0,0 +1,14 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ camera = vimba.camera(0)
+ camera.open()
+
+ for feature_name in camera.feature_names():
+ feature = camera.feature(feature_name)
+ print(feature.info)
+
+ camera.close()
diff --git a/examples/camera/list_feature_names.py b/examples/camera/list_feature_names.py
new file mode 100644
index 0000000..d3415dc
--- /dev/null
+++ b/examples/camera/list_feature_names.py
@@ -0,0 +1,13 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ camera = vimba.camera(0)
+ camera.open()
+
+ for feature_name in camera.feature_names():
+ print(feature_name)
+
+ camera.close()
diff --git a/examples/camera/list_feature_values_and_ranges.py b/examples/camera/list_feature_values_and_ranges.py
new file mode 100644
index 0000000..353d48e
--- /dev/null
+++ b/examples/camera/list_feature_values_and_ranges.py
@@ -0,0 +1,34 @@
+from pymba import Vimba, VimbaException
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ camera = vimba.camera(0)
+ camera.open()
+
+ # get feature value via feature object
+ for feature_name in camera.feature_names():
+ feature = camera.feature(feature_name)
+
+ try:
+ value = feature.value
+ range_ = feature.range
+
+ # alternatively the feature value can be read as an object attribute
+ # value = getattr(camera, feature_name)
+ # or
+ # value = camera.someFeatureName
+
+ except VimbaException as e:
+ value = e
+ range_ = None
+
+ print('\n\t'.join(
+ str(x) for x in (
+ feature_name,
+ f'value: {value}',
+ f'range: {range_}')
+ if x is not None))
+
+ camera.close()
diff --git a/examples/camera/opencv_capture_image.py b/examples/camera/opencv_capture_image.py
new file mode 100644
index 0000000..e8bf3d5
--- /dev/null
+++ b/examples/camera/opencv_capture_image.py
@@ -0,0 +1,34 @@
+import cv2
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ camera = vimba.camera(0)
+ camera.open()
+
+ # setup camera and frame and capture a single image
+ camera.AcquisitionMode = 'SingleFrame'
+ frame = camera.create_frame()
+ frame.announce()
+ camera.start_capture()
+ frame.queue_for_capture()
+ camera.run_feature_command('AcquisitionStart')
+ camera.run_feature_command('AcquisitionStop')
+ frame.wait_for_capture()
+
+ # get the image data as a numpy array
+ image = frame.image_numpy_array()
+
+ # display image
+ cv2.imshow(camera.camera_id, image)
+ # waits for user to close image
+ cv2.waitKey(0)
+
+ # stop capturing and clean up
+ camera.end_capture()
+ camera.flush_capture_queue()
+ camera.revoke_all_frames()
+
+ camera.close()
diff --git a/examples/camera/opencv_capture_image_with_callback.py b/examples/camera/opencv_capture_image_with_callback.py
new file mode 100644
index 0000000..4d5fa28
--- /dev/null
+++ b/examples/camera/opencv_capture_image_with_callback.py
@@ -0,0 +1,44 @@
+from time import sleep
+import cv2
+from pymba import Vimba
+from pymba.frame import Frame
+
+
+def on_callback(completed_frame: Frame):
+ print('Callback called!')
+
+ # get the image data as a numpy array
+ image = completed_frame.image_numpy_array()
+
+ # display image
+ cv2.imshow(camera.camera_id, image)
+ # waits for user to close image
+ cv2.waitKey(0)
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ camera = vimba.camera(0)
+ camera.open()
+
+ # setup camera and frame and capture a single image
+ camera.AcquisitionMode = 'SingleFrame'
+ frame = camera.create_frame()
+ frame.announce()
+ camera.start_capture()
+ frame.queue_for_capture(on_callback)
+ camera.run_feature_command('AcquisitionStart')
+ camera.run_feature_command('AcquisitionStop')
+
+ # wait long enough for the frame callback to be called
+ for _ in range(100):
+ sleep(0.1)
+ print('.', end='')
+
+ # stop capturing and clean up
+ camera.end_capture()
+ camera.flush_capture_queue()
+ camera.revoke_all_frames()
+
+ camera.close()
diff --git a/examples/camera/write_feature_value.py b/examples/camera/write_feature_value.py
new file mode 100644
index 0000000..77f8ce5
--- /dev/null
+++ b/examples/camera/write_feature_value.py
@@ -0,0 +1,22 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ camera = vimba.camera(0)
+ camera.open()
+
+ # read a feature value
+ feature = camera.feature('ExposureAuto')
+ value = feature.value
+
+ # set the feature value
+ feature.value = value
+
+ print(feature.name, '=', feature.value)
+
+ # alternatively the feature value can be set as an object attribute
+ camera.ExposureAuto = feature.value
+
+ camera.close()
diff --git a/examples/interface/get_interface_object.py b/examples/interface/get_interface_object.py
new file mode 100644
index 0000000..0465223
--- /dev/null
+++ b/examples/interface/get_interface_object.py
@@ -0,0 +1,9 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ # provide interface index or id
+ interface = vimba.interface(0)
+ print(interface)
diff --git a/examples/interface/list_feature_infos.py b/examples/interface/list_feature_infos.py
new file mode 100644
index 0000000..fefa079
--- /dev/null
+++ b/examples/interface/list_feature_infos.py
@@ -0,0 +1,14 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ interface = vimba.interface(0)
+ interface.open()
+
+ for feature_name in interface.feature_names():
+ feature = interface.feature(feature_name)
+ print(feature.info)
+
+ interface.close()
diff --git a/examples/interface/list_feature_names.py b/examples/interface/list_feature_names.py
new file mode 100644
index 0000000..6f0347d
--- /dev/null
+++ b/examples/interface/list_feature_names.py
@@ -0,0 +1,13 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ interface = vimba.interface(0)
+ interface.open()
+
+ for feature_name in interface.feature_names():
+ print(feature_name)
+
+ interface.close()
diff --git a/examples/interface/list_feature_values_and_ranges.py b/examples/interface/list_feature_values_and_ranges.py
new file mode 100644
index 0000000..b33c76a
--- /dev/null
+++ b/examples/interface/list_feature_values_and_ranges.py
@@ -0,0 +1,33 @@
+from pymba import Vimba, VimbaException
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ interface = vimba.interface(0)
+ interface.open()
+
+ # get feature value via feature object
+ for feature_name in interface.feature_names():
+ feature = interface.feature(feature_name)
+ try:
+ value = feature.value
+ range_ = feature.range
+
+ # alternatively the feature value can be read as an object attribute
+ # value = getattr(interface, feature_name)
+ # or
+ # value = interface.someFeatureName
+
+ except VimbaException as e:
+ value = e
+ range_ = None
+
+ print('\n\t'.join(
+ str(x) for x in (
+ feature_name,
+ f'value: {value}',
+ f'range: {range_}')
+ if x is not None))
+
+ interface.close()
diff --git a/examples/interface/list_interface_ids.py b/examples/interface/list_interface_ids.py
new file mode 100644
index 0000000..9a7cbec
--- /dev/null
+++ b/examples/interface/list_interface_ids.py
@@ -0,0 +1,7 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ print(vimba.interface_ids())
diff --git a/examples/interface/write_feature_value.py b/examples/interface/write_feature_value.py
new file mode 100644
index 0000000..0c71da2
--- /dev/null
+++ b/examples/interface/write_feature_value.py
@@ -0,0 +1,22 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ interface = vimba.interface(0)
+ interface.open()
+
+ # set a feature value by feature name
+ feature = interface.feature('InterfacePingPace')
+ value = feature.value
+
+ # set the feature value
+ feature.value = value
+
+ print(feature.name, '=', feature.value)
+
+ # alternatively the feature value can be set as an object attribute
+ interface.InterfacePingPace = 3
+
+ interface.close()
diff --git a/examples/show_version.py b/examples/show_version.py
new file mode 100644
index 0000000..643dc1c
--- /dev/null
+++ b/examples/show_version.py
@@ -0,0 +1,6 @@
+from pymba import Vimba, PYMBA_VERSION
+
+
+if __name__ == '__main__':
+ print(f'Pymba version: {PYMBA_VERSION}')
+ print(f'Vimba version: {Vimba.version()}')
diff --git a/examples/system/get_system_object.py b/examples/system/get_system_object.py
new file mode 100644
index 0000000..2d59001
--- /dev/null
+++ b/examples/system/get_system_object.py
@@ -0,0 +1,8 @@
+from pymba import Vimba
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ system = vimba.system()
+ print(system)
diff --git a/examples/system/list_feature_values_and_ranges.py b/examples/system/list_feature_values_and_ranges.py
new file mode 100644
index 0000000..ef4da34
--- /dev/null
+++ b/examples/system/list_feature_values_and_ranges.py
@@ -0,0 +1,30 @@
+from pymba import Vimba, VimbaException
+
+
+if __name__ == '__main__':
+
+ with Vimba() as vimba:
+ system = vimba.system()
+
+ # get feature value via feature object
+ for feature_name in system.feature_names():
+ feature = system.feature(feature_name)
+ try:
+ value = feature.value
+ range_ = feature.range
+
+ # alternatively the feature value can be read as an object attribute
+ # value = getattr(system, feature_name)
+ # or
+ # value = system.someFeatureName
+
+ except VimbaException as e:
+ value = e
+ range_ = None
+
+ print('\n\t'.join(
+ str(x) for x in (
+ feature_name,
+ f'value: {value}',
+ f'range: {range_}')
+ if x is not None))
diff --git a/pymba/__init__.py b/pymba/__init__.py
index c21ed07..b067302 100644
--- a/pymba/__init__.py
+++ b/pymba/__init__.py
@@ -1,5 +1,4 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from .vimba import Vimba
-from .vimba_exception import VimbaException
+from .vimba import Vimba, VimbaException
+
+PYMBA_VERSION = 0.2
diff --git a/pymba/camera.py b/pymba/camera.py
new file mode 100644
index 0000000..3bdc16b
--- /dev/null
+++ b/pymba/camera.py
@@ -0,0 +1,161 @@
+from ctypes import byref, sizeof, c_uint32
+from typing import Optional, List
+
+from .vimba_object import VimbaObject
+from .vimba_exception import VimbaException
+from .frame import Frame
+from . import vimba_c
+
+
+# todo update this to be more like VmbPixelFormatType in VmbCommonTypes.h
+# Map pixel formats to bytes per pixel
+PIXEL_FORMAT_BYTES = {
+ "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,
+}
+
+
+def _camera_infos() -> List[vimba_c.VmbCameraInfo]:
+ """
+ Gets camera info of all attached cameras.
+ """
+ # call once just to get the number of cameras
+ vmb_camera_info = vimba_c.VmbCameraInfo()
+ num_found = c_uint32(-1)
+ error = vimba_c.vmb_cameras_list(byref(vmb_camera_info),
+ 0,
+ byref(num_found),
+ sizeof(vmb_camera_info))
+ if error and error != VimbaException.ERR_DATA_TOO_LARGE:
+ raise VimbaException(error)
+
+ # call again to get the features
+ num_cameras = num_found.value
+ vmb_camera_infos = (vimba_c.VmbCameraInfo * num_cameras)()
+ error = vimba_c.vmb_cameras_list(vmb_camera_infos,
+ num_cameras,
+ byref(num_found),
+ sizeof(vmb_camera_info))
+ if error:
+ raise VimbaException(error)
+ return list(vmb_camera_info for vmb_camera_info in vmb_camera_infos)
+
+
+def _camera_info(id_string: str) -> vimba_c.VmbCameraInfo:
+ """
+ Gets camera info object of specified camera.
+ :param id_string: the ID of the camera object to get. This can be an ID or e.g. a serial number. Check the Vimba
+ documentation for other possible values.
+ """
+ vmb_camera_info = vimba_c.VmbCameraInfo()
+ error = vimba_c.vmb_camera_info_query(id_string.encode(),
+ vmb_camera_info,
+ sizeof(vmb_camera_info))
+ if error:
+ raise VimbaException(error)
+ return vmb_camera_info
+
+
+def camera_ids():
+ """
+ Gets IDs of all available cameras.
+ """
+ return list(vmb_camera_info.cameraIdString.decode()
+ for vmb_camera_info in _camera_infos())
+
+
+class Camera(VimbaObject):
+ """
+ A Vimba camera object.
+ """
+
+ def __init__(self, camera_id: str):
+ self._camera_id = camera_id
+ super().__init__()
+
+ @property
+ def handle(self):
+ return self._handle
+
+ @property
+ def camera_id(self) -> str:
+ return self._camera_id
+
+ @property
+ def info(self) -> vimba_c.VmbCameraInfo:
+ """
+ Get info of the camera. Does not require the camera to be opened.
+ """
+ return _camera_info(self.camera_id)
+
+ def open(self, camera_access_mode: Optional[int] = VimbaObject.VMB_ACCESS_MODE_FULL):
+ """
+ Open the camera with requested access mode.
+ """
+ error = vimba_c.vmb_camera_open(self.camera_id.encode(),
+ camera_access_mode,
+ byref(self._handle))
+ if error:
+ raise VimbaException(error)
+
+ def close(self):
+ """
+ Close the camera.
+ """
+ error = vimba_c.vmb_camera_close(self._handle)
+ if error:
+ raise VimbaException(error)
+
+ def revoke_all_frames(self):
+ """
+ Revoke all frames assigned to the camera.
+ """
+ error = vimba_c.vmb_frame_revoke_all(self._handle)
+ if error:
+ raise VimbaException(error)
+
+ def start_capture(self):
+ """
+ Prepare the API for incoming frames.
+ """
+ error = vimba_c.vmb_capture_start(self._handle)
+ if error:
+ raise VimbaException(error)
+
+ def end_capture(self):
+ """
+ Stop the API from being able to receive frames.
+ """
+ error = vimba_c.vmb_capture_end(self._handle)
+ if error:
+ raise VimbaException(error)
+
+ def flush_capture_queue(self):
+ """
+ Flush the capture queue.
+ """
+ error = vimba_c.vmb_capture_queue_flush(self._handle)
+ if error:
+ raise VimbaException(error)
+
+ def create_frame(self) -> Frame:
+ """
+ Creates and returns a new frame object. Multiple frames per camera can therefore be returned.
+ """
+ return Frame(self)
diff --git a/pymba/feature.py b/pymba/feature.py
new file mode 100644
index 0000000..7ac403d
--- /dev/null
+++ b/pymba/feature.py
@@ -0,0 +1,234 @@
+from ctypes import byref, sizeof, c_uint32, c_double, c_char_p, c_bool, c_int64, create_string_buffer
+from typing import Tuple, List, Callable
+
+from .vimba_exception import VimbaException
+from . import vimba_c
+
+
+(
+ _FEATURE_DATA_UNKNOWN,
+ _FEATURE_DATA_INT,
+ _FEATURE_DATA_FLOAT,
+ _FEATURE_DATA_ENUM,
+ _FEATURE_DATA_STRING,
+ _FEATURE_DATA_BOOL,
+ _FEATURE_DATA_COMMAND,
+ _FEATURE_DATA_RAW,
+ _FEATURE_DATA_NONE,
+) = range(9)
+
+
+class Feature:
+ """
+ A feature of a Vimba object.
+ """
+
+ @property
+ def name(self):
+ return self._name.decode()
+
+ @property
+ def info(self) -> vimba_c.VmbFeatureInfo:
+ return self._feature_info()
+
+ @property
+ def value(self):
+ return self._access_func('get', self.info.featureDataType)()
+
+ @value.setter
+ def value(self, val):
+ self._access_func('set', self.info.featureDataType)(val)
+
+ @property
+ def range(self):
+ return self._access_func('range', self.info.featureDataType)()
+
+ def __init__(self, name, handle):
+ self._name = name.encode()
+ self._handle = handle
+
+ def _access_func(self, func_type: str, data_type: int) -> Callable:
+ """
+ Get the correct function needed to access the feature attribute based on the feature's data type.
+ :param func_type: One of 'get', 'set', or 'range'.
+ :param data_type: Data type as defined in VmbFeatureDataType.
+ """
+ # (getter, setter, range) funcs
+ access_funcs = {
+ _FEATURE_DATA_UNKNOWN: (),
+ _FEATURE_DATA_INT: (self._get_int,
+ self._set_int,
+ self._range_query_int),
+ _FEATURE_DATA_FLOAT: (self._get_float,
+ self._set_float,
+ self._range_query_float),
+ _FEATURE_DATA_ENUM: (self._get_enum,
+ self._set_enum,
+ self._range_query_enum),
+ _FEATURE_DATA_STRING: (self._get_string,
+ self._set_string),
+ _FEATURE_DATA_BOOL: (self._get_bool,
+ self._set_bool),
+ _FEATURE_DATA_COMMAND: (),
+ _FEATURE_DATA_RAW: (),
+ _FEATURE_DATA_NONE: (),
+ }
+
+ access_indices = {
+ 'get': 0,
+ 'set': 1,
+ 'range': 2,
+ }
+
+ try:
+ return access_funcs[data_type][access_indices[func_type]]
+ except IndexError:
+ raise VimbaException(VimbaException.ERR_NOT_IMPLEMENTED_IN_PYMBA)
+
+ def _feature_info(self) -> vimba_c.VmbFeatureInfo:
+ vmb_feature_info = vimba_c.VmbFeatureInfo()
+ error = vimba_c.vmb_feature_info_query(self._handle,
+ self._name,
+ byref(vmb_feature_info),
+ sizeof(vmb_feature_info))
+ if error:
+ raise VimbaException(error)
+
+ return vmb_feature_info
+
+ def _get_int(self) -> int:
+ value = c_int64()
+ error = vimba_c.vmb_feature_int_get(self._handle,
+ self._name,
+ byref(value))
+ if error:
+ raise VimbaException(error)
+
+ return value.value
+
+ def _set_int(self, value: int) -> None:
+ error = vimba_c.vmb_feature_int_set(self._handle,
+ self._name,
+ value)
+ if error:
+ raise VimbaException(error)
+
+ def _get_float(self) -> float:
+ value = c_double()
+ error = vimba_c.vmb_feature_float_get(self._handle,
+ self._name,
+ byref(value))
+ if error:
+ raise VimbaException(error)
+
+ return value.value
+
+ def _set_float(self, value: float) -> None:
+ error = vimba_c.vmb_feature_float_set(self._handle,
+ self._name,
+ value)
+ if error:
+ raise VimbaException(error)
+
+ def _get_enum(self) -> str:
+ value = c_char_p()
+ error = vimba_c.vmb_feature_enum_get(self._handle,
+ self._name,
+ byref(value))
+ if error:
+ raise VimbaException(error)
+
+ return value.value.decode()
+
+ def _set_enum(self, value: str):
+ error = vimba_c.vmb_feature_enum_set(self._handle,
+ self._name,
+ value.encode())
+ if error:
+ raise VimbaException(error)
+
+ def _get_string(self) -> str:
+ buffer_size = 256
+ value = create_string_buffer(buffer_size)
+ size_filled = c_uint32()
+
+ error = vimba_c.vmb_feature_string_get(self._handle,
+ self._name,
+ value,
+ buffer_size,
+ byref(size_filled))
+ if error:
+ raise VimbaException(error)
+ return value.value.decode()
+
+ def _set_string(self, value: str) -> None:
+ error = vimba_c.vmb_feature_string_set(self._handle,
+ self._name,
+ value.encode())
+ if error:
+ raise VimbaException(error)
+
+ def _get_bool(self) -> bool:
+ value = c_bool()
+ error = vimba_c.vmb_feature_bool_get(self._handle,
+ self._name,
+ byref(value))
+ if error:
+ raise VimbaException(error)
+
+ return value.value
+
+ def _set_bool(self, value: bool):
+ error = vimba_c.vmb_feature_bool_set(self._handle,
+ self._name,
+ value)
+ if error:
+ raise VimbaException(error)
+
+ def _range_query_int(self) -> Tuple[int, int]:
+ range_min = c_int64()
+ range_max = c_int64()
+ error = vimba_c.vmb_feature_int_range_query(self._handle,
+ self._name,
+ byref(range_min),
+ byref(range_max))
+ if error:
+ raise VimbaException(error)
+
+ return int(range_min.value), int(range_max.value)
+
+ def _range_query_float(self) -> Tuple[float, float]:
+ range_min = c_double()
+ range_max = c_double()
+ error = vimba_c.vmb_feature_float_range_query(self._handle,
+ self._name,
+ byref(range_min),
+ byref(range_max))
+ if error:
+ raise VimbaException(error)
+
+ return range_min.value, range_max.value
+
+ def _range_query_enum(self) -> List[str]:
+ # call once to get number of available enum names
+ num_found = c_uint32(-1)
+ error = vimba_c.vmb_feature_enum_range_query(self._handle,
+ self._name,
+ None,
+ 0,
+ byref(num_found))
+ if error:
+ raise VimbaException(error)
+
+ # call again to get the actual enum names
+ num_enum_names = num_found.value
+ enum_names = (c_char_p * num_enum_names)()
+ error = vimba_c.vmb_feature_enum_range_query(self._handle,
+ self._name,
+ enum_names,
+ num_enum_names,
+ byref(num_found))
+ if error:
+ raise VimbaException(error)
+
+ return list(enum_name.decode() for enum_name in enum_names)
diff --git a/pymba/frame.py b/pymba/frame.py
new file mode 100644
index 0000000..5f9bcda
--- /dev/null
+++ b/pymba/frame.py
@@ -0,0 +1,127 @@
+from ctypes import byref, sizeof, addressof, create_string_buffer, cast, POINTER, c_ubyte, c_void_p
+from typing import Optional, Callable
+import numpy as np
+
+from . import camera as _camera
+from .vimba_exception import VimbaException
+from . import vimba_c
+
+
+class MemoryBlock:
+ """
+ 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, block_size):
+ self._block = create_string_buffer(block_size)
+
+ # this seems to be None if too much memory is requested
+ if self._block is None:
+ raise VimbaException(VimbaException.ERR_FRAME_BUFFER_MEMORY)
+
+
+class Frame:
+ """
+ A Vimba frame.
+ """
+
+ def __init__(self, camera: '_camera.Camera'):
+ self._camera = camera
+
+ self._vmb_frame = vimba_c.VmbFrame()
+
+ self._c_mem = None
+ self._frame_callback = None
+ self._frame_callback_wrapper_c = None
+
+ def announce(self) -> None:
+ """
+ Announce frames to the API that may be queued for frame capturing later. Should be called after the frame is
+ created. Call startCapture after this method.
+ """
+ # keep this reference to keep block alive for life of frame
+ self._c_mem = MemoryBlock(self._camera.PayloadSize)
+
+ # set buffer to have length of expected payload size
+ self._vmb_frame.buffer = self._c_mem.block
+
+ # set buffer size to expected payload size
+ self._vmb_frame.bufferSize = self._camera.PayloadSize
+
+ error = vimba_c.vmb_frame_announce(self._camera.handle,
+ byref(self._vmb_frame),
+ sizeof(self._vmb_frame))
+ if error:
+ raise VimbaException(error)
+
+ def revoke(self) -> None:
+ """
+ Revoke a frame from the API.
+ """
+ error = vimba_c.vmb_frame_revoke(self._camera.handle,
+ byref(self._vmb_frame))
+ if error:
+ raise VimbaException(error)
+
+ def queue_for_capture(self, frame_callback: Optional[Callable] = None) -> None:
+ """
+ Queue frames that may be filled during frame capturing. Call after announceFrame and startCapture. Callback
+ must accept argument of type frame. Remember to requeue the frame by calling frame.queue_capture() at the end
+ of your callback function.
+ """
+ self._frame_callback = frame_callback
+
+ # define a callback wrapper here so it doesn't bind self
+ def frame_callback_wrapper(camera_handle, frame_ptr):
+ # 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._frame_callback(self)
+
+ if self._frame_callback is None:
+ self._frame_callback_wrapper_c = None
+ else:
+ # keep a reference to prevent gc issues
+ self._frame_callback_wrapper_c = vimba_c.vmb_frame_callback_func(frame_callback_wrapper)
+
+ error = vimba_c.vmb_capture_frame_queue(self._camera.handle,
+ byref(self._vmb_frame),
+ self._frame_callback_wrapper_c)
+ if error:
+ raise VimbaException(error)
+
+ def wait_for_capture(self, timeout_ms: Optional[int] = 2000) -> None:
+ """
+ Wait for a queued frame to be filled (or dequeued). Call after an acquisition command.
+ :param timeout_ms: time out in milliseconds.
+ """
+ error = vimba_c.vmb_capture_frame_wait(self._camera.handle,
+ byref(self._vmb_frame),
+ timeout_ms)
+ if error:
+ raise VimbaException(error)
+
+ def image_pointer(self):
+ """
+ Get a pointer to the frame's image data as a ctypes c_ubyte array pointer.
+ """
+ return cast(self._vmb_frame.buffer, POINTER(c_ubyte * self._vmb_frame.bufferSize))
+
+ def image_buffer(self):
+ """
+ Get a copy of the frame's image data as a ctypes c_ubyte array.
+ """
+ return self.image_pointer().contents
+
+ def image_numpy_array(self) -> np.ndarray:
+ """
+ Get the frame's image data as a NumPy array, which can be used with OpenCV.
+ """
+ # todo pixel formats larger than 8-bit
+
+ return np.ndarray(buffer=self.image_buffer(),
+ dtype=np.uint8,
+ shape=(self._vmb_frame.height, self._vmb_frame.width))
diff --git a/pymba/interface.py b/pymba/interface.py
new file mode 100644
index 0000000..fdd4675
--- /dev/null
+++ b/pymba/interface.py
@@ -0,0 +1,92 @@
+from ctypes import byref, sizeof, c_uint32
+from typing import List
+
+from .vimba_object import VimbaObject
+from .vimba_exception import VimbaException
+from . import vimba_c
+
+
+def _interface_infos() -> List[vimba_c.VmbInterfaceInfo]:
+ """
+ Gets interface info of all available interfaces.
+ """
+ # call once just to get the number of interfaces
+ num_found = c_uint32(-1)
+ error = vimba_c.vmb_interfaces_list(None,
+ 0,
+ byref(num_found),
+ sizeof(vimba_c.VmbInterfaceInfo))
+ if error:
+ raise VimbaException(error)
+
+ # call again to get the features
+ num_interfaces = num_found.value
+ vmb_interface_infos = (vimba_c.VmbInterfaceInfo * num_interfaces)()
+ error = vimba_c.vmb_interfaces_list(vmb_interface_infos,
+ num_interfaces,
+ byref(num_found),
+ sizeof(vimba_c.VmbInterfaceInfo))
+ if error:
+ raise VimbaException(error)
+
+ return list(vmb_interface_info for vmb_interface_info in vmb_interface_infos)
+
+
+def _interface_info(interface_id: str) -> vimba_c.VmbInterfaceInfo:
+ """
+ Gets interface info object of specified interface.
+ :param interface_id: the ID of the interface object to get.
+ """
+ for vmb_interface_info in _interface_infos():
+ if interface_id == vmb_interface_info.interfaceIdString.decode():
+ return vmb_interface_info
+ raise VimbaException(VimbaException.ERR_INSTANCE_NOT_FOUND)
+
+
+def interface_ids() -> List[str]:
+ """
+ Gets IDs of all available interfaces.
+ """
+ return list(vmb_interface_info.interfaceIdString.decode()
+ for vmb_interface_info in _interface_infos())
+
+
+class Interface(VimbaObject):
+ """
+ A Vimba interface object. This class provides the minimal access
+ to Vimba functions required to control the interface.
+ """
+
+ def __init__(self, interface_id: str):
+ if interface_id not in interface_ids():
+ raise VimbaException(VimbaException.ERR_INSTANCE_NOT_FOUND)
+ self._interface_id = interface_id
+ super().__init__()
+
+ @property
+ def interface_id(self):
+ return self._interface_id
+
+ @property
+ def info(self) -> vimba_c.VmbInterfaceInfo:
+ """
+ Get info of the interface. Does not require the interface to be opened.
+ """
+ return _interface_info(self.interface_id)
+
+ def open(self):
+ """
+ Open the interface.
+ """
+ error = vimba_c.vmb_interface_open(self.interface_id.encode(),
+ byref(self._handle))
+ if error:
+ raise VimbaException(error)
+
+ def close(self):
+ """
+ Close the interface.
+ """
+ error = vimba_c.vmb_interface_close(self._handle)
+ if error:
+ raise VimbaException(error)
diff --git a/pymba/system.py b/pymba/system.py
new file mode 100644
index 0000000..2cc6870
--- /dev/null
+++ b/pymba/system.py
@@ -0,0 +1,9 @@
+from .vimba_object import VimbaObject
+
+
+class System(VimbaObject):
+ """
+ A Vimba system object. This class provides the minimal access to Vimba functions required to control the system.
+ """
+ def __init__(self):
+ super().__init__(handle=1)
diff --git a/pymba/vimba.py b/pymba/vimba.py
index 5656b7c..02c29c7 100644
--- a/pymba/vimba.py
+++ b/pymba/vimba.py
@@ -1,49 +1,41 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-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 *
+from ctypes import sizeof
+from typing import List, Union
+from .vimba_exception import VimbaException
+from .system import System
+from .interface import Interface, interface_ids
+from .camera import Camera, camera_ids
+from . import vimba_c
-class Vimba(object):
+class Vimba:
"""
- An Allied Vision Technology Vimba API.
- This API provides access to AVT cameras.
+ Python wrapper for Allied Vision's Vimba C API.
"""
- # todo - assign camera info and feature info as own object proeprties
+ @staticmethod
+ def version() -> str:
+ """
+ Retrieve the version number of the Vimba C API.
+ """
+ vmb_version_info = vimba_c.VmbVersionInfo()
+ error = vimba_c.vmb_version_query(vmb_version_info, sizeof(vmb_version_info))
+ if error:
+ raise VimbaException(error)
+
+ return '.'.join(str(x) for x in (vmb_version_info.major,
+ vmb_version_info.minor,
+ vmb_version_info.patch))
def __init__(self):
-
# create own system singleton object
- self._system = VimbaSystem()
-
- # lists of VimbaCameraInfo and VimbaInterfaceInfo objects
- # can't be called before startup() so populate later
- self._interfaceInfos = None
-
- # dict of {camera ID : VimbaCamera object} as we don't want to forget
- # them
- self._cameras = {}
-
- # dict of {interface ID : VimbaInterface object} as we don't want to
- # forget them
+ self._system = System()
self._interfaces = {}
+ self._cameras = {}
def __enter__(self):
"""
Define vimba context for safe execution.
-
- The vimba object should be used like this:
- # start Vimba
- with Vimba() as vimba:
- system = vimba.getSystem()
- # ...
"""
self.startup()
return self
@@ -56,220 +48,66 @@ class Vimba(object):
"""
self.shutdown()
- def _getInterfaceInfos(self):
+ def startup(self):
"""
- Gets interface info of all available interfaces.
-
- :returns: list -- interface info for available interfaces.
+ Initialize the Vimba C API.
"""
- if self._interfaceInfos is None:
- # args
- numFound = c_uint32(-1)
-
- # call once just to get the number of interfaces
- # Vimba DLL will return an error code
- errorCode = VimbaDLL.interfacesList(None,
- 0,
- byref(numFound),
- sizeof(structs.VimbaInterfaceInfo))
- if errorCode != 0:
- raise VimbaException(errorCode)
+ error = vimba_c.vmb_startup()
+ if error:
+ raise VimbaException(error)
- numInterfaces = numFound.value
+ # automatically check for the presence of a GigE transport layer
+ if self.system().GeVTLIsPresent:
+ self.system().run_feature_command('GeVDiscoveryAllOnce')
- # args
- interfaceInfoArray = (structs.VimbaInterfaceInfo * numInterfaces)()
-
- # call again to get the features
- # Vimba DLL will return an error code
- errorCode = VimbaDLL.interfacesList(interfaceInfoArray,
- numInterfaces,
- byref(numFound),
- sizeof(structs.VimbaInterfaceInfo))
- if errorCode != 0:
- raise VimbaException(errorCode)
- self._interfaceInfos = list(
- interfaceInfo for interfaceInfo in interfaceInfoArray)
- return self._interfaceInfos
-
- def _getCameraInfos(self):
+ @staticmethod
+ def shutdown():
"""
- Gets camera info of all attached cameras.
-
- :returns: list -- camera info for available cameras.
+ Perform a shutdown on the API.
"""
- # args
- dummyCameraInfo = structs.VimbaCameraInfo()
- numFound = c_uint32(-1)
-
- # call once just to get the number of cameras
- # Vimba DLL will return an error code
- errorCode = VimbaDLL.camerasList(byref(dummyCameraInfo),
- 0,
- byref(numFound),
- sizeof(dummyCameraInfo))
- if errorCode != 0 and errorCode != -9:
- raise VimbaException(errorCode)
-
- numCameras = numFound.value
-
- # args
- cameraInfoArray = (structs.VimbaCameraInfo * numCameras)()
+ vimba_c.vmb_shutdown()
- # call again to get the features
- # Vimba DLL will return an error code
- errorCode = VimbaDLL.camerasList(cameraInfoArray,
- numCameras,
- byref(numFound),
- sizeof(dummyCameraInfo))
- if errorCode != 0:
- raise VimbaException(errorCode)
- return list(camInfo for camInfo in cameraInfoArray)
-
- def getSystem(self):
+ def system(self) -> System:
"""
- Gets system singleton object.
-
- :returns: VimbaSystem object -- the system singleton object.
+ Get the system object.
"""
return self._system
- def getInterfaceIds(self):
- """
- Gets IDs of all available interfaces.
+ @staticmethod
+ def interface_ids():
+ return interface_ids()
- :returns: list -- interface IDs for available interfaces.
+ def interface(self, interface_id: Union[str, int]) -> Interface:
"""
- return list(interfaceInfo.interfaceIdString for interfaceInfo in self._getInterfaceInfos())
-
- def getCameraIds(self):
+ Gets interface object based on interface ID string or index. Will not recreate interface object if it already exists.
+ :param interface_id: the ID or the index of the interface.
"""
- Gets IDs of all available cameras.
+ # if index is provided, look up the camera id using the index
+ if isinstance(interface_id, int):
+ interface_id = interface_ids()[interface_id]
- :returns: list -- camera IDs for available cameras.
- """
- return list(camInfo.cameraIdString.decode() for camInfo in self._getCameraInfos())
-
- def getInterfaceInfo(self, interfaceId):
- """
- Gets interface info object of specified interface.
+ if interface_id in self._interfaces:
+ return self._interfaces[interface_id]
+ interface = Interface(interface_id)
+ self._interfaces[interface_id] = interface
+ return interface
- :param interfaceId: the ID of the interface object to get.
+ @staticmethod
+ def camera_ids() -> List[str]:
+ return camera_ids()
- :returns: VimbaInterfaceInfo object -- the interface info object specified.
+ def camera(self, camera_id: Union[str, int]) -> Camera:
"""
- # don't do this live as we already have this info
- # return info object if it exists
- for interfaceInfo in self._getInterfaceInfos():
- if interfaceInfo.interfaceIdString == interfaceId:
- return interfaceInfo
- # otherwise raise error
- raise VimbaException(-54)
-
- def getCameraInfo(self, cameraId):
- """
- Gets camera info object of specified camera.
-
- :param cameraId: the ID of the camera object to get.
- This might not only be a cameraId as returned by getCameraIds()
- but also e.g. a serial number. Check the Vimba documentation for
- other possible values.
-
- :returns: VimbaCameraInfo object -- the camera info object specified.
- """
- cameraInfo = structs.VimbaCameraInfo()
- errorCode = VimbaDLL.cameraInfoQuery(cameraId.encode(),
- cameraInfo,
- sizeof(cameraInfo))
- if errorCode == 0:
- return cameraInfo
-
- # otherwise raise error
- raise VimbaException(-50)
-
- def getInterface(self, interfaceId):
- """
- Gets interface object based on interface ID string. Will not recreate
- interface object if it already exists.
-
- :param interfaceId: the ID of the interface.
-
- :returns: VimbaInterface object -- the interface object specified.
- """
- # check ID is valid
- if interfaceId in self.getInterfaceIds():
- # create it if it doesn't exist
- if interfaceId not in self._interfaces:
- self._interfaces[interfaceId] = VimbaInterface(interfaceId)
- return self._interfaces[interfaceId]
- raise VimbaException(-54)
-
- def getCamera(self, cameraId):
- """
- Gets camera object based on camera ID string. Will not recreate
- camera object if it already exists.
-
- :param cameraId: the ID of the camera object to get.
- This might not only be a cameraId as returned by getCameraIds()
- but also e.g. a serial number. Check the Vimba documentation for
- other possible values.
-
- :returns: VimbaCamera object -- the camera object specified.
- """
- # check ID is valid
- if cameraId in self.getCameraIds():
- # create it if it doesn't exist
- if cameraId not in self._cameras:
- self._cameras[cameraId] = VimbaCamera(cameraId)
- return self._cameras[cameraId]
- else:
- # the given string might not be a camera ID -> check for other IDs
- cameraInfo = structs.VimbaCameraInfo()
- errorCode = VimbaDLL.cameraInfoQuery(cameraId.encode(),
- cameraInfo,
- sizeof(cameraInfo))
- if errorCode != 0:
- raise VimbaException(-50) # camera not found
-
- cameraIdString = cameraInfo.cameraIdString.decode()
- if cameraIdString not in self._cameras:
- self._cameras[cameraIdString] = VimbaCamera(cameraIdString)
- return self._cameras[cameraIdString]
-
-
- def getVersion(self):
- """
- Retrieve the version number of VimbaC.
-
- :returns: string - Vimba API version info.
- """
- # args
- versionInfo = structs.VimbaVersion()
-
- # Vimba DLL will return an error code
- errorCode = VimbaDLL.versionQuery(
- versionInfo,
- sizeof(versionInfo)
- )
- if errorCode:
- raise VimbaException(errorCode)
-
- versionStr = '.'.join([str(versionInfo.major),
- str(versionInfo.minor),
- str(versionInfo.patch)])
- return versionStr
-
- def startup(self):
- """
- Initialize the VimbaC API.
+ Gets camera object based on camera ID string or index. Will not recreate camera object if it already exists.
+ :param camera_id: the ID or the index of the camera object to get. This can be an ID or e.g. a serial number.
+ Check the Vimba documentation for other possible values.
"""
- # Vimba DLL will return an error code
- errorCode = VimbaDLL.startup()
- if errorCode != 0:
- raise VimbaException(errorCode)
+ # if index is provided, look up the camera id using the index
+ if isinstance(camera_id, int):
+ camera_id = camera_ids()[camera_id]
- def shutdown(self):
- """
- Perform a shutdown on the API.
- """
- VimbaDLL.shutdown()
+ if camera_id in self._cameras:
+ return self._cameras[camera_id]
+ camera = Camera(camera_id)
+ self._cameras[camera_id] = camera
+ return camera
diff --git a/pymba/vimba_c.py b/pymba/vimba_c.py
new file mode 100644
index 0000000..034df6e
--- /dev/null
+++ b/pymba/vimba_c.py
@@ -0,0 +1,430 @@
+from sys import platform as sys_plat
+import platform
+import os
+from ctypes import *
+
+
+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":
+ CALLBACK_FUNCTYPE = WINFUNCTYPE
+else:
+ CALLBACK_FUNCTYPE = CFUNCTYPE
+
+
+class NiceStructure(Structure):
+ def __repr__(self):
+ field_names = (field[0] for field in self._fields_)
+ return f'{type(self).__name__}(' \
+ f'{", ".join("=".join((field, str(getattr(self, field)))) for field in field_names)})'
+
+
+class VmbVersionInfo(NiceStructure):
+ _fields_ = [
+ ('major', c_uint32),
+ ('minor', c_uint32),
+ ('patch', c_uint32)]
+
+
+class VmbInterfaceInfo(NiceStructure):
+ _fields_ = [
+ # Unique identifier for each interface
+ ('interfaceIdString', c_char_p),
+ # Interface type, see VmbInterfaceType
+ ('interfaceType', c_uint32),
+ # Interface name, given by the transport layer
+ ('interfaceName', c_char_p),
+ # Serial number
+ ('serialString', c_char_p),
+ # Used access mode, see VmbAccessModeType
+ ('permittedAccess', c_uint32)]
+
+
+class VmbCameraInfo(NiceStructure):
+ _fields_ = [
+ # Unique identifier for each camera
+ ('cameraIdString', c_char_p),
+ # Name of the camera
+ ('cameraName', c_char_p),
+ # Model name
+ ('modelName', c_char_p),
+ # Serial number
+ ('serialString', c_char_p),
+ # Used access mode, see VmbAccessModeType
+ ('permittedAccess', c_uint32),
+ # Unique value for each interface or bus
+ ('interfaceIdString', c_char_p)]
+
+
+class VmbFeatureInfo(NiceStructure):
+ _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)]
+
+
+class VmbFrame(Structure):
+ _fields_ = [
+ # ---- IN ----
+ # Comprises image and ancillary data
+ ('buffer', c_void_p),
+ # Size of the data buffer
+ ('bufferSize', c_uint32),
+
+ # 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 of an image
+ ('width', c_uint32),
+ # Height of an image
+ ('height', c_uint32),
+ # 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 of the data transfer
+ ('timestamp', c_uint64)]
+
+
+_vimba_lib = dll_loader.LoadLibrary(vimbaC_path)
+
+# ----- The below function signatures are defined in VimbaC.h -----
+
+# callback for frame queue
+vmb_frame_callback_func = CALLBACK_FUNCTYPE(c_void_p,
+ c_void_p,
+ POINTER(VmbFrame))
+
+vmb_version_query = _vimba_lib.VmbVersionQuery
+vmb_version_query.restype = c_int32
+vmb_version_query.argtypes = (POINTER(VmbVersionInfo),
+ c_uint32)
+
+vmb_startup = _vimba_lib.VmbStartup
+vmb_startup.restype = c_int32
+
+vmb_shutdown = _vimba_lib.VmbShutdown
+
+vmb_cameras_list = _vimba_lib.VmbCamerasList
+vmb_cameras_list.restype = c_int32
+vmb_cameras_list.argtypes = (POINTER(VmbCameraInfo),
+ c_uint32,
+ POINTER(c_uint32),
+ c_uint32)
+
+vmb_camera_info_query = _vimba_lib.VmbCameraInfoQuery
+vmb_camera_info_query.restype = c_int32
+vmb_camera_info_query.argtypes = (c_char_p,
+ POINTER(VmbCameraInfo),
+ c_uint32)
+
+vmb_camera_open = _vimba_lib.VmbCameraOpen
+vmb_camera_open.restype = c_int32
+vmb_camera_open.argtypes = (c_char_p,
+ c_uint32,
+ c_void_p)
+
+vmb_camera_close = _vimba_lib.VmbCameraClose
+vmb_camera_close.restype = c_int32
+vmb_camera_close.argtypes = (c_void_p,)
+
+vmb_features_list = _vimba_lib.VmbFeaturesList
+vmb_features_list.restype = c_int32
+vmb_features_list.argtypes = (c_void_p,
+ POINTER(VmbFeatureInfo),
+ c_uint32,
+ POINTER(c_uint32),
+ c_uint32)
+
+vmb_feature_info_query = _vimba_lib.VmbFeatureInfoQuery
+vmb_feature_info_query.restype = c_int32
+vmb_feature_info_query.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(VmbFeatureInfo),
+ c_uint32)
+
+# todo VmbFeatureListAffected
+# todo VmbFeatureListSelected
+# todo VmbFeatureAccessQuery
+
+vmb_feature_int_get = _vimba_lib.VmbFeatureIntGet
+vmb_feature_int_get.restype = c_int32
+vmb_feature_int_get.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_int64))
+
+vmb_feature_int_set = _vimba_lib.VmbFeatureIntSet
+vmb_feature_int_set.restype = c_int32
+vmb_feature_int_set.argtypes = (c_void_p,
+ c_char_p,
+ c_int64)
+
+vmb_feature_int_range_query = _vimba_lib.VmbFeatureIntRangeQuery
+vmb_feature_int_range_query.restype = c_int32
+vmb_feature_int_range_query.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_int64),
+ POINTER(c_int64))
+
+# todo VmbFeatureIntIncrementQuery
+
+vmb_feature_float_get = _vimba_lib.VmbFeatureFloatGet
+vmb_feature_float_get.restype = c_int32
+vmb_feature_float_get.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_double))
+
+vmb_feature_float_set = _vimba_lib.VmbFeatureFloatSet
+vmb_feature_float_set.restype = c_int32
+vmb_feature_float_set.argtypes = (c_void_p,
+ c_char_p,
+ c_double)
+
+vmb_feature_float_range_query = _vimba_lib.VmbFeatureFloatRangeQuery
+vmb_feature_float_range_query.restype = c_int32
+vmb_feature_float_range_query.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_double),
+ POINTER(c_double))
+
+# todo VmbFeatureFloatIncrementQuery
+
+vmb_feature_enum_get = _vimba_lib.VmbFeatureEnumGet
+vmb_feature_enum_get.restype = c_int32
+vmb_feature_enum_get.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_char_p))
+
+vmb_feature_enum_set = _vimba_lib.VmbFeatureEnumSet
+vmb_feature_enum_set.restype = c_int32
+vmb_feature_enum_set.argtypes = (c_void_p,
+ c_char_p,
+ c_char_p)
+
+vmb_feature_enum_range_query = _vimba_lib.VmbFeatureEnumRangeQuery
+vmb_feature_enum_range_query.restype = c_int32
+vmb_feature_enum_range_query.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_char_p),
+ c_uint32,
+ POINTER(c_uint32))
+
+# todo VmbFeatureEnumIsAvailable
+# todo VmbFeatureEnumAsInt
+# todo VmbFeatureEnumAsString
+# todo VmbFeatureEnumEntryGet
+
+vmb_feature_string_get = _vimba_lib.VmbFeatureStringGet
+vmb_feature_string_get.restype = c_int32
+vmb_feature_string_get.argtypes = (c_void_p,
+ c_char_p,
+ c_char_p,
+ c_uint32,
+ POINTER(c_uint32))
+
+vmb_feature_string_set = _vimba_lib.VmbFeatureStringSet
+vmb_feature_string_set.restype = c_int32
+vmb_feature_string_set.argtypes = (c_void_p,
+ c_char_p,
+ c_char_p)
+
+# todo VmbFeatureStringMaxlengthQuery
+
+vmb_feature_bool_get = _vimba_lib.VmbFeatureBoolGet
+vmb_feature_bool_get.restype = c_int32
+vmb_feature_bool_get.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_bool))
+
+vmb_feature_bool_set = _vimba_lib.VmbFeatureBoolSet
+vmb_feature_bool_set.restype = c_int32
+vmb_feature_bool_set.argtypes = (c_void_p,
+ c_char_p,
+ c_bool)
+
+vmb_feature_command_run = _vimba_lib.VmbFeatureCommandRun
+vmb_feature_command_run.restype = c_int32
+vmb_feature_command_run.argtypes = (c_void_p,
+ c_char_p)
+
+vmb_feature_command_is_done = _vimba_lib.VmbFeatureCommandIsDone
+vmb_feature_command_is_done.restype = c_int32
+vmb_feature_command_is_done.argtypes = (c_void_p,
+ c_char_p,
+ POINTER(c_bool))
+
+# todo VmbFeatureRawGet
+# todo VmbFeatureRawSet
+# todo VmbFeatureRawLengthQuery
+# todo VmbFeatureInvalidationRegister
+# todo VmbFeatureInvalidationUnregister
+
+vmb_frame_announce = _vimba_lib.VmbFrameAnnounce
+vmb_frame_announce.restype = c_int32
+vmb_frame_announce.argtypes = (c_void_p,
+ POINTER(VmbFrame),
+ c_uint32)
+
+vmb_frame_revoke = _vimba_lib.VmbFrameRevoke
+vmb_frame_revoke.restype = c_int32
+vmb_frame_revoke.argtypes = (c_void_p,
+ POINTER(VmbFrame))
+
+vmb_frame_revoke_all = _vimba_lib.VmbFrameRevokeAll
+vmb_frame_revoke_all.restype = c_int32
+vmb_frame_revoke_all.argtypes = (c_void_p,)
+
+vmb_capture_start = _vimba_lib.VmbCaptureStart
+vmb_capture_start.restype = c_int32
+vmb_capture_start.argtypes = (c_void_p,)
+
+vmb_capture_end = _vimba_lib.VmbCaptureEnd
+vmb_capture_end.restype = c_int32
+vmb_capture_end.argtypes = (c_void_p,)
+
+vmb_capture_frame_queue = _vimba_lib.VmbCaptureFrameQueue
+vmb_capture_frame_queue.restype = c_int32
+vmb_capture_frame_queue.argtypes = (c_void_p,
+ POINTER(VmbFrame),
+ c_void_p)
+
+vmb_capture_frame_wait = _vimba_lib.VmbCaptureFrameWait
+vmb_capture_frame_wait.restype = c_int32
+vmb_capture_frame_wait.argtypes = (c_void_p,
+ POINTER(VmbFrame),
+ c_uint32)
+
+vmb_capture_queue_flush = _vimba_lib.VmbCaptureQueueFlush
+vmb_capture_queue_flush.restype = c_int32
+vmb_capture_queue_flush.argtypes = (c_void_p,)
+
+vmb_interfaces_list = _vimba_lib.VmbInterfacesList
+vmb_interfaces_list.restype = c_int32
+vmb_interfaces_list.argtypes = (POINTER(VmbInterfaceInfo),
+ c_uint32,
+ POINTER(c_uint32),
+ c_uint32)
+
+vmb_interface_open = _vimba_lib.VmbInterfaceOpen
+vmb_interface_open.restype = c_int32
+vmb_interface_open.argtypes = (c_char_p,
+ c_void_p)
+
+vmb_interface_close = _vimba_lib.VmbInterfaceClose
+vmb_interface_close.restype = c_int32
+vmb_interface_close.argtypes = (c_void_p,)
+
+# todo VmbAncillaryDataOpen
+# todo VmbAncillaryDataClose
+# todo VmbMemoryRead
+# todo VmbMemoryWrite
+# todo VmbAncillaryDataOpen
+
+vmb_registers_read = _vimba_lib.VmbRegistersRead
+vmb_registers_read.restype = c_int32
+vmb_registers_read.argtypes = (c_void_p,
+ c_uint32,
+ POINTER(c_uint64),
+ POINTER(c_uint64),
+ POINTER(c_uint32))
+
+vmb_registers_write = _vimba_lib.VmbRegistersWrite
+vmb_registers_write.restype = c_int32
+vmb_registers_write.argtypes = (c_void_p,
+ c_uint32,
+ POINTER(c_uint64),
+ POINTER(c_uint64),
+ POINTER(c_uint32))
+
+# todo VmbCameraSettingsSave
+# todo VmbCameraSettingsLoad
diff --git a/pymba/vimba_camera.py b/pymba/vimba_camera.py
deleted file mode 100644
index 5e131a1..0000000
--- a/pymba/vimba_camera.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# -*- 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
deleted file mode 100644
index a62b087..0000000
--- a/pymba/vimba_dll.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 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
index ac6abee..22f03c2 100644
--- a/pymba/vimba_exception.py
+++ b/pymba/vimba_exception.py
@@ -1,58 +1,71 @@
class VimbaException(Exception):
+ ERROR_CODES = (
+ # 0
+ ERR_NO_ERROR,
- """
- An exception for the AVT Vimba API. It contains a message
- property which is a string indicating what went wrong.
+ # -1 to -19
+ ERR_UNEXPECTED_FAULT,
+ ERR_STARTUP_NOT_CALLED,
+ ERR_INSTANCE_NOT_FOUND,
+ ERR_HANDLE_INVALID,
+ ERR_DEVICE_NOT_OPENED,
+ ERR_OPERATION_INVALID_FOR_ACCESS_MODE,
+ ERR_PARAMETER_INVALID,
+ ERR_STRUCT_SIZE_INVALID,
+ ERR_DATA_TOO_LARGE,
+ ERR_FEATURE_TYPE_WRONG,
+ ERR_VALUE_INVALID,
+ ERR_TIMEOUT,
+ ERR_OTHER_ERROR,
+ ERR_RESOURCE_NOT_AVAILABLE,
+ ERR_CALL_INVALID,
+ ERR_TRANSPORT_LAYER_NOT_FOUND,
+ ERR_FEATURE_NOT_IMPLEMENTED,
+ ERR_FEATURE_NOT_SUPPORTED,
+ ERR_PARTIAL_REGISTER_ACCESS,
- :param errorCode: Error code to be used to look up error message.
- """
+ # -50 to -56
+ ERR_FRAME_BUFFER_MEMORY,
+ ERR_NOT_IMPLEMENTED_IN_PYMBA,
+ ERR_UNDEFINED_ERROR_CODE,
+ ) = tuple(range(0, -20, -1)) + tuple(range(-50, -53, -1))
- @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.',
+ ERRORS = {
+ # Vimba C API specific errors
+ ERR_NO_ERROR: 'No error.',
+ ERR_UNEXPECTED_FAULT: 'Unexpected fault in VimbaC or driver.',
+ ERR_STARTUP_NOT_CALLED: 'VmbStartup() was not called before the current command.',
+ ERR_INSTANCE_NOT_FOUND: 'The designated instance (camera, feature etc.) cannot be found.',
+ ERR_HANDLE_INVALID: 'The given handle is not valid, ensure device open.',
+ ERR_DEVICE_NOT_OPENED: 'Device was not opened for usage.',
+ ERR_OPERATION_INVALID_FOR_ACCESS_MODE: 'Operation is invalid with the current access mode.',
+ ERR_PARAMETER_INVALID: 'One of the parameters was invalid (usually an illegal pointer).',
+ ERR_STRUCT_SIZE_INVALID: 'The given struct size is not valid for this version of the API.',
+ ERR_DATA_TOO_LARGE: 'More data was returned in a string/list than space was provided.',
+ ERR_FEATURE_TYPE_WRONG: 'The feature type for this access function was wrong.',
+ ERR_VALUE_INVALID: 'The value was not valid; either out of bounds or not an increment of the minimum.',
+ ERR_TIMEOUT: 'Timeout during wait.',
+ ERR_OTHER_ERROR: 'Other error.',
+ ERR_RESOURCE_NOT_AVAILABLE: 'Resources not available (e.g. memory).',
+ ERR_CALL_INVALID: 'Call is invalid in the current context (e.g. callback).',
+ ERR_TRANSPORT_LAYER_NOT_FOUND: 'No transport layers were found.',
+ ERR_FEATURE_NOT_IMPLEMENTED: 'API feature is not implemented.',
+ ERR_FEATURE_NOT_SUPPORTED: 'API feature is not supported.',
+ ERR_PARTIAL_REGISTER_ACCESS: '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.',
+ ERR_FRAME_BUFFER_MEMORY: 'Not enough memory to assign frame buffer.',
+ ERR_NOT_IMPLEMENTED_IN_PYMBA: 'This function is not yet implemented in Pymba',
+ ERR_UNDEFINED_ERROR_CODE: 'Undefined error code',
+ }
- # Miscellaneous errors
- -1000: 'Oops, unknown internal error code!',
- -1001: 'Oops, this VimbaFeature function is not yet implemented in pymba!'}
+ @property
+ def message(self):
+ return self.ERRORS[self.error_code]
- 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
+ def __init__(self, error_code: int):
+ if error_code not in self.ERROR_CODES:
+ error_code = self.ERR_UNDEFINED_ERROR_CODE
+ self.error_code = error_code
- super(VimbaException, self).__init__(self.message)
+ super().__init__(self.message)
diff --git a/pymba/vimba_feature.py b/pymba/vimba_feature.py
deleted file mode 100644
index 3e838f0..0000000
--- a/pymba/vimba_feature.py
+++ /dev/null
@@ -1,341 +0,0 @@
-# -*- 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
deleted file mode 100644
index 8cf0c86..0000000
--- a/pymba/vimba_frame.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# -*- 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
- imagebytes = int(self.height * self.width * self.pixel_bytes)
- array = (c_ubyte * imagebytes).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
-
- def getTimestamp(self):
- return self._frame.timestamp
-
- def getReceiveStatus(self):
- return self._frame.receiveStatus
diff --git a/pymba/vimba_interface.py b/pymba/vimba_interface.py
deleted file mode 100644
index df5acdc..0000000
--- a/pymba/vimba_interface.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- 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
index 5f1cead..174fe9a 100644
--- a/pymba/vimba_object.py
+++ b/pymba/vimba_object.py
@@ -1,228 +1,162 @@
-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from . import vimba_structure as structs
+from ctypes import byref, sizeof, c_void_p, c_uint32, c_uint64, c_bool
+from typing import List, Optional
+
from .vimba_exception import VimbaException
-from .vimba_feature import VimbaFeature
-from .vimba_dll import VimbaDLL
-from ctypes import *
+from .feature import Feature
+from . import vimba_c
-class VimbaObject(object):
+class VimbaObject:
"""
- A Vimba object has a handle and features associated with it.
- Objects include System, Camera, Interface and AncillaryData.
+ A Vimba object has a handle and features associated with it. Objects include System, Camera, Interface and
+ AncillaryData. Features are automatically readable as instance attributes.
"""
- @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.
+ VMB_ACCESS_MODE_NONE = 0
+ VMB_ACCESS_MODE_FULL = 1
+ VMB_ACCESS_MODE_READ = 2
+ VMB_ACCESS_MODE_CONFIG = 4
+ VMB_ACCESS_MODE_LITE = 8
- :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.
+ def __init__(self, handle: Optional[int] = None):
+ self._handle = c_void_p(handle)
+ self._features = {}
- :returns: list -- feature names for available features.
- """
- return list(featInfo.name.decode() for featInfo in self._getFeatureInfos())
+ def __getattr__(self, item: str):
+ # allow direct access to feature values as an attribute
+ if item in self.feature_names():
+ return self.feature(item).value
- def getFeatureInfo(self, featureName):
- """
- Gets feature info object of specified feature.
+ raise AttributeError(f'{self.__class__.__name__} object has no attribute {item}')
+
+ # allow direct access to feature values as an attribute
+ def __setattr__(self, item: str, value):
+ # set privates as normally to avoid recursion errors
+ if item.startswith('_'):
+ super().__setattr__(item, value)
- :param featureName: the name of the feature.
+ # allow direct access to feature values as an attribute
+ elif item in self.feature_names():
+ self.feature(item).value = value
+
+ else:
+ super().__setattr__(item, value)
- :returns: VimbaFeatureInfo object -- the feature info object specified.
+ def _feature_infos(self) -> List[vimba_c.VmbFeatureInfo]:
"""
- # 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):
+ Gets feature info of all available features. Will cause error if object/camera/etc is not opened.
+ """
+ # call once to get number of available features
+ vmb_feature_info = vimba_c.VmbFeatureInfo()
+ num_found = c_uint32(-1)
+ error = vimba_c.vmb_features_list(self._handle,
+ None,
+ 0,
+ byref(num_found),
+ sizeof(vmb_feature_info))
+ if error:
+ raise VimbaException(error)
+
+ # call again to get the features
+ num_features = num_found.value
+ vmb_feature_infos = (vimba_c.VmbFeatureInfo * num_features)()
+ error = vimba_c.vmb_features_list(self._handle,
+ vmb_feature_infos,
+ num_features,
+ byref(num_found),
+ sizeof(vmb_feature_info))
+ if error:
+ raise VimbaException(error)
+
+ return list(vmb_feature_info for vmb_feature_info in vmb_feature_infos)
+
+ def _feature_info(self, feature_name: str) -> vimba_c.VmbFeatureInfo:
+ """
+ Gets feature info object of specified feature.
+ :param feature_name: the name of the feature.
"""
- Get valid range of feature values.
+ for vmb_feature_info in self._feature_infos():
+ if feature_name == vmb_feature_info.name.decode():
+ return vmb_feature_info
+ raise VimbaException(VimbaException.ERR_INSTANCE_NOT_FOUND)
- :param featureName: name of the feature to query.
+ def feature_names(self) -> List[str]:
+ """
+ Get names of all available features.
+ """
+ return list(vmb_feature_info.name.decode()
+ for vmb_feature_info in self._feature_infos())
- :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).
+ def feature(self, feature_name: str) -> Feature:
+ """
+ Gets feature object by name from the corresponding Vimba object.
+ :param feature_name: name of the feature to get.
"""
- # can't cache this, need to look it up live
- return VimbaFeature(featureName, self._handle).range
+ if feature_name in self._features:
+ return self._features[feature_name]
+ feature = Feature(feature_name, self._handle)
+ self._features[feature_name] = feature
+ return feature
- def runFeatureCommand(self, featureName):
+ def run_feature_command(self, feature_name: str) -> None:
"""
Run a feature command.
-
- :param featureName: the name of the feature.
+ :param feature_name: 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
+ error = vimba_c.vmb_feature_command_run(self._handle,
+ feature_name.encode())
+ if error:
+ raise VimbaException(error)
+
+ def feature_command_is_done(self, feature_name: str) -> bool:
+ is_done = c_bool()
+ error = vimba_c.vmb_feature_command_is_done(self._handle,
+ feature_name.encode(),
+ byref(is_done))
+ if error:
+ raise VimbaException(error)
+
+ return is_done.value
+
+ # todo test
+ def read_register(self, address: int) -> int:
+ # 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).
-
+ Read from a register of the module (camera) and return its value.
: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_count = 1
+ reg_address = c_uint64(address)
+ reg_data = c_uint64()
+ num_complete_reads = c_uint32()
+ error = vimba_c.vmb_registers_read(self._handle,
+ read_count,
+ byref(reg_address),
+ byref(reg_data),
+ byref(num_complete_reads))
+ if error:
+ raise VimbaException(error)
+
+ return reg_data.value
+
+ # todo test
+ def write_register(self, address: int, value: int) -> None:
+ # 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).
-
+ Write to 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)
+ write_count = 1
+ reg_address = c_uint64(address)
+ reg_data = c_uint64(value)
+ num_complete_writes = c_uint32()
+ error = vimba_c.vmb_registers_write(self._handle,
+ write_count,
+ byref(reg_address),
+ byref(reg_data),
+ byref(num_complete_writes))
+ if error:
+ raise VimbaException(error)
diff --git a/pymba/vimba_structure.py b/pymba/vimba_structure.py
deleted file mode 100644
index 73c4e96..0000000
--- a/pymba/vimba_structure.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/vimba_system.py b/pymba/vimba_system.py
deleted file mode 100644
index f4d0c54..0000000
--- a/pymba/vimba_system.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- 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/setup.py b/setup.py
index ea18344..429f77f 100644
--- a/setup.py
+++ b/setup.py
@@ -1,30 +1,49 @@
from setuptools import setup
+from pymba import PYMBA_VERSION
-setup(name='pymba',
- version=0.1,
- description="Pymba is a Python wrapper for Allied Vision's Vimba SDK.",
- long_description="Pymba is a Python wrapper for Allied Vision's Vimba SDK. It uses the Vimba C API included in "
- "the Allied Vision Vimba installation to provide a simple Python interface for Allied Vimba "
- "cameras.",
+
+setup(name='Pymba',
+ version=PYMBA_VERSION,
+ description="Pymba is a Python wrapper for Allied Vision's Vimba C API.",
+ long_description="Pymba is a Python wrapper for Allied Vision's Vimba C API. It wraps the VimbaC library file "
+ "included in the Vimba installation to provide a simple Python interface for Allied Vision "
+ "cameras. It currently supports most of the functionality provided by Vimba.",
+ # https://pypi.org/pypi?%3Aaction=list_classifiers
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
- 'Intended Audience :: Science/Research',
+ 'Intended Audience :: End Users/Desktop',
+ 'Intended Audience :: Healthcare Industry',
'Intended Audience :: Manufacturing',
- 'License :: OSI Approved :: GPL-3.0 License',
+ 'Intended Audience :: Science/Research',
+ 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
+ 'Natural Language :: English',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Topic :: Multimedia :: Graphics :: Capture :: Digital Camera',
- 'Topic :: Multimedia :: Graphics :: Graphics Conversion',
+ 'Topic :: Multimedia :: Video :: Capture',
'Topic :: Scientific/Engineering :: Image Recognition',
- 'Topic :: Software Development :: Libraries :: Python Modules'],
- keywords='python, opencv, machine vision, computer vision, image recognition, vimba, vimba-sdk, allied vision',
+ 'Topic :: Scientific/Engineering :: Visualization',
+ 'Topic :: Software Development :: Libraries :: Python Modules'
+ ],
+ keywords='python, python3, opencv, cv, machine vision, computer vision, image recognition, vimba, allied vision',
author='morefigs',
author_email='morefigs@gmail.com',
url='https://github.com/morefigs/pymba',
license='GPL-3.0',
- packages=['pymba'],
+ packages=[
+ 'pymba',
+ 'tests',
+ ],
zip_safe=False,
- requires=['numpy'])
+ install_requires=[
+ 'numpy',
+ ],
+ extras_requires={
+ 'dev': [
+ 'pytest',
+ ]
+ }
+ )
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tests/__init__.py
+++ /dev/null
diff --git a/tests/opencv_example.py b/tests/opencv_example.py
deleted file mode 100644
index 238e8b4..0000000
--- a/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/tests/opencv_liveview_example.py b/tests/opencv_liveview_example.py
deleted file mode 100644
index 78b6b67..0000000
--- a/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/tests/opencv_liveview_example_color.py b/tests/opencv_liveview_example_color.py
deleted file mode 100644
index fd7a819..0000000
--- a/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/tests/test_cameras.py b/tests/test_cameras.py
deleted file mode 100644
index a5a4dd9..0000000
--- a/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/tests/test_enumfeature.py b/tests/test_enumfeature.py
deleted file mode 100644
index 7f9dd4c..0000000
--- a/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/tests/test_installation.py b/tests/test_installation.py
deleted file mode 100644
index 06af7d6..0000000
--- a/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/tests/test_interfaces.py b/tests/test_interfaces.py
deleted file mode 100644
index 270d42c..0000000
--- a/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/tests/test_systemfeature.py b/tests/test_systemfeature.py
deleted file mode 100644
index abb4da7..0000000
--- a/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/tests/test_vimba.py b/tests/test_vimba.py
new file mode 100644
index 0000000..b1ef987
--- /dev/null
+++ b/tests/test_vimba.py
@@ -0,0 +1,52 @@
+import pytest
+
+from pymba import Vimba, VimbaException
+
+
+def test_version():
+ version = Vimba().version.split('.')
+ assert int(version[0]) >= 1
+ assert int(version[1]) >= 7
+ assert int(version[2]) >= 0
+
+
+def test_startup_shutdown():
+ with pytest.raises(VimbaException) as e:
+ Vimba().system().feature_names()
+ assert e.value.error_code == VimbaException.ERR_STARTUP_NOT_CALLED
+
+ # manual
+ Vimba().startup()
+ Vimba().system().feature_names()
+ Vimba().shutdown()
+
+ # context manager
+ with Vimba() as vmb:
+ vmb.system().feature_names()
+
+
+@pytest.fixture
+def vimba() -> Vimba:
+ with Vimba() as vimba:
+ # for ethernet camera discovery
+ if vimba.system().GeVTLIsPresent:
+ vimba.system().run_feature_command("GeVDiscoveryAllOnce")
+ yield vimba
+
+
+def test_interface_camera_ids(vimba: Vimba):
+ # test id funcs return a list of strings (not bytes)
+ for func in (vimba.interface_ids, vimba.camera_ids):
+ ids = func()
+ assert isinstance(ids, list)
+ assert ids
+ for x in ids:
+ assert isinstance(x, str)
+
+
+def test_interface(vimba: Vimba):
+ interface = vimba.interface(vimba.interface_ids()[0])
+
+
+def test_camera(vimba: Vimba):
+ camera = vimba.camera(vimba.camera_ids()[0])