def _setupVimba(self):
        from pymba import Vimba

        self._vimba = Vimba()
        self._vimba.startup()
        system = self._vimba.getSystem()
        if system.GeVTLIsPresent:
            system.runFeatureCommand("GeVDiscoveryAllOnce")
            time.sleep(0.2)
Beispiel #2
0
def test_installation():
    vimba = Vimba()
    version = vimba.getVersion()
    assert version == '1.2.0'
class VimbaCamera(FrameSource):
    """
    **SUMMARY**
    VimbaCamera is a wrapper for the Allied Vision cameras,
    such as the "manta" series.

    This requires the
    1) Vimba SDK provided from Allied Vision
    http://www.alliedvisiontec.com/us/products/software/vimba-sdk.html

    2) Pyvimba Python library
    TODO: <INSERT URL>

    Note that as of time of writing, the VIMBA driver is not available
    for Mac.

    All camera properties are directly from the Vimba SDK manual -- if not
    specified it will default to whatever the camera state is.  Cameras
    can either by

    **EXAMPLE**
    >>> cam = VimbaCamera(0, {"width": 656, "height": 492})
    >>>
    >>> img = cam.getImage()
    >>> img.show()
    """

    def _setupVimba(self):
        from pymba import Vimba

        self._vimba = Vimba()
        self._vimba.startup()
        system = self._vimba.getSystem()
        if system.GeVTLIsPresent:
            system.runFeatureCommand("GeVDiscoveryAllOnce")
            time.sleep(0.2)

    def __del__(self):
        #This function should disconnect from the Vimba Camera
        if self._camera is not None:
            if self.threaded:
                self._thread.stop()
                time.sleep(0.2)

            if self._frame is not None:
                self._frame.revokeFrame()
                self._frame = None

            self._camera.closeCamera()

        self._vimba.shutdown()

    def shutdown(self):
        """You must call this function if you are using threaded=true when you are finished
            to prevent segmentation fault"""
        # REQUIRED TO PREVENT SEGMENTATION FAULT FOR THREADED=True
        if (self._camera):
            self._camera.closeCamera()

        self._vimba.shutdown()


    def __init__(self, camera_id = -1, properties = {}, threaded = False):
        if not VIMBA_ENABLED:
            raise Exception("You don't seem to have the pymba library installed.  This will make it hard to use a AVT Vimba Camera.")

        self._vimba = None
        self._setupVimba()

        camlist = self.listAllCameras()
        self._camTable = {}
        self._frame = None
        self._buffer = None # Buffer to store images
        self._buffersize = 10 # Number of images to keep in the rolling image buffer for threads
        self._lastimage = None # Last image loaded into memory
        self._thread = None
        self._framerate = 0
        self.threaded = False
        self._properties = {}
        self._camera = None

        i = 0
        for cam in camlist:
            self._camTable[i] = {'id': cam.cameraIdString}
            i += 1

        if not len(camlist):
            raise Exception("Couldn't find any cameras with the Vimba driver.  Use VimbaViewer to confirm you have one connected.")

        if camera_id < 9000: #camera was passed as an index reference
            if camera_id == -1:  #accept -1 for "first camera"
                camera_id = 0

            if (camera_id > len(camlist)):
                raise Exception("Couldn't find camera at index %d." % camera_id)

            cam_guid = camlist[camera_id].cameraIdString
        else:
            raise Exception("Index %d is too large" % camera_id)

        self._camera = self._vimba.getCamera(cam_guid)
        self._camera.openCamera()

        self.uniqueid = cam_guid

        self.setProperty("AcquisitionMode","SingleFrame")
        self.setProperty("TriggerSource","Freerun")

        # TODO: FIX
        if properties.get("mode", "RGB") == 'gray':
            self.setProperty("PixelFormat", "Mono8")
        else:
            fmt = "RGB8Packed" # alternatively use BayerRG8
            self.setProperty("PixelFormat", "BayerRG8")

        #give some compatablity with other cameras
        if properties.get("mode", ""):
            properties.pop("mode")

        if properties.get("height", ""):
            properties["Height"] = properties["height"]
            properties.pop("height")

        if properties.get("width", ""):
            properties["Width"] = properties["width"]
            properties.pop("width")

        for p in properties:
            self.setProperty(p, properties[p])

        if threaded:
          self._thread = VimbaCameraThread(self)
          self._thread.daemon = True
          self._buffer = deque(maxlen=self._buffersize)
          self._thread.start()
          self.threaded = True

        self._refreshFrameStats()

    def restart(self):
        """
        This tries to restart the camera thread
        """
        self._thread.stop()
        self._thread = VimbaCameraThread(self)
        self._thread.daemon = True
        self._buffer = deque(maxlen=self._buffersize)
        self._thread.start()

    def listAllCameras(self):
        """
        **SUMMARY**
        List all cameras attached to the host

        **RETURNS**
        List of VimbaCamera objects, otherwise empty list
        VimbaCamera objects are defined in the pymba module
        """
        cameraIds = self._vimba.getCameraIds()
        ar = []
        for cameraId in cameraIds:
            ar.append(self._vimba.getCamera(cameraId))
        return ar

    def runCommand(self,command):
        """
        **SUMMARY**
        Runs a Vimba Command on the camera

        Valid Commands include:
        * AcquisitionAbort
        * AcquisitionStart
        * AcquisitionStop

        **RETURNS**

        0 on success

        **EXAMPLE**
        >>>c = VimbaCamera()
        >>>c.runCommand("TimeStampReset")
        """
        return self._camera.runFeatureCommand(command)

    def getProperty(self, name):
        """
        **SUMMARY**
        This retrieves the value of the Vimba Camera attribute

        There are around 140 properties for the Vimba Camera, so reference the
        Vimba Camera pdf that is provided with
        the SDK for detailed information

        Throws VimbaException if property is not found or not implemented yet.

        **EXAMPLE**
        >>>c = VimbaCamera()
        >>>print c.getProperty("ExposureMode")
        """
        return self._camera.__getattr__(name)

    #TODO, implement the PvAttrRange* functions
    #def getPropertyRange(self, name)

    def getAllProperties(self):
        """
        **SUMMARY**
        This returns a dict with the name and current value of the
        documented Vimba attributes

        CAVEAT: it addresses each of the properties individually, so
        this may take time to run if there's network latency

        **EXAMPLE**
        >>>c = VimbaCamera(0)
        >>>props = c.getAllProperties()
        >>>print props['ExposureMode']

        """
        from pymba import VimbaException

        # TODO
        ar = {}
        c = self._camera
        cameraFeatureNames = c.getFeatureNames()
        for name in cameraFeatureNames:
            try:
                ar[name] =  c.__getattr__(name)
            except VimbaException:
                # Ignore features not yet implemented
                pass
        return ar


    def setProperty(self, name, value, skip_buffer_size_check=False):
        """
        **SUMMARY**
        This sets the value of the Vimba Camera attribute.

        There are around 140 properties for the Vimba Camera, so reference the
        Vimba Camera pdf that is provided with
        the SDK for detailed information

        Throws VimbaException if property not found or not yet implemented

        **Example**
        >>>c = VimbaCamera()
        >>>c.setProperty("ExposureAutoRate", 200)
        >>>c.getImage().show()
        """
        ret = self._camera.__setattr__(name, value)

        #just to be safe, re-cache the camera metadata
        if not skip_buffer_size_check:
            self._refreshFrameStats()

        return ret

    def getImage(self):
        """
        **SUMMARY**
        Extract an Image from the Camera, returning the value.  No matter
        what the image characteristics on the camera, the Image returned
        will be RGB 8 bit depth, if camera is in greyscale mode it will
        be 3 identical channels.

        **EXAMPLE**
        >>>c = VimbaCamera()
        >>>c.getImage().show()
        """

        if self.threaded:
            self._thread.lock.acquire()
            try:
                img = self._buffer.pop()
                self._lastimage = img
            except IndexError:
                img = self._lastimage
            self._thread.lock.release()

        else:
            img = self._captureFrame()

        return img

    def setupASyncMode(self):
        self.setProperty('AcquisitionMode','SingleFrame')
        self.setProperty('TriggerSource','Software')

    def setupSyncMode(self):
        self.setProperty('AcquisitionMode','SingleFrame')
        self.setProperty('TriggerSource','Freerun')

    def _refreshFrameStats(self):
        self.width = self.getProperty("Width")
        self.height = self.getProperty("Height")
        self.pixelformat = self.getProperty("PixelFormat")
        self.imgformat = 'RGB'
        if self.pixelformat == 'Mono8':
            self.imgformat = 'L'

    def _getFrame(self):
        if not self._frame:
            self._frame = self._camera.getFrame()    # creates a frame
            self._frame.announceFrame()

        return self._frame

    def _captureFrame(self, timeout = 5000):
        try:
            c = self._camera
            f = self._getFrame()

            colorSpace = Factory.Image.BGR
            if self.pixelformat == 'Mono8':
                colorSpace = Factory.Image.GRAY

            c.startCapture()
            f.queueFrameCapture()
            c.runFeatureCommand('AcquisitionStart')
            c.runFeatureCommand('AcquisitionStop')
            try:
                f.waitFrameCapture(timeout)
            except Exception, e:
                print "Exception waiting for frame: %s: %s" % (e, traceback.format_exc())
                raise(e)

            imgData = f.getBufferByteData()
            moreUsefulImgData = np.ndarray(buffer = imgData,
                                           dtype = np.uint8,
                                           shape = (f.height, f.width, 1))

            rgb = cv2.cvtColor(moreUsefulImgData, cv2.COLOR_BAYER_RG2RGB)
            c.endCapture()

            return Factory.Image(rgb, colorSpace=colorSpace)

        except Exception, e:
            print "Exception acquiring frame: %s: %s" % (e, traceback.format_exc())
            raise(e)
