コード例 #1
0
class CameraPlot:
    def __init__(self):
        self.vimba = Vimba()
        self.vimba.startup()
        self.system = self.vimba.getSystem()
        self.cameraIds = self.vimba.getCameraIds()
        self.init_win()
        self.init_camera()

    def init_win(self):
        self.win = QtGui.QMainWindow()
        self.win.show()
        self.win.resize(600, 400)
        self.win.setWindowTitle("pymba + pyqtgraph")
        self.img = pg.ImageView()
        self.win.setCentralWidget(self.img)

    def init_camera(self):
        print("Vimba version:", self.vimba.getVersion())
        print("Found {:d} cameras.".format(len(self.cameraIds)))
        self.cam = self.vimba.getCamera(self.cameraIds[0])
        self.cam.openCamera()
        info = self.cam.getInfo()
        print("cameraName:", info.cameraName.decode("ascii"))
        print("interfaceIdString:", info.interfaceIdString.decode("ascii"))
        print("modelName:", info.modelName.decode("ascii"))

    def start_camera(self):
        self.cam.AcquisitionMode = "Continuous"
        self.cam.IIDCPhyspeed = "S800"
        self.cam.PixelFormat = "Mono16"
        self.cam.TriggerMode = "Off"
        self.cam.AcquisitionFrameRate = 20.0

        self.frame = self.cam.getFrame()
        self.frame.announceFrame()
        self.cam.startCapture()
        self.cam.runFeatureCommand("AcquisitionStart")

    def process_images(self):
        QtCore.QTimer.singleShot(50, self.process_images)
        self.frame.queueFrameCapture()
        self.frame.waitFrameCapture()
        im = self.frame.getImage().T
        self.img.setImage(im,
                          autoRange=False,
                          autoLevels=False,
                          autoHistogramRange=False)

    def stop_camera(self):
        self.cam.runFeatureCommand("AcquisitionStop")
        self.cam.endCapture()
        self.cam.revokeAllFrames()

    def deinit_camera(self):
        self.vimba.shutdown()
コード例 #2
0
class VimbaCam(Driver):

    def initialize(self):
        self.vimba = Vimba()
        self.vimba.startup()
        self.cam = self.vimba.getCamera(self.vimba.getCameraIds()[0])
        self.cam.openCamera()

        self.cam.PixelFormat = 'Mono8'
        self.frame = self.cam.getFrame()
        self.frame.announceFrame()
        self.cam.startCapture()
        return

    def finalize(self):
        self.vimba.shutdown()
        return

    @Action()
    def getFrame(self):
        try:
            self.frame.queueFrameCapture()
            success = True
        except:
            success = False

        self.cam.runFeatureCommand('AcquisitionStart')
        self.cam.runFeatureCommand('AcquisitionStop')
        self.frame.waitFrameCapture(0)
        frame_data = self.frame.getBufferByteData()
        if success:
            img_config = {
                'buffer': frame_data,
                'dtype': np.uint8,
                'shape': (self.frame.height, self.frame.width, 1),
            }
            img = np.ndarray(**img_config)
            return img[...,0]
        else:
            return None
