Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVT Camera #142

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/publish_docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Workflow to build the docs (with sphinx) and deploy the build to GitHub Pages
# note: parts of this workflow were copied directly from GitHub's suggested workflows
name: Build and deploy docs

on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow one concurrent deployment
concurrency:
group: "pages"
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Pages
id: pages
uses: actions/configure-pages@v3
- name: Install dependencies
working-directory: ./docs
run: |
python -m pip install --upgrade pip
pip install -r requirements-docs.txt
- name: Build the docs
working-directory: ./docs
run: make build
- name: Upload build artifacts
uses: actions/upload-pages-artifact@v1
with:
path: './docs/build/html'

deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
2 changes: 1 addition & 1 deletion .github/workflows/test_pull_requests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install black
pip install black==22.12.0
- name: Check code styling with Black
run: |
black --diff -S -t py39 copylot
Expand Down
4 changes: 3 additions & 1 deletion copylot/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ def __init__(self, *args, **kwargs):
) as json_file:
self.defaults = json.load(json_file)

except FileNotFoundError: # construct initial defaults.txt fileself.defaults = [3, 6, 25, 100]
except (
FileNotFoundError
): # construct initial defaults.txt fileself.defaults = [3, 6, 25, 100]
if not os.path.isdir(os.path.join(str(Path.home()), ".coPylot")):
os.mkdir(os.path.join(str(Path.home()), ".coPylot"))

Expand Down
Empty file.
115 changes: 115 additions & 0 deletions copylot/hardware/cameras/avt/camera.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import sys
from enum import Enum
from typing import Tuple

from copylot.hardware.cameras.abstract_camera import AbstractCamera
from copylot.hardware.cameras.avt.vimba import Vimba


class BinningMode(Enum):
AVERAGE = "Average"
SUM = "Sum"


class AVTCameraException(Exception):
pass


class AVTCamera(AbstractCamera):
def __init__(self, nb_camera = 1):
self.nb_camera = nb_camera

self._exposure_time = None

# Internal variables used to keep track of the number of
# > total images
# > incomplete frames
# > frames dropped (i.e the caller attempted to get an image but none were in the queue),
# > times a frame was attempted to be placed in the queue but failed because the queue was full
self.all_count = 0
self.incomplete_count = 0
self.dropped_count = 0
self.full_count = 0

self._isActivated = False
# self.queue: queue.Queue[Tuple[np.ndarray, float]] = queue.Queue(maxsize=1)

@property
def temperature(self) -> float:
"""Get the device temperature

Returns
-------
float

"""
try:
return self.camera.DeviceTemperature.get()
except Exception as e:
print(
f"Could not get the device temperature using DeviceTemperature: {e}"
)
raise e

@property
def exposure_bounds(self):
try:
exposure_bounds = []
with Vimba.get_instance() as vimba:
for cam in vimba.get_all_cameras():
with cam:
exposure_bounds.append(
(
cam.ExposureAutoMin.get() / 1000,
cam.ExposureAutoMax.get() / 1000
)
)
return exposure_bounds
except Exception as e:
print(
f"Could not get exposure using ExposureAutoMin / ExposureAutoMax: {e}"
)
raise e

@property
def exposure_time(self):
return self._exposure_time

@exposure_time.setter
def exposure_time(self, cam_index_and_value: Tuple[int, int]):
camera_index, value = cam_index_and_value
min_exposure, max_exposure = self.exposure_bounds[camera_index]
if min_exposure <= value <= max_exposure:
try:
with Vimba.get_instance() as vimba:
camera = vimba.get_all_cameras()[camera_index]
camera.ExposureTime.set(value * 1000)

self._exposure_time = camera.ExposureTime.get() / 1000

print(f"Exposure time set to {self.exposure_time} ms.")
except Exception as e:
print(f"Failed to set exposure: {e}")
raise e
else:
raise ValueError(
f"value out of range: must be in "
f"[{min_exposure}, {max_exposure}], but value_ms={value}"
)

@staticmethod
def acquire_single_frame():
with Vimba.get_instance() as vimba:
cams = vimba.get_all_cameras()
with cams[0] as cam:
# Acquire single frame synchronously
frame = cam.get_frame()

return frame

# def start_acquisition(self):
# with Vimba.get_instance() as vimba:
# cams = vimba.get_all_cameras()
# if self.nb_camera == 1:
# with cams[0] as cam:

Empty file.
23 changes: 23 additions & 0 deletions copylot/hardware/cameras/avt/demo/camera.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from time import perf_counter

from copylot.hardware.cameras.avt.camera import AVTCamera


def main():
camera = AVTCamera()

# acquire single frame
start_time = perf_counter()
AVTCamera().acquire_single_frame()
stop_time = perf_counter()
print(stop_time - start_time)

# get exposure bounds for all available cameras
print(camera.exposure_bounds)

