Source code for pymanip.video.ids

"""IDS Camera module (:mod:`pymanip.video.ids`)
===============================================

This module implements the :class:`pymanip.video.ids.IDS_Camera` class
using the third-party :mod:`pyueye` module.

.. autoclass:: IDS_Camera
   :members:
   :private-members:
   :show-inheritance:

"""

from datetime import datetime
import asyncio
import ctypes

import numpy as np
from pyueye import ueye
from pymanip.video import MetadataArray, Camera, CameraTimeout


[docs]class IDS_Camera(Camera): """Concrete implementation for IDS Camera. """ def __init__(self, cam_num=0): self.name = f"IDS Camera {cam_num:}" self.hCam = ueye.HIDS(cam_num) self.sInfo = ueye.SENSORINFO() self.cInfo = ueye.CAMINFO() self.pcImageMemory = ueye.c_mem_p() self.MemID = ueye.int() self.rectAOI = ueye.IS_RECT() self.pitch = ueye.INT() self.nBitsPerPixel = ueye.INT( 24 ) # 24: bits per pixel for color mode; take 8 bits per pixel for monochrome self.channels = ( 3 # 3: channels for color mode(RGB); take 1 channel for monochrome ) self.m_nColorMode = ueye.INT() # Y8/RGB16/RGB24/REG32 self.bytes_per_pixel = int(self.nBitsPerPixel / 8) # Starts the driver and establishes the connection to the camera nRet = ueye.is_InitCamera(self.hCam, None) if nRet != ueye.IS_SUCCESS: raise RuntimeError(f"is_InitCamera ERROR {nRet:}") # Reads out the data hard-coded in the non-volatile camera memory and writes it to the data structure that cInfo points to nRet = ueye.is_GetCameraInfo(self.hCam, self.cInfo) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_GetCameraInfo ERROR") # You can query additional information about the sensor type used in the camera nRet = ueye.is_GetSensorInfo(self.hCam, self.sInfo) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_GetSensorInfo ERROR") nRet = ueye.is_ResetToDefault(self.hCam) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_ResetToDefault ERROR") # Set display mode to DIB nRet = ueye.is_SetDisplayMode(self.hCam, ueye.IS_SET_DM_DIB) # Set the right color mode if ( int.from_bytes(self.sInfo.nColorMode.value, byteorder="big") == ueye.IS_COLORMODE_BAYER ): # setup the color depth to the current windows setting ueye.is_GetColorDepth(self.hCam, self.nBitsPerPixel, self.m_nColorMode) self.bytes_per_pixel = int(self.nBitsPerPixel / 8) print("IS_COLORMODE_BAYER: ") print("\tm_nColorMode: \t\t", self.m_nColorMode) print("\tnBitsPerPixel: \t\t", self.nBitsPerPixel) print("\tbytes_per_pixel: \t\t", self.bytes_per_pixel) print() elif ( int.from_bytes(self.sInfo.nColorMode.value, byteorder="big") == ueye.IS_COLORMODE_CBYCRY ): # for color camera models use RGB32 mode self.m_nColorMode = ueye.IS_CM_BGRA8_PACKED self.nBitsPerPixel = ueye.INT(32) self.bytes_per_pixel = int(self.nBitsPerPixel / 8) print("IS_COLORMODE_CBYCRY: ") print("\tm_nColorMode: \t\t", self.m_nColorMode) print("\tnBitsPerPixel: \t\t", self.nBitsPerPixel) print("\tbytes_per_pixel: \t\t", self.bytes_per_pixel) print() elif ( int.from_bytes(self.sInfo.nColorMode.value, byteorder="big") == ueye.IS_COLORMODE_MONOCHROME ): # for color camera models use RGB32 mode self.m_nColorMode = ueye.IS_CM_MONO8 self.nBitsPerPixel = ueye.INT(8) self.bytes_per_pixel = int(self.nBitsPerPixel / 8) print("IS_COLORMODE_MONOCHROME: ") print("\tm_nColorMode: \t\t", self.m_nColorMode) print("\tnBitsPerPixel: \t\t", self.nBitsPerPixel) print("\tbytes_per_pixel: \t\t", self.bytes_per_pixel) print() else: # for monochrome camera models use Y8 mode self.m_nColorMode = ueye.IS_CM_MONO8 self.nBitsPerPixel = ueye.INT(8) self.bytes_per_pixel = int(self.nBitsPerPixel / 8) # print("else") # Can be used to set the size and position of an "area of interest"(AOI) within an image nRet = ueye.is_AOI( self.hCam, ueye.IS_AOI_IMAGE_GET_AOI, self.rectAOI, ueye.sizeof(self.rectAOI), ) if nRet != ueye.IS_SUCCESS: print("is_AOI ERROR") self.width = self.rectAOI.s32Width self.height = self.rectAOI.s32Height # Prints out some information about the camera and the sensor print("Camera model:\t\t", self.sInfo.strSensorName.decode("utf-8")) print("Camera serial no.:\t", self.cInfo.SerNo.decode("utf-8")) print("Maximum image width:\t", self.width) print("Maximum image height:\t", self.height) print() nRet = ueye.is_AllocImageMem( self.hCam, self.width, self.height, self.nBitsPerPixel, self.pcImageMemory, self.MemID, ) if nRet != ueye.IS_SUCCESS: print("is_AllocImageMem ERROR") else: # Makes the specified image memory the active memory nRet = ueye.is_SetImageMem(self.hCam, self.pcImageMemory, self.MemID) if nRet != ueye.IS_SUCCESS: print("is_SetImageMem ERROR") else: # Set the desired color mode nRet = ueye.is_SetColorMode(self.hCam, self.m_nColorMode) def close(self): ueye.is_ExitCamera(self.hCam) def __exit__(self, type_, value, cb): """Context manager exit method """ super(IDS_Camera, self).__exit__(type_, value, cb) self.close()
[docs] def acquisition_oneshot(self, timeout_ms=1000): nRet = ueye.is_EnableEvent(self.hCam, ueye.IS_SET_EVENT_FRAME) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_EnableEvent ERROR") nRet = ueye.is_FreezeVideo(self.hCam, ueye.IS_DONT_WAIT) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_CaptureVideo ERROR") nRet = ueye.is_WaitEvent(self.hCam, ueye.IS_SET_EVENT_FRAME, timeout_ms) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_WaitEvent ERROR") nRet = ueye.is_InquireImageMem( self.hCam, self.pcImageMemory, self.MemID, self.width, self.height, self.nBitsPerPixel, self.pitch, ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_InquireImageMem ERROR") array = ueye.get_data( self.pcImageMemory, self.width, self.height, self.nBitsPerPixel, self.pitch, copy=True, ) nRet = ueye.is_DisableEvent(self.hCam, ueye.IS_SET_EVENT_FRAME) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_DisableEvent ERROR") return array.reshape((self.height.value, self.width.value))
[docs] async def acquisition_async( self, num=np.inf, timeout=1000, raw=False, initialising_cams=None, raise_on_timeout=True, ): """Concrete implementation """ loop = asyncio.get_event_loop() nRet = ueye.is_CaptureVideo(self.hCam, ueye.IS_DONT_WAIT) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_CaptureVideo ERROR") try: nRet = ueye.is_InquireImageMem( self.hCam, self.pcImageMemory, self.MemID, self.width, self.height, self.nBitsPerPixel, self.pitch, ) image_info = ueye.UEYEIMAGEINFO() if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_InquireImageMem ERROR") count = 0 while count < num: nRet = ueye.is_EnableEvent(self.hCam, ueye.IS_SET_EVENT_FRAME) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_EnableEvent ERROR") nRet = await loop.run_in_executor( None, ueye.is_WaitEvent, self.hCam, ueye.IS_SET_EVENT_FRAME, timeout ) if nRet == ueye.IS_TIMED_OUT: if raise_on_timeout: raise RuntimeError("Timeout") else: stop_signal = yield None if stop_signal: break else: continue elif nRet != ueye.IS_SUCCESS: raise RuntimeError("is_WaitEvent ERROR") array = ueye.get_data( self.pcImageMemory, self.width, self.height, self.nBitsPerPixel, self.pitch, copy=False, ) nRet = ueye.is_GetImageInfo( self.hCam, self.MemID, image_info, ctypes.sizeof(image_info) ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_GetImageInfo ERROR") count = count + 1 ts = datetime( image_info.TimestampSystem.wYear.value, image_info.TimestampSystem.wMonth.value, image_info.TimestampSystem.wDay.value, image_info.TimestampSystem.wHour.value, image_info.TimestampSystem.wMinute.value, image_info.TimestampSystem.wSecond.value, image_info.TimestampSystem.wMilliseconds * 1000, ) stop_signal = yield MetadataArray( array.reshape((self.height.value, self.width.value)), metadata={"counter": count, "timestamp": ts.timestamp()}, ) if stop_signal: break finally: nRet = ueye.is_StopLiveVideo(self.hCam, ueye.IS_DONT_WAIT) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_StopLiveVideo ERROR") nRet = ueye.is_DisableEvent(self.hCam, ueye.IS_SET_EVENT_FRAME) if nRet != ueye.IS_SUCCESS: raise RuntimeError("is_DisableEvent ERROR") if stop_signal: yield True
[docs] def possible_pixelclock(self): """Query the possible values for pixelclock (in MHz) """ nPixelclocks = ueye.UINT() nRet = ueye.is_PixelClock( self.hCam, ueye.IS_PIXELCLOCK_CMD_GET_NUMBER, nPixelclocks, ctypes.sizeof(nPixelclocks), ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_PIXELCLOCK_CMD_GET_NUMBER failed") if nPixelclocks.value == 0: return [] pixelclock_list = (ueye.UINT * nPixelclocks.value)() nRet = ueye.is_PixelClock( self.hCam, ueye.IS_PIXELCLOCK_CMD_GET_LIST, pixelclock_list, ctypes.sizeof(pixelclock_list), ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_PIXELCLOCK_CMD_GET_LIST failed") return [pc.value for pc in pixelclock_list]
[docs] def set_pixelclock(self, pixelclock): """Set the pixelclock (in MHz) """ pc = ueye.UINT(int(pixelclock)) nRet = ueye.is_PixelClock( self.hCam, ueye.IS_PIXELCLOCK_CMD_SET, pc, ctypes.sizeof(pc) ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_PIXELCLOCK_CMD_SET failed") return pc.value
[docs] def current_pixelclock(self): """Queries the current pixelclock (in MHz) """ pc = ueye.UINT() nRet = ueye.is_PixelClock( self.hCam, ueye.IS_PIXELCLOCK_CMD_GET, pc, ctypes.sizeof(pc) ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_PIXELCLOCK_CMD_GET failed") return pc.value
[docs] def possible_exposure_time(self): """Query the min, max and increment in ms """ min_ms = ctypes.c_double() max_ms = ctypes.c_double() inc_ms = ctypes.c_double() nRet = ueye.is_Exposure( self.hCam, ueye.IS_EXPOSURE_CMD_GET_EXPOSURE_RANGE_MIN, min_ms, ctypes.sizeof(min_ms), ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_EXPOSURE_CMD_GET_EXPOSURE_RANGE_MIN failed") nRet = ueye.is_Exposure( self.hCam, ueye.IS_EXPOSURE_CMD_GET_EXPOSURE_RANGE_MAX, max_ms, ctypes.sizeof(max_ms), ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_EXPOSURE_CMD_GET_EXPOSURE_RANGE_MAX failed") nRet = ueye.is_Exposure( self.hCam, ueye.IS_EXPOSURE_CMD_GET_EXPOSURE_RANGE_INC, inc_ms, ctypes.sizeof(inc_ms), ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_EXPOSURE_CMD_GET_EXPOSURE_RANGE_INC failed") return min_ms.value, max_ms.value, inc_ms.value
[docs] def current_exposure_time(self): """Query the current exposure time in ms """ exposure_ms = ctypes.c_double() nRet = ueye.is_Exposure( self.hCam, ueye.IS_EXPOSURE_CMD_GET_EXPOSURE, exposure_ms, ctypes.sizeof(exposure_ms), ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_EXPOSURE_CMD_GET_EXPOSURE failed") return exposure_ms.value
[docs] def set_exposure_time(self, exposure_ms): """Sets exposure time in ms. If 0 is passed, the exposure time is set to the maximum value of 1/frame rate. """ exposure_ms_double = ctypes.c_double(exposure_ms) nRet = ueye.is_Exposure( self.hCam, ueye.IS_EXPOSURE_CMD_SET_EXPOSURE, exposure_ms_double, ctypes.sizeof(exposure_ms_double), ) if nRet != ueye.IS_SUCCESS: raise RuntimeError("IS_EXPOSURE_CMD_SET_EXPOSURE failed") actual = exposure_ms_double.value if actual != exposure_ms: print("Warning: actual value of exposure time is", actual, "ms")
[docs] def set_frame_rate(self, framerate_fps): """Sets the framerate in frames per seconds """ newFPS = ctypes.c_double() nRet = ueye.is_SetFrameRate(self.hCam, float(framerate_fps), newFPS) if nRet != ueye.IS_SUCCESS: raise RuntimeError("SetFrameRate failed") if newFPS.value != framerate_fps: print("Warning actual framerate is", newFPS.value) return newFPS.value
[docs] def current_frame_rate(self): """Queries the current framerate """ fps = ctypes.c_double() nRet = ueye.is_GetFrameRate(self.hCam, fps) if nRet != ueye.IS_SUCCESS: raise RuntimeError("GetFrameRate failed") return fps.value