コード例 #3
0
class Vimba_Camera:
    def version():
        with Vimba() as vimba:
            return vimba.getVersion()

    def enumerate_cameras():
        # get connected camera ids
        # otherwise we haven't started yet. Open and close vimba library
        with Vimba() as vimba:
            return vimba.getCameraIds()

    def startup_vimba(self):
        log.info('Starting vimba.')
        self.vimba = Vimba()
        self.vimba.startup()

    def shutdown_vimba(self):
        self.vimba.shutdown()

    def __init__(self, name, vimba=None):
        # remember that Vimba as a singleton
        # you can use the camera as a context manager so as to not worry
        # about opening and closing the libary or the camera.
        # Otherwise remember to do it manually

        self.name = name
        if vimba is None:
            self.startup_vimba()
        else:
            self.vimba = vimba
            print(f"Received vimba {id(self.vimba)}")
        cams = self.vimba.getCameraIds()

        # check if the camera exists
        if self.name not in cams:
            raise NameError(
                f'Camera {name} not found in list of connected cameras.')

        self.camera = self.vimba.getCamera(self.name)
        self.camera.openCamera()
        log.info(f'Initialise camera {name}.')

    def close(self):
        # release both camera and vimba handles
        self.camera.closeCamera()
        log.info(f'Closing camera.')

        # self.vimba.shutdown()
        # log.info(f'Shutting down vimba.')

    def __enter__(self):
        log.info('__enter__')
        # __init__ starts vimba and opens the camera. Don't bother here.
        return self

    def __exit__(self, type, value, traceback):
        self.close()

    def list_features(self):
        features = self.camera.getFeatureNames()

        return [self.camera.getFeatureInfo(feature) for feature in features]

    def get_feature_range(self, feature):
        try:
            return self.camera.getFeatureRange(feature)
        except VimbaException:
            pass

    def get_camera_info(self):
        return self.camera.getInfo()

    def print_feature_description(self, feature):
        try:
            print(self.camera.getFeatureInfo(feature).description)
        except VimbaException:
            print('No description available.')

    def write_features_and_values_to_file(self):
        features = self.list_features()
        info = self.get_camera_info()

        filename = (info.cameraName.decode('utf8') +
                    info.cameraIdString.decode('utf8') + '_attributes.txt')
        with open(filename, 'w') as f:
            for feature in features:
                name = feature.name.decode('utf-8')
                try:
                    value = self.camera.__getattr__(name)
                except (VimbaException, TypeError):
                    value = None
                # print(name, value)
                f.write(f"['{name}', ")
                f.write(f"'{value}'],\n")

            # delete that last comma
            f.seek(0, 2)
            size = f.tell()
            f.truncate(size - 3)

    def set_feature(self, name, value):
        setattr(self.camera, name, value)

    def set_features(self, _dict):
        # ideally this would be an ordered dict since some features can only be
        # set after others, e.g. cannot set Gain Value unless Gain is Manual.
        for k, v in _dict.items():
            self.set_feature(k, v)

    def set_roi(self, roi):
        # set the rois with the correct order
        try:
            self.set_feature('Height', roi['Height'])
            self.set_feature('OffsetY', roi['OffsetY'])
        except VimbaException:
            self.set_feature('OffsetY', roi['OffsetY'])
            self.set_feature('Height', roi['Height'])

        try:
            self.set_feature('Width', roi['Width'])
            self.set_feature('OffsetX', roi['OffsetX'])
        except VimbaException:
            self.set_feature('OffsetX', roi['OffsetX'])
            self.set_feature('Width', roi['Width'])

    def snap(self, trigger=False):
        self.camera.TriggerMode = 'On' if trigger else 'Off'
        self.camera.AcquisitionMode = 'SingleFrame'
        # self.camera.AcquisitionMode = 'MultiFrame'
        # self.camera.AcquisitionFrameCount = 2

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

        # capture a camera image
        self.camera.startCapture()
        frame.queueFrameCapture()
        self.camera.runFeatureCommand('AcquisitionStart')

        # this will never time out
        while frame.waitFrameCapture() != 0:
            print('.', end='')
        # frame.waitFrameCapture(timeout=-1)
        self.camera.runFeatureCommand('AcquisitionStop')
        # frame.waitFrameCapture()

        # clean up after capture
        self.camera.endCapture()
        self.camera.revokeAllFrames()

        data = self._decode_image_data(frame)

        return data

    def grab_multiple(self, N=3, trigger=True):
        self.camera.TriggerMode = 'On' if trigger else 'Off'
        self.camera.AcquisitionMode = 'MultiFrame'
        self.camera.AcquisitionFrameCount = N

        frames = [self.camera.getFrame() for _ in range(N)]
        for frame in frames:
            frame.announceFrame()

        # start capturing
        self.camera.startCapture()
        # queue the frames
        for frame in frames:
            frame.queueFrameCapture()
        self.camera.runFeatureCommand('AcquisitionStart')

        # this will never time out
        # having it the while loop here means that I can get SIGINT to exit
        while frames[-1].waitFrameCapture() != 0:
            print('.', end='')
        # frames[-1].waitFrameCapture(timeout=-1)
        self.camera.runFeatureCommand('AcquisitionStop')
        # frame.waitFrameCapture()

        # clean up after capture
        self.camera.endCapture()
        self.camera.revokeAllFrames()

        data = [self._decode_image_data(frame) for frame in frames]

        return np.array(data)

    def _decode_image_data(self, frame):
        bitdepths = {
            'Mono16': np.uint16,
            'Mono12Packed': np.uint16,
            'Mono8': np.uint8
        }

        bitdepth = bitdepths[self.camera.PixelFormat]

        data = np.ndarray(buffer=frame.getBufferByteData(),
                          dtype=bitdepth,
                          shape=(frame.height, frame.width))

        return data.copy()
