-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from zauberzeug/active-cameras
Unify camera providers
- Loading branch information
Showing
49 changed files
with
1,644 additions
and
868 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/usr/bin/env python3 | ||
import logging | ||
|
||
from nicegui import ui | ||
|
||
import rosys.vision | ||
|
||
|
||
def add_card(camera: rosys.vision.Camera, container: ui.element) -> None: | ||
uid = camera.id | ||
if uid not in streams: | ||
with container: | ||
camera_card = ui.card().tight() | ||
camera_cards[uid] = camera_card | ||
print(f'adding card for {uid}') | ||
with camera_grid: | ||
with camera_card: | ||
streams[uid] = ui.interactive_image() | ||
ui.label(uid).classes('m-2') | ||
with ui.row(): | ||
ui.switch('stream').bind_value(camera, 'streaming') | ||
ui.button('capture', on_click=camera.capture_image) | ||
ui.button('disconnect', on_click=camera.disconnect).bind_enabled_from(camera, 'is_connected') | ||
if isinstance(camera, rosys.vision.ConfigurableCamera): | ||
create_camera_settings_panel(camera) | ||
|
||
streams[uid].set_source(camera.get_latest_image_url()) | ||
|
||
|
||
def create_camera_settings_panel(camera: rosys.vision.ConfigurableCamera) -> None: | ||
camera_parameters = camera.get_capabilities() | ||
parameter_names = [parameter.name for parameter in camera_parameters] | ||
with ui.expansion('Settings').classes('w-full').bind_enabled_from(camera, 'is_connected'): | ||
if isinstance(camera, rosys.vision.RtspCamera): | ||
ui.label('URL') \ | ||
.bind_text_from(camera, 'url', backward=lambda x: x or 'URL not available') | ||
if 'fps' in parameter_names: | ||
with ui.card(), ui.row(): | ||
ui.label('FPS:') | ||
ui.select(options=list(range(1, 31)), on_change=lambda e: camera.set_parameters({'fps': e.value})) \ | ||
.bind_value_from(camera, 'parameters', backward=lambda params: params['fps']) | ||
if 'jovision_profile' in parameter_names: | ||
with ui.card(): | ||
ui.switch('High Quality', | ||
on_change=lambda e: camera.set_parameters({'jovision_profile': 0 if e.value else 1})) | ||
if 'exposure' in parameter_names: | ||
with ui.card(), ui.row(): | ||
ui.label('Exposure:') | ||
ui.select(options=list(range(0, 255)), on_change=lambda e: camera.set_parameters({'exposure': e.value})) \ | ||
.bind_value_from(camera, 'parameters', backward=lambda params: params['exposure']) | ||
if 'auto_exposure' in parameter_names: | ||
with ui.card(): | ||
ui.switch('Auto Exposure', on_change=lambda e: camera.set_parameters({'auto_exposure': e.value})) \ | ||
.bind_value_from(camera, 'parameters', backward=lambda params: params['auto_exposure']) | ||
if 'color' in parameter_names: | ||
with ui.card(), ui.row(): | ||
ui.label('Color:') | ||
with ui.button(icon='colorize'): | ||
ui.color_picker(on_pick=lambda e: camera.set_parameters({'color': e.color})) | ||
|
||
|
||
def update_camera_cards() -> None: | ||
providers: list[rosys.vision.CameraProvider] = [ | ||
rtsp_camera_provider, | ||
usb_camera_provider, | ||
simulated_camera_provider, | ||
] | ||
for provider in providers: | ||
for camera in provider.cameras.values(): | ||
add_card(camera, camera_grid) | ||
|
||
|
||
logging.basicConfig(level=logging.INFO) | ||
streams: dict[str, ui.interactive_image] = {} | ||
camera_cards: dict[str, ui.card] = {} | ||
camera_grid = ui.row() | ||
|
||
rtsp_camera_provider = rosys.vision.RtspCameraProvider() | ||
usb_camera_provider = rosys.vision.UsbCameraProvider() | ||
simulated_camera_provider = rosys.vision.SimulatedCameraProvider() | ||
|
||
ui.timer(0.1, update_camera_cards) | ||
|
||
simulated_camera_provider.add_cameras(1) | ||
|
||
ui.run(title='RoSys', port=8080) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,11 @@ | ||
#!/usr/bin/env python3 | ||
from nicegui import ui | ||
|
||
from rosys.vision import UsbCameraProviderSimulation, camera_provider | ||
from rosys.vision import ImageSize, SimulatedCamera | ||
|
||
camera_provider = UsbCameraProviderSimulation() | ||
camera_provider.add_camera(camera_provider.create_calibrated('test_cam', width=800, height=600)) | ||
camera = SimulatedCamera(id='test_cam', resolution=ImageSize(width=800, height=600)) | ||
|
||
|
||
def refresh() -> None: | ||
for uid, camera in camera_provider.cameras.items(): | ||
if uid not in feeds: | ||
feeds[uid] = ui.interactive_image() | ||
feeds[uid].set_source(camera_provider.get_latest_image_url(camera)) | ||
|
||
|
||
feeds: dict[str, ui.interactive_image] = {} | ||
ui.timer(0.3, refresh) | ||
image = ui.interactive_image() | ||
ui.timer(0.3, lambda: image.set_source(camera.get_latest_image_url())) | ||
|
||
ui.run(title='RoSys') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,14 @@ | ||
from .calibration import Calibration, Extrinsics, Intrinsics | ||
from .camera import Camera | ||
from .camera import CalibratableCamera, Camera, ConfigurableCamera, TransformableCamera | ||
from .camera_objects_ import CameraObjects as camera_objects | ||
from .camera_projector import CameraProjector | ||
from .camera_provider import CameraProvider | ||
from .combining_camera_provider import CombiningCameraProvider | ||
from .detections import BoxDetection, Detection, Detections, PointDetection | ||
from .detector import Autoupload, Detector | ||
from .detector_hardware import DetectorHardware | ||
from .detector_simulation import DetectorSimulation, SimulatedObject | ||
from .image import Image, ImageSize | ||
from .multi_camera_provider import MultiCameraProvider | ||
from .rtsp_camera import RtspCamera | ||
from .rtsp_camera_provider_hardware import RtspCameraProviderHardware | ||
from .usb_camera import UsbCamera | ||
from .usb_camera_provider_hardware import UsbCameraProviderHardware | ||
from .usb_camera_provider_simulation import UsbCameraProviderSimulation | ||
from .rtsp_camera import RtspCamera, RtspCameraProvider | ||
from .simulated_camera import SimulatedCamera, SimulatedCameraProvider | ||
from .usb_camera import UsbCamera, UsbCameraProvider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from .calibratable_camera import CalibratableCamera | ||
from .camera import Camera | ||
from .configurable_camera import ConfigurableCamera | ||
from .transformable_camera import TransformableCamera | ||
|
||
__all__ = [ | ||
'CalibratableCamera', | ||
'Camera', | ||
'ConfigurableCamera', | ||
'TransformableCamera', | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from typing import Optional, Self | ||
|
||
import numpy as np | ||
|
||
from ...geometry import Rotation | ||
from ..calibration import Calibration, Extrinsics, Intrinsics | ||
from .camera import Camera | ||
|
||
|
||
class CalibratableCamera(Camera): | ||
|
||
def __init__(self, **kwargs) -> None: | ||
super().__init__(**kwargs) | ||
self.calibration: Optional[Calibration] = None | ||
self.focal_length: Optional[float] = None | ||
|
||
@property | ||
def is_calibrated(self) -> bool: | ||
return self.calibration is not None | ||
|
||
@classmethod | ||
def create_calibrated(cls, *, | ||
width: int = 800, height: int = 600, | ||
x: float = 0.0, y: float = 0.0, z: float = 1.0, | ||
roll: float = np.pi, pitch: float = 0.0, yaw: float = 0.0, | ||
**kwargs) -> Self: | ||
camera = cls(**kwargs) | ||
camera.set_perfect_calibration(width=width, height=height, x=x, y=y, z=z, roll=roll, pitch=pitch, yaw=yaw) | ||
return camera | ||
|
||
def set_perfect_calibration(self, *, | ||
width=800, height=600, | ||
x: float = 0.0, y: float = 0.0, z: float = 1.0, | ||
roll: float = np.pi, pitch: float = 0.0, yaw: float = 0.0) -> None: | ||
self.calibration = Calibration( | ||
intrinsics=Intrinsics.create_default(width, height), | ||
extrinsics=Extrinsics(rotation=Rotation.from_euler(roll, pitch, yaw), translation=[x, y, z]), | ||
) |
Oops, something went wrong.