Beispiel #4
0
def test_interface(vimba: Vimba):
    interface = vimba.interface(vimba.interface_ids()[0])
Beispiel #5
0
def test_camera(vimba: Vimba):
    camera = vimba.camera(vimba.camera_ids()[0])
Beispiel #6
0
class Controller(ControllerTemplate):
    """
    Camera controller for AVT cameras based on pymba
    """
    def __init__(self):
        """
        Camera controller for AVT camera devices. This implementation uses
        pymba as backend.
        """
        super(Controller, self).__init__()
        self.logger = logging.getLogger(__name__)
        if LOGGING_LEVEL is not None:
            self.logger.setLevel(LOGGING_LEVEL)
        self.logger.debug('Starting AVT Camera Controller')
        self._vimba = Vimba()
        self._vimba.startup()
        self.__system = self._vimba.getSystem()
        self.__system.runFeatureCommand('GeVDiscoveryAllOnce')
        time.sleep(0.2)

    def updateDeviceHandles(self):
        """
        Refresh the list of available devices
        """
        self.logger.debug('Searching for AVT camera devices')
        self.device_handles = []
        cams = self._vimba.getCameraIds()
        for cam_id in cams:
            tmp = self._vimba.getCamera(cam_id)
            self.device_handles.append('<AVT {model} (MAC: {mac})>'
                                       ''.format(model=tmp._info.modelName,
                                                 mac=tmp._info.cameraIdString))

    def getDevice(self, device_handle):
        """
        Return the corresponding camera object for given device handle

        Parameters
        ----------
        device_handle : can be IP address, mac address or
                        camera ID (DEV_...) as reported by vimba.getCameraIds

        Returns
        -------
        cam : Camera object
            A camera object for AVT devices corresponding to the given
            device handle
        """

        # Check if device handle is list or tuple, if so: use first entry
        if isinstance(device_handle, (list, tuple)):
            device_handle = device_handle[0]

        self.logger.debug('Opening device {device_handle}'
                          ''.format(device_handle=device_handle))
        # Search for mac addresses in form 'DEV_XXXXXXXXXXXX'
        candidates = re.findall(r'(DEV_[0-9A-Z]{11,13})', device_handle)
        if len(candidates) == 0:
            # no mac address found: search for IP
            candidates = re.findall(r'[0-9]+(?:\.[0-9]+){3}', device_handle)

        try:
            return Camera(device_handle=candidates[0], vimba=self._vimba)
        except Exception as e:
            self.logger.exception('Failed to open the camera device: {e}'
                                  ''.format(e=e))
            msg = '<Was not able to open camera with given device handle!!\n' \
                  'Handle must be IP or MAC address (DEV_XXXXXXXXXXXXX)>'
            e.message = msg
            print(e.message)
            raise

    def closeController(self):
        self._vimba.shutdown()
        self.logger.info("Vimba Camera Controller shutdown")

    def __repr__(self):
        return "<AVT Camera Controller>"