コード例 #4
0
ファイル: cameraAVT.py プロジェクト: nilsmelchert/pyCameras
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>"
コード例 #5
0
ファイル: cameraAVT.py プロジェクト: nilsmelchert/pyCameras
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)
        # 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)
        # Function to set pixel format
        self.registerFeature('pixelFormat', self.setFormat)
        self.registerFeature('pixelType', self.setFormat)
        self.registerFeature('format', self.setFormat)

        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)
        self.device.runFeatureCommand('AcquisitionStop')

        # 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 setFormat(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
        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)
コード例 #6
0
ファイル: vimba.py プロジェクト: mtsolmn/lantz-drivers
class VimbaCam(Driver):

    def __init__(self, camera=0, level='beginner',
                 *args, **kwargs):
        """
        @params
        :type camera_num: int, The camera device index: 0,1,..
        :type level: str, Level of controls to show ['beginner', 'expert']

        Example:
        import lantz
        from lantz.drivers.allied_vision import Cam
        import time
        try:
                lantzlog
        except NameError:
                lantzlog = lantz.log.log_to_screen(level=lantz.log.DEBUG)

        cam = Cam(camera='Basler acA4112-8gm (40006341)')
        cam.initialize()
        cam.exposure_time
        cam.exposure_time = 3010
        cam.exposure_time
        cam.grab_image()
        print('Speedtest:')
        nr = 10
        start = time.time()
        for n in range(nr):
            cam.grab_image()
            duration = (time.time()-start)*1000*lantz.Q_('ms')
            print('Read {} images in {}. Reading alone took {}. Framerate {}'.format(nr,
                duration, duration - nr* cam.exposure_time, nr / duration.to('s')))
        cam.finalize()
        """
        super().__init__(*args, **kwargs)
        self.camera = camera
        self.level = level
        # Some actions cannot be performed while reading
        self._grabbing_lock = threading.RLock()

    def initialize(self):
        """
        Params:
        camera -- number in list of show_cameras or friendly_name
        """

        self.vimba = Vimba()
        self.vimba.startup()

        cameras = self.vimba.getCameraIds()
        self.log_debug('Available cameras are:' + str(cameras))

        try:
            if isinstance(self.camera, int):
                cam = cameras[self.camera]
                self.cam = self.vimba.getCamera(cam)
            else:
                self.cam = self.vimba.getCamera(self.camera)
        except RuntimeError as err:
            self.log_error(err)
            raise RuntimeError(err)

        self.frame = self.cam.getFrame()
        self.frame.announceFrame()
        self.cam.startCapture()

        self._dynamically_add_properties()
        self._aliases()

        # get rid of Mono12Packed and give a log error:
        fmt = self.pixel_format
        if fmt == str('Mono12Packed'):
            self.log_error('PixelFormat {} not supported. Using Mono12 '
                           'instead'.format(fmt))
            self.pixel_format = 'Mono12'

        # Go to full available speed
        # cam.properties['DeviceLinkThroughputLimitMode'] = 'Off'

    def finalize(self):
        self.cam.endCapture()
        self.cam.revokeAllFrames()
        return

    def _dynamically_add_properties(self):
        """Add all properties available on driver as Feats"""
        props = self.getFeatureNames() if self.level == 'expert' else beginner_controls
        for p in props:
            info = self.cam.getFeatureInfo(p)
            range_ = self.cam.getFeatureRange(p)
            limits = range_ if isinstance(tuple, range_) else None
            values = range_ if isinstance(list, range_) else None

            feat = Feat(fget=create_getter(p),
                        fset=create_setter(p),
                        doc=info.description,
                        units=info.unit,
                        limits=limits,
                        values=values,
                        )
            feat.name = p
            attach_dyn_propr(self, p, feat)

    def _aliases(self):
        """Add easy to use aliases to strange internal pylon names

        Note that in the Logs, the original is renamed to the alias"""
        for alias, orig in aliases.items():
            attach_dyn_propr(self, alias, self.feats[orig].feat)

    @Feat()
    def info(self):
        # We can still get information of the camera back
        return 'Camera info of camera object:', self.cam.getInfo()  # TODO TEST

    # Most properties are added automatically by _dynamically_add_properties

    @Feat(values=todict(['Mono8', 'Mono12', 'Mono12Packed']))
    def pixel_format(self):
        fmt = self.cam['PixelFormat']
        if fmt == 'Mono12Packed':
            self.log_error('PixelFormat {} not supported. Use Mono12 instead'
                           ''.format(fmt))
        return fmt

    @pixel_format.setter
    def pixel_format(self, value):
        if value == 'Mono12Packed':
            self.log_error('PixelFormat {} not supported. Using Mono12 '
                           'instead'.format(value))
            value = 'Mono12'
        self.cam['PixelFormat'] = value

    @Feat()
    def properties(self):
        """Dict with all properties supported by pylon dll driver"""
        return self.cam.getFeatureNames()

    @Action()
    def list_properties(self):
        """List all properties and their values"""
        for key in self.cam.getFeatureNames():
            try:
                value = self.cam[key]
            except IOError:
                value = '<NOT READABLE>'

            description = self.cam.getFeatureInfo(key)
            range_ = self.cam.getFeatureRange(key)
            print('{0} ({1}):\t{2}\t{3}'.format(key, description, value, range_))

    @Action(log_output=False)
    def grab_image(self):
        """Record a single image from the camera"""
        self.cam.AcquisitionMode = 'SingleFrame'
        try:
            self.frame.queueFrameCapture()
            success = True
        except:
            success = False

        self.cam.runFeatureCommand('AcquisitionStart')
        self.cam.runFeatureCommand('AcquisitionStop')
        self.frame.waitFrameCapture(0)
        frame_data = self.frame.getBufferByteData()
        if success:
            img_config = {
                'buffer': frame_data,
                'dtype': np.uint8,
                'shape': (self.frame.height, self.frame.width, 1),
            }
            img = np.ndarray(**img_config)
            return img[..., 0]
        else:
            return None

    @Action(log_output=False)
    def grab_images(self, num=1):
        # ΤΟDO see https://gist.github.com/npyoung/1c160c9eee91fd44c587
        raise NotImplemented()
        with self._grabbing_lock:
            img = self.cam.grab_images(num)
        return img

    @Action(log_output=False)
    def getFrame(self):
        """Backward compatibility"""
        return self.grab_image

    @Action()
    def set_roi(self, height, width, yoffset, xoffset):
        # Validation:
        if width + xoffset > self.properties['WidthMax']:
            self.log_error('Not setting ROI:  Width + xoffset = {} exceeding '
                           'max width of camera {}.'.format(width + xoffset,
                                                            self.properties['WidthMax']))
            return
        if height + yoffset > self.properties['HeightMax']:
            self.log_error('Not setting ROI: Height + yoffset = {} exceeding '
                           'max height of camera {}.'.format(height + yoffset,
                                                             self.properties['HeightMax']))
            return

        # Offset should be multiple of 2:
        xoffset -= xoffset % 2
        yoffset -= yoffset % 2

        if height < 16:
            self.log_error('Height {} too small, smaller than 16. Adjusting '
                           'to 16'.format(height))
            height = 16
        if width < 16:
            self.log_error('Width {} too small, smaller than 16. Adjusting '
                           'to 16'.format(width))
            width = 16

        with self._grabbing_lock:
            # Order matters!
            if self.OffsetY > yoffset:
                self.Height = height
                self.OffsetY = yoffset
            else:
                self.Height = height
                self.OffsetY = yoffset
            if self.OffsetX > xoffset:
                self.OffsetX = xoffset
                self.Width = width
            else:
                self.Width = width
                self.OffsetX = xoffset

    @Action()
    def reset_roi(self):
        """Sets ROI to maximum camera size"""
        self.set_roi(self.properties['HeightMax'],
                     self.properties['WidthMax'],
                     0,
                     0)

    # Helperfunctions for ROI settings
    def limit_width(self, dx):
        if dx > self.properties['WidthMax']:
            dx = self.properties['WidthMax']
        elif dx < 16:
            dx = 16
        return dx

    def limit_height(self, dy):
        if dy > self.properties['HeightMax']:
            dy = self.properties['HeightMax']
        elif dy < 16:
            dy = 16
        return dy

    def limit_xoffset(self, xoffset, dx):
        if xoffset < 0:
            xoffset = 0
        if xoffset + dx > self.properties['WidthMax']:
            xoffset = self.properties['WidthMax'] - dx
        return xoffset

    def limit_yoffset(self, yoffset, dy):
        if yoffset < 0:
            yoffset = 0
        if yoffset + dy > self.properties['HeightMax']:
            yoffset = self.properties['HeightMax'] - dy
        return yoffset

    @Action()
    def calc_roi(self, center=None, size=None, coords=None):
        """Calculate the left bottom corner and the width and height
        of a box with center (x,y) and size x [(x,y)]. Respects device
        size"""
        if center and size:
            y, x = center
            try:
                dy, dx = size
            except TypeError:
                dx = dy = size

            # Make sizes never exceed camera sizes
            dx = self.limit_width(dx)
            dy = self.limit_width(dy)

            xoffset = x - dx // 2
            yoffset = y - dy // 2

            xoffset = self.limit_xoffset(xoffset, dx)
            yoffset = self.limit_yoffset(yoffset, dy)

            return dy, dx, yoffset, xoffset

        elif coords:
            xoffset = int(coords[1][0])
            dx = int(coords[1][1] - xoffset)

            yoffset = int(coords[0][0])
            dy = int(coords[0][1] - yoffset)

            # print(dy,dx)
            dx = self.limit_width(dx)
            dy = self.limit_height(dy)

            # print(yoffset, xoffset)
            xoffset = self.limit_xoffset(xoffset, dx)
            yoffset = self.limit_yoffset(yoffset, dy)

            return dy, dx, yoffset, xoffset

        else:
            raise ValueError('center&size or coords should be supplied')

    def calc_roi_from_rel_coords(self, relcoords):
        """Calculate the new ROI from coordinates relative to the current
        viewport"""

        coords = ((self.OffsetY + relcoords[0][0],
                   self.OffsetY + relcoords[0][1]),
                  (self.OffsetX + relcoords[1][0],
                   self.OffsetX + relcoords[1][1]))
        # print('Rel_coords says new coords are', coords)
        return self.calc_roi(coords=coords)
