Skip to content
Merged
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
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ package-url = 'https://github.com/PyMoDAQ/pymodaq_plugins_opencv'
name = "pymodaq_plugins_opencv"
description = 'plugin to use camera instrumented using the opencv library'
dependencies = [
"pymodaq>=5.3.2",
"pymodaq>=5.3.9",
"pymodaq_utils>=5.3.1",
"pymodaq_gui>=5.3.0",
"pymodaq_gui>=5.3.9",
"pymodaq_data>=5.3.0",
"pymodaq_plugins_utils>=5.3.1",
"pymodaq_plugins_utils>=5.3.2",
'opencv-python',
]

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from copy import deepcopy

from pymodaq_utils.logger import set_logger, get_module_name
from pymodaq_gui.parameter import Parameter

Expand All @@ -12,22 +10,6 @@
logger = set_logger(get_module_name(__file__))


def webcam_params() -> list:
"""The settings of ``CameraBase`` that suit a webcam: colour image converted to gray by default, no exposure
time nor buffer (OpenCV sets neither, see ``Cam. Settings``)"""
params = deepcopy(cam_params)
for param in params:
if param['name'] == 'color_conversion':
param['value'] = 'RGB2GRAY'
elif param['name'] == 'buffer':
param['visible'] = False
elif param['name'] == 'timing_opts':
for child in param['children']:
if child['name'] == 'exposure_time':
child['visible'] = False
return params


class DAQ_2DViewer_OpenCV(CameraBase):
"""Cameras read with OpenCV (webcams, any device handled by ``cv2.VideoCapture``)

Expand All @@ -42,7 +24,14 @@ class DAQ_2DViewer_OpenCV(CameraBase):
[{'title': 'Camera index:', 'name': 'camera_index', 'type': 'int', 'value': 0, 'default': 0, 'min': 0},
{'title': 'Open Settings:', 'name': 'open_settings', 'type': 'bool', 'value': False},
{'title': 'Cam. Settings:', 'name': 'cam_settings', 'type': 'group', 'children': []},
] + webcam_params()
] + cam_params

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# OpenCV sets neither the exposure time nor the buffer of CameraBase, and a colour image is shown in gray
self.settings.child('timing_opts', 'exposure_time').show(False)
self.settings.child('buffer').show(False)
self.settings.child('color_conversion').setOpts(value='RGB2GRAY', default='RGB2GRAY')

def ini_detector_custom(self, controller=None):
"""Open the camera (master) or take the one of the master (slave)"""
Expand Down
13 changes: 13 additions & 0 deletions src/pymodaq_plugins_opencv/hardware/opencv_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

Frames are given as RGB, the order of OpenCV being BGR.
"""
import os
import sys
import threading
import time
Expand All @@ -27,6 +28,18 @@
from pymodaq_plugins_opencv.hardware.opencv import OpenCVProp


def _keep_qt_of_the_binding():
"""The opencv-python package (not the headless one) points Qt to the platform plugins it ships, which makes the
creation of a QApplication abort with the Qt of PyQt/PySide: restore the plugins of the Qt binding"""
cv2_dir = os.path.dirname(os.path.abspath(cv2.__file__))
for name in ('QT_QPA_PLATFORM_PLUGIN_PATH', 'QT_QPA_FONTDIR'):
if os.environ.get(name, '').startswith(cv2_dir):
del os.environ[name]


_keep_qt_of_the_binding()


class OpenCVCamera(CameraDriverBase):
"""A camera read with ``cv2.VideoCapture``

Expand Down
26 changes: 21 additions & 5 deletions tests/test_opencv_camera.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""The OpenCV camera driver and its plugin, without a webcam: a video file read by the real OpenCV, and a fake of
``cv2.VideoCapture`` for what a file cannot do (properties, failing reads, change of the frame size)"""
import importlib.util
import os
import time

import cv2
Expand All @@ -24,7 +25,7 @@

from pymodaq_plugins_utils.hardware.camera_driver import CameraDriverBase

from pymodaq_plugins_opencv.hardware.opencv_camera import OpenCVCamera
from pymodaq_plugins_opencv.hardware.opencv_camera import OpenCVCamera, _keep_qt_of_the_binding
from pymodaq_plugins_opencv.daq_viewer_plugins.plugins_2D.daq_2Dviewer_OpenCV import DAQ_2DViewer_OpenCV

WIDTH, HEIGHT = 64, 48
Expand Down Expand Up @@ -116,12 +117,27 @@ def acquire(driver: OpenCVCamera, nframes=1) -> np.ndarray:
return driver.read_multiple_images()


def click_led(plugin, name: str):
"""What the user does: press the (checkable) button of the parameter, which the DAQ_Viewer sends to the plugin"""
param = plugin.settings.child('roi', name)
param.opts['checked'] = True
param.activate()


def apply_roi(plugin, rows: slice, columns: slice):
plugin.settings.child('roi', 'update_roi').setValue(True)
plugin.roi_select(RoiInfo.from_slices([rows, columns]))
param = plugin.settings.child('roi', 'apply_roi')
param.setValue(True)
plugin.commit_settings(param)
click_led(plugin, 'update_roi')
click_led(plugin, 'apply_roi')


def test_the_qt_plugins_of_opencv_python_are_forgotten(monkeypatch):
cv2_qt = os.path.join(os.path.dirname(os.path.abspath(cv2.__file__)), 'qt', 'plugins')
monkeypatch.setenv('QT_QPA_PLATFORM_PLUGIN_PATH', cv2_qt)
_keep_qt_of_the_binding()
assert 'QT_QPA_PLATFORM_PLUGIN_PATH' not in os.environ
monkeypatch.setenv('QT_QPA_PLATFORM_PLUGIN_PATH', '/my/own/plugins') # not the one of OpenCV: left alone
_keep_qt_of_the_binding()
assert os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] == '/my/own/plugins'


class TestVideoFile:
Expand Down
Loading