Beispiel #7
0
def test_version():
    version = [int(v) for v in Vimba.version().split('.')]
    assert version[0] >= 1
    assert version[1] >= 7
    assert version[2] >= 0
Beispiel #8
0
    def __init__(self, device_handle, vimba=None):
        """
        Implementation of the AVT camera device

        Parameters
        ----------
        device_handle : object
            Unique camera device handle to identify the camera
        """
        if vimba is None:
            self._vimba = Vimba()
            self._vimba.startup()
            self.__system = self._vimba.getSystem()
            self.__system.runFeatureCommand('GeVDiscoveryAllOnce')
            time.sleep(0.2)
        else:
            self._vimba = vimba
        super(Camera, self).__init__(device_handle)
        self.logger = logging.getLogger(__name__)
        if LOGGING_LEVEL is not None:
            self.logger.setLevel(LOGGING_LEVEL)

        self.device = self._vimba.getCamera(
            self._checkDeviceHandle(device_handle))
        self.device_handle = device_handle
        self.camId = None

        self.modelName = self.device._info.modelName
        self.triggerModeSetting = 'off'

        # Open device and activate freerun mode
        self.openDevice()
        # time.sleep(0.2)
        self.device.TriggerMode = 'Off'

        # self.device.GevSCPSPacketSize = 1500  # Automatic setting not yet implemented in pymba (date: 11.12.17)
        # self.device.GevSCPSPacketSize = 8228
        self.device.runFeatureCommand("GVSPAdjustPacketSize")
        # Influences framerate, necessary if network bandwidth is not big enough
        # NOTE: Functions self._setMaxTransferRate, self._setTransferRate and self._setNumberCams may change this value
        # self.device.StreamBytesPerSecond = 10000000  # 10 Mb/sec (without GigE)
        self.device.StreamBytesPerSecond = 115000000  # 100 Mb/sec (with GigE)

        self.maxTransferRate = 115000000
        self.numCams = 1
        self.isSet = {'rate': False, 'numCams': False}

        # Register AVT specific functions.
        # Function to set maximum transfer rate depending on used network specifications
        self.registerFeature('maxRate', self._setMaxTransferRate)
        self.registerFeature('bandwidth', self._setMaxTransferRate)
        self.registerFeature('maximumTransferRate', self._setMaxTransferRate)
        self.registerFeature('transferRate', self._setTransferRate)
        # Function to set number of cameras, may affect the available transfer rate per camera
        self.registerFeature('numCams', self._setNumberCams)
        self.registerFeature('numberCams', self._setNumberCams)
        self.registerFeature('numberOfCameras', self._setNumberCams)

        self.framelist = []
        self.imgData = []
        self._clearQueueAndFrames()

        # Init data type LUT for each PixelFormat
        self.imageFormatLUT = {'Mono8': np.uint8, 'Mono12': np.uint16}