コード例 #7
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)
コード例 #8
0
ファイル: avt.py プロジェクト: tbenst/stytra
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, **kwargs):
        # Set timeout for frame acquisition. Give this as input?
        self.timeout_ms = 1000

        super().__init__(**kwargs)

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

        self.frame = None

    def open_camera(self):
        """ """
        self.vimba.startup()
        messages = []
        # If there are multiple cameras, only the first one is used (this may
        # change):
        camera_ids = self.vimba.getCameraIds()
        if len(camera_ids) > 1:
            messages.append(
                "I:Multiple cameras detected: {}. {} wiil be used.".format(
                    camera_ids, camera_ids[0]))
        else:
            messages.append("I: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")

        return messages

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

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

        val :


        Returns
        -------

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

            else:
                # To set new frame rate for AVT cameras acquisition has to be
                # interrupted:
                messages.append("E:" + param +
                                " setting not supported on AVT cameras")
        except VimbaException:
            messages.append(
                "E:Invalid value! {} will not be changed.".format(param))
        return messages

    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

        return frame

    def release(self):
        """ """
        self.frame.waitFrameCapture(self.timeout_ms)
        self.cam.runFeatureCommand("AcquisitionStop")
        self.cam.endCapture()
        self.cam.revokeAllFrames()
        self.vimba.shutdown()
コード例 #9
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)
コード例 #10
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()