# check temperature
print(camera.temperature)


if __name__ == '__main__':
main()
128 changes: 128 additions & 0 deletions copylot/hardware/cameras/avt/vimba/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"""BSD 2-Clause License

Copyright (c) 2019, Allied Vision Technologies GmbH
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

# Suppress 'imported but unused' - Error from static style checker.
# flake8: noqa: F401

__version__ = '1.2.1'

__all__ = [
'Vimba',
'Camera',
'CameraChangeHandler',
'CameraEvent',
'AccessMode',
'PersistType',
'Interface',
'InterfaceType',
'InterfaceChangeHandler',
'InterfaceEvent',
'PixelFormat',
'Frame',
'FeatureTypes',
'FrameHandler',
'FrameStatus',
'AllocationMode',
'Debayer',
'intersect_pixel_formats',
'MONO_PIXEL_FORMATS',
'BAYER_PIXEL_FORMATS',
'RGB_PIXEL_FORMATS',
'RGBA_PIXEL_FORMATS',
'BGR_PIXEL_FORMATS',
'BGRA_PIXEL_FORMATS',
'YUV_PIXEL_FORMATS',
'YCBCR_PIXEL_FORMATS',
'COLOR_PIXEL_FORMATS',
'OPENCV_PIXEL_FORMATS',

'VimbaSystemError',
'VimbaCameraError',
'VimbaInterfaceError',
'VimbaFeatureError',
'VimbaFrameError',
'VimbaTimeout',

'IntFeature',
'FloatFeature',
'StringFeature',
'BoolFeature',
'EnumEntry',
'EnumFeature',
'CommandFeature',
'RawFeature',

'LogLevel',
'LogConfig',
'Log',
'LOG_CONFIG_TRACE_CONSOLE_ONLY',
'LOG_CONFIG_TRACE_FILE_ONLY',
'LOG_CONFIG_TRACE',
'LOG_CONFIG_INFO_CONSOLE_ONLY',
'LOG_CONFIG_INFO_FILE_ONLY',
'LOG_CONFIG_INFO',
'LOG_CONFIG_WARNING_CONSOLE_ONLY',
'LOG_CONFIG_WARNING_FILE_ONLY',
'LOG_CONFIG_WARNING',
'LOG_CONFIG_ERROR_CONSOLE_ONLY',
'LOG_CONFIG_ERROR_FILE_ONLY',
'LOG_CONFIG_ERROR',
'LOG_CONFIG_CRITICAL_CONSOLE_ONLY',
'LOG_CONFIG_CRITICAL_FILE_ONLY',
'LOG_CONFIG_CRITICAL',

'TraceEnable',
'ScopedLogEnable',
'RuntimeTypeCheckEnable'
]

# Import everything exported from the top level module
from .vimba import Vimba

from .camera import AccessMode, PersistType, Camera, CameraChangeHandler, CameraEvent, FrameHandler

from .interface import Interface, InterfaceType, InterfaceChangeHandler, InterfaceEvent

from .frame import PixelFormat, Frame, Debayer, intersect_pixel_formats, MONO_PIXEL_FORMATS, \
BAYER_PIXEL_FORMATS, RGB_PIXEL_FORMATS, RGBA_PIXEL_FORMATS, BGR_PIXEL_FORMATS, \
BGRA_PIXEL_FORMATS, YUV_PIXEL_FORMATS, YCBCR_PIXEL_FORMATS, \
COLOR_PIXEL_FORMATS, OPENCV_PIXEL_FORMATS, FrameStatus, FeatureTypes, \
AllocationMode

from .error import VimbaSystemError, VimbaCameraError, VimbaInterfaceError, VimbaFeatureError, \
VimbaFrameError, VimbaTimeout

from .feature import IntFeature, FloatFeature, StringFeature, BoolFeature, EnumEntry, EnumFeature, \
CommandFeature, RawFeature

from .util import Log, LogLevel, LogConfig, LOG_CONFIG_TRACE_CONSOLE_ONLY, \
LOG_CONFIG_TRACE_FILE_ONLY, LOG_CONFIG_TRACE, LOG_CONFIG_INFO_CONSOLE_ONLY, \
LOG_CONFIG_INFO_FILE_ONLY, LOG_CONFIG_INFO, LOG_CONFIG_WARNING_CONSOLE_ONLY, \
LOG_CONFIG_WARNING_FILE_ONLY, LOG_CONFIG_WARNING, LOG_CONFIG_ERROR_CONSOLE_ONLY, \
LOG_CONFIG_ERROR_FILE_ONLY, LOG_CONFIG_ERROR, LOG_CONFIG_CRITICAL_CONSOLE_ONLY, \
LOG_CONFIG_CRITICAL_FILE_ONLY, LOG_CONFIG_CRITICAL, ScopedLogEnable, \
TraceEnable, RuntimeTypeCheckEnable
Loading