Beispiel #9
0
class Camera(CameraTemplate):
    """
    AVT Camera implementation based on pymba

    Creating this Object automatically opens the camera. It is NOT necessary to
    call openDevice() !!! This is done to set some settings to put the camera
    into freerun mode.
    """
    def __init__(self, device_handle, vimba=None):
        """
        Implementation of the AVT camera device

        Parameters
        ----------
        device_handle : object
            Unique camera device handle to identify the camera
        """
        if vimba is None:
            self._vimba = Vimba()
            self._vimba.startup()
            self.__system = self._vimba.getSystem()
            self.__system.runFeatureCommand('GeVDiscoveryAllOnce')
            time.sleep(0.2)
        else:
            self._vimba = vimba
        super(Camera, self).__init__(device_handle)
        self.logger = logging.getLogger(__name__)
        if LOGGING_LEVEL is not None:
            self.logger.setLevel(LOGGING_LEVEL)

        self.device = self._vimba.getCamera(
            self._checkDeviceHandle(device_handle))
        self.device_handle = device_handle
        self.camId = None

        self.modelName = self.device._info.modelName
        self.triggerModeSetting = 'off'

        # Open device and activate freerun mode
        self.openDevice()
        # time.sleep(0.2)
        self.device.TriggerMode = 'Off'

        # self.device.GevSCPSPacketSize = 1500  # Automatic setting not yet implemented in pymba (date: 11.12.17)
        # self.device.GevSCPSPacketSize = 8228
        self.device.runFeatureCommand("GVSPAdjustPacketSize")
        # Influences framerate, necessary if network bandwidth is not big enough
        # NOTE: Functions self._setMaxTransferRate, self._setTransferRate and self._setNumberCams may change this value
        # self.device.StreamBytesPerSecond = 10000000  # 10 Mb/sec (without GigE)
        self.device.StreamBytesPerSecond = 115000000  # 100 Mb/sec (with GigE)

        self.maxTransferRate = 115000000
        self.numCams = 1
        self.isSet = {'rate': False, 'numCams': False}

        # Register AVT specific functions.
        # Function to set maximum transfer rate depending on used network specifications
        self.registerFeature('maxRate', self._setMaxTransferRate)
        self.registerFeature('bandwidth', self._setMaxTransferRate)
        self.registerFeature('maximumTransferRate', self._setMaxTransferRate)
        self.registerFeature('transferRate', self._setTransferRate)
        # Function to set number of cameras, may affect the available transfer rate per camera
        self.registerFeature('numCams', self._setNumberCams)
        self.registerFeature('numberCams', self._setNumberCams)
        self.registerFeature('numberOfCameras', self._setNumberCams)

        self.framelist = []
        self.imgData = []
        self._clearQueueAndFrames()

        # Init data type LUT for each PixelFormat
        self.imageFormatLUT = {'Mono8': np.uint8, 'Mono12': np.uint16}

    def __del__(self):
        # self._cleanUp()
        self._vimba.shutdown()

    def _checkDeviceHandle(self, device_handle):
        """
        Return the corresponding camera object for given device handle

        Parameters
        ----------
        device_handle : can be IP address, mac address or
                        camera ID (DEV_...) as reported by vimba.getCameraIds

        Returns
        -------
        cam : Camera object
            A camera object for AVT devices corresponding to the given
            device handle
        """
        # Check if device handle is list or tuple, if so: use first entry
        if isinstance(device_handle, (list, tuple)):
            device_handle = device_handle[0]

        self.logger.debug('Opening device {device_handle}'
                          ''.format(device_handle=device_handle))
        # Search for mac addresses in form 'DEV_XXXXXXXXXXXX'
        candidates = re.findall(r'([0-9A-Z]{11,13})', device_handle)
        if len(candidates) == 0:
            # no mac address found: search for IP
            candidates = re.findall(r'[0-9]+(?:\.[0-9]+){3}', device_handle)

        return candidates[0]

    def _setMaxTransferRate(self, rate=None):
        """
        Sets the transfer rate by changing 'StreamBytesPerSecond'.
        If passed None, will return actual rate set.

        Parameters
        ----------
        rate: int
            Maximum bandwidth available. Typical values:
            - with GigE     : 115000000
            - without GigE  : 10000000

        Returns
        -------
        self.max_bandwidth: int
            If passed None: returns set bandwidth
        """
        self.logger.debug(
            "Setting max transfer rate for device {handle} to {rate}"
            "".format(handle=self.device_handle, rate=rate))
        if rate is None:
            return self.maxTransferRate
        self.maxTransferRate = rate
        self.isSet['rate'] = True

        # Call function if number of cams was set
        if self.isSet['numCams']:
            self._setTransferRate()
        else:
            self.device.StreamBytesPerSecond = rate

        return self.maxTransferRate

    def _setNumberCams(self, num=None):
        """
        Sets the number of AVT cameras used (this will affect the maximum transfer rate for each camera).
        If passed None, will return actual number of cameras set.

        Parameters
        ----------
        num: int
            Number of AVT cameras

        Returns
        -------
        self.numCams: int
            Number of AVT cameras set for this object
        """
        self.logger.debug(
            "Setting number of cameras for device {handle} to {num}"
            "".format(handle=self.device_handle, num=num))
        if num is None:
            return self.numCams
        self.numCams = num
        self.isSet['numCams'] = True

        if self.isSet['rate']:
            self._setTransferRate()

        return self.numCams

    def _setTransferRate(self):
        """
        Takes maxTransferRate and numCams to compute a viable transfer rate for the device.
        """
        transfer_rate = int(self.maxTransferRate / self.numCams)
        self.device.StreamBytesPerSecond = transfer_rate
        self.logger.debug("Setting transfer rate for {device} to {rate}"
                          "".format(device=self.device_handle,
                                    rate=transfer_rate))

    def _clearQueueAndFrames(self):
        """
        Does some cleanup jobs. Call after whenever you feel like there might be a buffer overflow.
        Calls:  - flushCaptureQueue()
                - revokeAllFrames()
        """
        self.device.flushCaptureQueue()
        self.device.revokeAllFrames()

    def _cleanUp(self):
        """
        Does some cleanup jobs. Call after "AcquisitionStop".
        Calls:  - endCapture()
                - flushCaptureQueue()
                - revokeAllFrames()
        """
        self.device.endCapture()
        self._clearQueueAndFrames()

    def _frameCallback(self, frame):
        """
        Callback function to fill frames with data

        Parameters
        -------
        frame : frame object
            frame created by device.getFrame()
        """
        frame.waitFrameCapture(1000)
        # Get image data ...
        singleImg = np.ndarray(
            buffer=frame.getBufferByteData(),
            dtype=self.imageFormatLUT[self.device.PixelFormat],
            shape=(frame.height, frame.width))

        self.imgData.append(singleImg)
        frame.queueFrameCapture(self._frameCallback)

    def _getCamId(self):
        """
        Creates a cam-specific cam id, which consists of the manufacturer and a
        4 digit number. This id makes it possible to identify the virtual
        object with real object.

        Returns
        -------
        camId : "unique" cam id
        """
        if self.camId is None:
            mfr = b'AVT'  # mfr = manufacturer
            id = self.device._info.cameraIdString[-4:]
            camId = b'_'.join((mfr, id)).decode('utf-8')

            return camId
        else:
            return self.camId

    @staticmethod
    def listDevices():
        """
        List available AVT cameras

        Returns
        -------
        cams : list
            list of available AVT devices
        """
        return Controller().listDevices()

    def openDevice(self):
        """
        Opens a camera device with the stored self.device object
        """

        try:
            self.logger.debug('Opening camera device')
            self.device.openCamera()
        except Exception as e:
            self.logger.exception('Failed to open the camera device: '
                                  '{e}'.format(e=e))

    def closeDevice(self):
        """
        Closes camera device
        """
        try:
            self.logger.debug('Closing camera device')
            self.device.closeCamera()
            del self.device
            self.device = None
        except Exception as e:
            self.logger.exception('Failed to close the camera device: '
                                  '{e}'.format(e=e))

    def isOpen(self):
        """
        Check if the device for this instance is currently open and ready to
        communicate

        Returns
        -------
        bool
            True if the camera connection is open, False if it is not
        """
        # AVT cameras do not have any isOpen-function by itself.
        # Assuming that if there is a device given in self.device, device is opened.
        if self.device is not None:
            return True
        else:
            return False

    def getImage(self, *args, **kwargs):
        """
        Get an image from the camera device

        *args and **kwargs are ignored parameters!

        !!! Warning: Check transfer rate of your network connection !!!
        Low transfer-rates may cause incomplete image transfer with missing
        data

        Returns
        -------
        img : np.ndarray
            Current camera image
        """

        self.logger.debug('Creating frame and starting acquisition')
        # Create new frame for camera
        frame = self.device.getFrame()
        # Announce frame
        frame.announceFrame()
        # Capture a camera image
        self.device.startCapture()
        frame.queueFrameCapture()
        self.device.runFeatureCommand('AcquisitionStart')

        frame.waitFrameCapture(1000)
        incomplete_frames = 0
        incomplete_frame_limit = 20
        while frame.getReceiveStatus() != 0:
            frame.queueFrameCapture()
            frame.waitFrameCapture(1000)
            incomplete_frames += 1
            if incomplete_frames > incomplete_frame_limit:
                raise RuntimeError(
                    "More than {lim} frames in a row were incomplete! Check transfer settings!"
                    "".format(lim=incomplete_frame_limit))
        self.device.runFeatureCommand('AcquisitionStop')
        self.logger.debug(
            "Trashed frames: {t_frames}".format(t_frames=incomplete_frames))

        # Get image data ...
        imgData = np.ndarray(
            buffer=frame.getBufferByteData(),
            dtype=self.imageFormatLUT[self.device.PixelFormat],
            shape=(frame.height, frame.width))

        # Do cleanup
        self._cleanUp()
        self.logger.debug('Image acquisition finished')

        return imgData.copy()

    def prepareRecording(self, num):
        """ Sets the camera to MultiFrame mode and prepares frames. Use with
        "record()"-function.

        Parameters
        ----------
        num : int
            number of frames to be captured during acquisition
        """
        self._clearQueueAndFrames()
        self.device.AcquisitionMode = 'MultiFrame'
        self.device.AcquisitionFrameCount = num

        # Creating frames
        self.framelist = []
        for _ in range(num):
            frame = self.device.getFrame()
            frame.announceFrame()
            frame.queueFrameCapture(self._frameCallback)
            self.framelist.append(frame)

        self.device.startCapture()

    def record(self):
        """ Blocking image acquisition, ends acquisition when num frames are
        captured, where num is set by "prepareRecording(num)". Only use with
        "prepareRecording(num)".

        Returns
        -------
        imgData : list
            List of images
        """

        self.imgData = []
        self.device.runFeatureCommand('AcquisitionStart')
        # Block until num images are captured
        while len(self.imgData) != len(self.framelist):
            pass
        self.device.runFeatureCommand('AcquisitionStop')
        # Do cleanup
        self._cleanUp()
        # Set back to freerun mode
        self.device.AcquisitionMode = 'Continuous'

        return copy.deepcopy(self.imgData)

    # TODO: If grabStart without "num" is needed - implement threading solution with while loop (similar to _liveView())
    def grabStart(self, num):
        """
        Prepares num images to be grabbed. This function is not blocking.
        Calling "grabStop()" will end acquisition.

        Parameters
        ----------
        num : int
            Number of images that should be recorded
        """
        self.device.AcquisitionMode = 'MultiFrame'
        self.device.AcquisitionFrameCount = num

        # Creating frames
        self.framelist = []
        for _ in range(num):
            frame = self.device.getFrame()
            frame.announceFrame()
            frame.queueFrameCapture(self._frameCallback)
            self.framelist.append(frame)

        self.device.startCapture()
        self.device.runFeatureCommand('AcquisitionStart')

    def grabStop(self):
        """
        Stop grabbing images and return camera to continuous mode.
        """
        self.device.runFeatureCommand('AcquisitionStop')
        # Do cleanup
        self._cleanUp()
        # Set back to freerun mode
        self.device.AcquisitionMode = 'Continuous'

        return copy.deepcopy(self.imgData)

    def _liveView(self):
        """
        Live image stream an visualization through OpenCV window

        Leave _liveView by pressing "q"
        """
        cv.startWindowThread()
        cv.namedWindow("IMG", 2)
        cv.resizeWindow("IMG", 900, 900)
        frame = self.device.getFrame()
        frame.announceFrame()

        self.device.startCapture()

        framecount = 0
        droppedframes = []

        while True:
            try:
                frame.queueFrameCapture()
                success = True
            except Exception:
                droppedframes.append(framecount)
                success = False
            self.device.runFeatureCommand("AcquisitionStart")
            self.device.runFeatureCommand("AcquisitionStop")
            frame.waitFrameCapture(1000)
            frame_data = frame.getBufferByteData()
            if success:
                live_img = np.ndarray(
                    buffer=frame_data,
                    dtype=self.imageFormatLUT[self.device.PixelFormat],
                    shape=(frame.height, frame.width))

                cv.imshow("IMG", live_img)
            framecount += 1
            key = cv.waitKey(1) & 0xFF
            if key == ord("q"):
                cv.destroyAllWindows()
                self.logger.info("Frames displayed: %i" % framecount)
                self.logger.info("Frames dropped: %s" % droppedframes)
                break

        # Cleanup
        self._cleanUp()

    def listFeatures(self):
        """
        Lists camera features
        """
        try:
            self.logger.debug('Listing camera features')
            featureNames = self.device.getFeatureNames()
            print("Printing feature names: ...\n")
            print("\n".join(featureNames))
        except Exception as e:
            self.logger.exception('Failed to get feature names: '
                                  '{e}'.format(e=e))

    def setExposureMicrons(self, microns=None):
        """
        Set the exposure time to the given value in microseconds or read the
        current value by passing None

        Parameters
        ----------
        microns : int
            Desired exposure time in microseconds that should be set, or None
            to read the current exposure time

        Returns
        -------
        microns : int
            The exposure time in microseconds after applying the passed value
        """
        if microns is not None:
            self.logger.debug('Setting <ExposureTime> to {microns}'
                              ''.format(microns=microns))
            self.device.ExposureTimeAbs = microns
        return self.device.ExposureTimeAbs

    def autoExposure(self):
        """
        Automatically sets the exposure time of the camera ONCE.
        Old exposure setting is lost during the process!

        Returns
        -------
        exposure : int
            The exposure time in microseconds after auto exposure
        """
        self.logger.debug("Starting automatic exposure control")
        self.device.ExposureAuto = "Once"
        # Save trigger settings and activate acquisition until
        # auto exposure has settled
        triggerMode_buffer = self.triggerMode

        frame = self.device.getFrame()
        frame.announceFrame()

        self.device.startCapture()

        self.triggerMode = "off"
        max_iter = 100
        iter = 0
        # Auto exposure gets stuck if the border values are reached,
        # but further adjustments are necessary
        limits = (self.device.ExposureAutoMin, self.device.ExposureAutoMax)
        limit_cnt = 0
        last_exposure = -1

        self.device.runFeatureCommand("AcquisitionStart")
        while self.device.ExposureAuto != "Off":
            if last_exposure in limits:
                limit_cnt += 1
            else:
                limit_cnt = 0
            try:
                frame.queueFrameCapture()
            except Exception:
                pass
            frame.waitFrameCapture(1000)
            iter += 1
            last_exposure = self.device.ExposureTimeAbs
            if limit_cnt > 5:
                self.logger.info(
                    "Auto exposure has run into limits. Continuing with exposure of: {exposure} "
                    .format(exposure=last_exposure))
                self.device.ExposureAuto = "Off"
            if iter >= max_iter:
                try:
                    raise TimeoutError("Timeout while setting auto exposure!")
                except NameError:
                    # Python 2 compatible Error
                    raise Exception("Timeout while setting auto exposure!")

        # Cleanup
        self.device.runFeatureCommand("AcquisitionStop")
        self._cleanUp()

        self.triggerMode = triggerMode_buffer
        self.logger.debug("Set exposure time to {exposure}"
                          "".format(exposure=self.device.ExposureTimeAbs))

        return self.device.ExposureTimeAbs

    def setResolution(self, resolution=None):
        """
        Set the resolution of the camera to the given values in pixels or read
        the current resolution by passing None

        Parameters
        ----------
        resolution : tuple
            Desired camera resolution in the form (width, height), or None to
            read the current resolution

        Returns
        -------
        resolution : tuple
            The set camera resolution after applying the passed value
        """
        if resolution is not None:
            self.logger.debug('Setting <Width> to {width}'
                              ''.format(width=resolution[0]))
            self.device.Width = resolution[0]
            self.logger.debug('Setting <Height> to {height}'
                              ''.format(height=resolution[1]))
            self.device.Height = resolution[1]
        return self.device.Width, self.device.Height

    def setGain(self, gain=None):
        """
        Set the gain of the camera to the given value or read the current value
        by passing None

        Parameters
        ----------
        gain : float
            Desired gain value in dB to be set, or None to read the current
            gain value

        Returns
        -------
        gain : int
            The gain value after applying the passed value
        """
        if gain is not None:
            self.logger.debug('Setting <Gain> to {gain}' ''.format(gain=gain))
            self.device.Gain = gain
        return self.device.Gain

    def setPixelFormat(self, fmt=None):
        """
        Set the image format to the passed setting or read the current format
        by passing None

        Parameters
        ----------
        fmt : str
            String describing the desired image format (e.g. "mono8"), or None
            to read the current image format. Check camera technical manual for available formats,
            may differ from model to model.

        Returns
        -------
        fmt : str
            The image format after applying the passed value
        """

        if fmt is not None:
            self.logger.debug('Setting <PixelFormat> to {fmt}'
                              ''.format(fmt=fmt))
            self.device.PixelFormat = fmt
            self.device.runFeatureCommand("GVSPAdjustPacketSize")
        return self.device.PixelFormat

    def setTriggerMode(self, mode=None):
        """
        Set the trigger mode of the camera to either "in", "out" or "off", or
        read the current trigger setting ba passing None

        Parameters
        ----------
        mode : str
            The desired trigger mode. "in" means the camera receives a trigger
            signal, "out" means the camera sends a trigger signal, "off"" means
            the camera does not react to triggers. To read the current trigger
            setting pass None

        Returns
        -------
        mode : str
            The trigger mode after applying the passed value
        """
        self.logger.debug("Setting trigger mode to: {mode}".format(mode=mode))
        if mode is None:
            return self.triggerModeSetting
        elif isinstance(mode, str):
            if mode.lower() == 'in':
                self.device.TriggerMode = 'On'
                self.device.TriggerSource = 'Line1'
                self.device.TriggerSelector = 'FrameStart'
                self.device.TriggerActivation = "RisingEdge"

                self.triggerModeSetting = 'in'
            elif mode.lower() == 'out':
                # TODO: Implement out trigger for AVT cameras
                self.triggerModeSetting = 'out'
                raise NotImplementedError('Sending triggers is not'
                                          'implemented yet!')
            elif mode.lower() == 'off':
                self.device.TriggerMode = 'Off'
                self.device.TriggerSource = 'Freerun'
                self.device.TriggerSelector = 'FrameStart'

                self.triggerModeSetting = 'off'
            else:
                raise ValueError('Unexpected value in setTriggerMode. '
                                 'Expected "in", "out", or "off". Got {mode}'
                                 ''.format(mode=mode))
            return self.triggerModeSetting
        else:
            raise TypeError('Trigger Mode should be None, "in", "out", or '
                            '"off". Got {mode}'.format(mode=mode))

    def __repr__(self):
        return repr(self.device)
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, 'value: {}'.format(value),
                                 'range: {}'.format(range_)) if x is not None))
