-
Notifications
You must be signed in to change notification settings - Fork 23
Description
from threading import Condition
import cv2
from seekcamera import (
SeekCameraFrameHeader,
SeekCameraManagerEvent,
SeekCameraIOType,
SeekCameraColorPalette,
SeekCameraColorPaletteData,
SeekCameraFilter,
SeekCameraFilterState,
SeekCameraAGCMode,
SeekCameraLinearAGCLockMode,
SeekCameraShutterMode,
SeekCameraTemperatureUnit,
SeekCameraManager,
SeekCamera,
SeekCameraFrameFormat,
SeekFrame,
)
from seekcamera.camera import (
SeekCameraFrame,
SeekCameraHistEQAGCGainLimitFactorMode,
SeekCameraHistEQAGCPlateauRedistributionMode)
#SeekCameraColorPalette.USER_0 = SeekCameraColorPaletteData()
#for index, value in enumerate(SeekCameraColorPalette.USER_0): print(value)
#SeekCameraColorPaletteData.USER_0 = (1:4), [(255, 0, 0, 0), (0, 0, 0, 0), (160, 0, 0, 0)]
class Renderer:
"""Contains camera and image data required to render images to the screen."""
def __init__(self):
self.busy = False
self.frame = SeekFrame()
self.camera = SeekCamera()
self.frame_condition = Condition()
self.first_frame = True
def on_frame(_camera, camera_frame, renderer):
"""Async callback fired whenever a new frame is available.
Parameters
----------
_camera: SeekCamera
Reference to the camera for which the new frame is available.
camera_frame: SeekCameraFrame
Reference to the class encapsulating the new frame (potentially
in multiple formats).
renderer: Renderer
User defined data passed to the callback. This can be anything
but in this case it is a reference to the renderer object.
"""
# Acquire the condition variable and notify the main thread
# that a new frame is ready to render. This is required since
# all rendering done by OpenCV needs to happen on the main thread.
with renderer.frame_condition:
renderer.frame = camera_frame.color_argb8888
renderer.frame_condition.notify()
def on_event(camera, event_type, event_status, renderer):
"""Async callback fired whenever a camera event occurs.
Parameters
----------
camera: SeekCamera
Reference to the camera on which an event occurred.
event_type: SeekCameraManagerEvent
Enumerated type indicating the type of event that occurred.
event_status: Optional[SeekCameraError]
Optional exception type. It will be a non-None derived instance of
SeekCameraError if the event_type is SeekCameraManagerEvent.ERROR.
renderer: Renderer
User defined data passed to the callback. This can be anything
but in this case it is a reference to the Renderer object.
"""
print("{}: {}".format(str(event_type), camera.chipid))
if event_type == SeekCameraManagerEvent.CONNECT:
if renderer.busy:
return
# Claim the renderer.
# This is required in case of multiple cameras.
renderer.busy = True
renderer.camera = camera
# Indicate the first frame has not come in yet.
# This is required to properly resize the rendering window.
renderer.first_frame = True
# Set a custom color palette.
# Other options can set in a similar fashion.
camera.color_palette = SeekCameraColorPalette.USER_0
palette_data = SeekCameraColorPaletteData()
for i in range(256):
palette_data[i] = (i, i, i, 255)
palette_data[125] = (160, 0, 0, 0)
camera.color_palette = SeekCameraColorPalette.USER_0 #
#camera.set_color_palette_data(SeekCameraColorPalette.HI, palette_data)
#camera.set_color_palette_data(SeekCameraColorPalette.HI, palette_data)
# Start imaging and provide a custom callback to be called
# every time a new frame is received.
camera.agc_mode = SeekCameraAGCMode(0)
camera.temperature_unit = SeekCameraTemperatureUnit.CELSIUS
camera.termography_window = SeekCamera.thermography_window.getter(320)
camera.plateau = SeekCameraHistEQAGCPlateauRedistributionMode.ACTIVE_BINS_ONLY
#camera.gradient_correction_filter_state(0)
#camera.flat_scene_correction_filter_state
SeekCamera.shutter_trigger
#SeekCamera.histeq_agc_trim_left.setter(100)
#SeekCamera.histeq_agc_trim_right.setter(100)
SeekCamera.scene_emissivity.setter(250)
SeekCamera.thermography_window.getter(10)
SeekCamera.thermography_offset.setter(10)
SeekCameraFrameHeader.environment_temperature.setter(700)
SeekCameraFrameHeader.thermography_max.setter(1000.0)
SeekCameraFrameHeader.thermography_min.setter(3500.0)
camera.set_filter_state = SeekCameraFilterState.DISABLED
camera.register_frame_available_callback(on_frame, renderer)
camera.capture_session_start(SeekCameraFrameFormat.COLOR_ARGB8888)
camera.set_filter_state = SeekCameraFilter.GRADIENT_CORRECTION
camera.shutter_mode = SeekCameraShutterMode.AUTO
camera.histeq_agc_num_bins = 1
camera.linear_agc_lock_mode = SeekCameraLinearAGCLockMode.MANUAL
camera.linear_agc_lock_min = 2800
camera.linear_agc_lock_max = 10000
camera.histeq_agc_gain_limit_factor_mode = SeekCameraHistEQAGCGainLimitFactorMode.AUTO
camera.histeq_agc_gain_limit_factor_ymin = 0.90
camera.histeq_agc_gain_limit_factor_xmax = 5000
elif event_type == SeekCameraManagerEvent.DISCONNECT:
# Check that the camera disconnecting is one actually associated with
# the renderer. This is required in case of multiple cameras.
if renderer.camera == camera:
# Stop imaging and reset all the renderer state.
camera.capture_session_stop()
renderer.camera = None
renderer.frame = None
renderer.busy = False
elif event_type == SeekCameraManagerEvent.ERROR:
print("{}: {}".format(str(event_status), camera.chipid))
elif event_type == SeekCameraManagerEvent.READY_TO_PAIR:
return
def main():
window_name = "DARL 4.0 Termica by E+S AiR"
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
# Create a context structure responsible for managing all connected USB cameras.
# Cameras with other IO types can be managed by using a bitwise or of the
# SeekCameraIOType enum cases.
with SeekCameraManager(SeekCameraIOType.USB) as manager:
# Start listening for events.
renderer = Renderer()
manager.register_event_callback(on_event, renderer)
while True:
# Wait a maximum of 150ms for each frame to be received.
# A condition variable is used to synchronize the access to the renderer;
# it will be notified by the user defined frame available callback thread.
with renderer.frame_condition:
if renderer.frame_condition.wait(150.0 / 1000.0):
img = renderer.frame.data
# Resize the rendering window.
if renderer.first_frame:
(height, width, _) = img.shape
cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.resizeWindow(window_name, width * 20, height * 20)
renderer.first_frame = False
# Render the image to the window.
cv2.imshow(window_name, img)
# Process key events.
key = cv2.waitKey(1)
if key == ord("q"):
break
# Check if the window has been closed manually.
if not cv2.getWindowProperty(window_name, cv2.WND_PROP_VISIBLE):
break
cv2.destroyWindow(window_name)
if name == "main":
main()