Beispiel #11
0
class AvtCamera(Camera):
    """Class for controlling an AVT camera.

    Uses the Vimba interface pymba
    (module documentation `here <https://github.com/morefigs/pymba>`_).

    Parameters
    ----------

    Returns
    -------

    """
    def __init__(self, downsampling=None, **kwargs):
        # Set timeout for frame acquisition. Give this as input?
        self.timeout_ms = 1000

        super().__init__(**kwargs)

        try:
            self.vimba = Vimba()
        except NameError:
            print("The pymba package must be installed to use an AVT camera!")

        self.frame = None

    def open_camera(self):
        """ """
        self.vimba.startup()

        # If there are multiple cameras, only the first one is used (this may
        # change):
        camera_ids = self.vimba.getCameraIds()
        if self.debug:
            if len(camera_ids) > 1:
                print("Multiple cameras detected: {}. {} wiil be used.".format(
                    camera_ids, camera_ids[0]))
            else:
                print("Detected camera {}.".format(camera_ids[0]))
        self.cam = self.vimba.getCamera(camera_ids[0])

        # Start camera:
        self.cam.openCamera()
        self.frame = self.cam.getFrame()
        self.frame.announceFrame()

        self.cam.startCapture()
        self.frame.queueFrameCapture()
        self.cam.runFeatureCommand("AcquisitionStart")

    def set(self, param, val):
        """

        Parameters
        ----------
        param :
            
        val :
            

        Returns
        -------

        """
        try:
            if param == "exposure":
                # camera wants exposure in us:
                self.cam.ExposureTime = int(val * 1000)

            if param == "framerate":
                # To set new frame rate for AVT cameras acquisition has to be
                # interrupted:
                # TODO Handle this in a cleaner way
                if val < 210:  # empirically found maximum frame rate to be set
                    self.frame.waitFrameCapture(self.timeout_ms)
                    self.cam.runFeatureCommand("AcquisitionStop")
                    self.cam.endCapture()
                    self.cam.revokeAllFrames()

                    self.cam.AcquisitionFrameRate = val

                    self.cam.startCapture()
                    self.frame.queueFrameCapture()
                    self.cam.runFeatureCommand("AcquisitionStart")
        except VimbaException:
            print("Invalid value! The parameter will not be changed.")

    def read(self):
        """ """
        try:
            self.frame.waitFrameCapture(self.timeout_ms)
            self.frame.queueFrameCapture()

            raw_data = self.frame.getBufferByteData()

            frame = np.ndarray(
                buffer=raw_data,
                dtype=np.uint8,
                shape=(self.frame.height, self.frame.width),
            )

        except VimbaException:
            frame = None
            if self.debug:
                print("Unable to acquire frame")

        return frame

    def release(self):
        """ """
        self.frame.waitFrameCapture(self.timeout_ms)
        self.cam.runFeatureCommand("AcquisitionStop")
        self.cam.endCapture()
        self.cam.revokeAllFrames()
        self.vimba.shutdown()
Beispiel #12
0
 def init_vimba(self):
     if AVTCamera.vimba == None:
         AVTCamera.vimba = Vimba()
         AVTCamera.vimba.startup()
         print ("init_vimba")