QVideo 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. QVideo/QCamcorder.py +125 -0
  2. QVideo/__init__.py +5 -0
  3. QVideo/cameras/Basler/QBaslerCamera.py +50 -0
  4. QVideo/cameras/Basler/QBaslerTree.py +67 -0
  5. QVideo/cameras/Basler/__init__.py +5 -0
  6. QVideo/cameras/Flir/QFlirCamera.py +48 -0
  7. QVideo/cameras/Flir/QFlirTree.py +70 -0
  8. QVideo/cameras/Flir/QListFlirCameras.py +31 -0
  9. QVideo/cameras/Flir/__init__.py +5 -0
  10. QVideo/cameras/Genicam/QGenicamCamera.py +382 -0
  11. QVideo/cameras/Genicam/QGenicamTree.py +224 -0
  12. QVideo/cameras/Genicam/__init__.py +5 -0
  13. QVideo/cameras/IDS/QIDSCamera.py +49 -0
  14. QVideo/cameras/IDS/QIDSTree.py +65 -0
  15. QVideo/cameras/IDS/__init__.py +5 -0
  16. QVideo/cameras/MV/QMVCamera.py +55 -0
  17. QVideo/cameras/MV/QMVTree.py +65 -0
  18. QVideo/cameras/MV/__init__.py +5 -0
  19. QVideo/cameras/Noise/QNoiseCamera.py +144 -0
  20. QVideo/cameras/Noise/QNoiseTree.py +35 -0
  21. QVideo/cameras/Noise/__init__.py +5 -0
  22. QVideo/cameras/OpenCV/QListCVCameras.py +73 -0
  23. QVideo/cameras/OpenCV/QOpenCVCamera.py +224 -0
  24. QVideo/cameras/OpenCV/QOpenCVTree.py +59 -0
  25. QVideo/cameras/OpenCV/__init__.py +5 -0
  26. QVideo/cameras/Picamera/QPicamera.py +229 -0
  27. QVideo/cameras/Picamera/QPicameraTree.py +47 -0
  28. QVideo/cameras/Picamera/__init__.py +5 -0
  29. QVideo/cameras/Vimbax/QVimbaXCamera.py +51 -0
  30. QVideo/cameras/Vimbax/QVimbaXTree.py +37 -0
  31. QVideo/cameras/Vimbax/__init__.py +5 -0
  32. QVideo/cameras/__init__.py +0 -0
  33. QVideo/dvr/QDVRWidget.py +354 -0
  34. QVideo/dvr/QHDF5Reader.py +93 -0
  35. QVideo/dvr/QHDF5Writer.py +89 -0
  36. QVideo/dvr/QOpenCVReader.py +98 -0
  37. QVideo/dvr/QOpenCVWriter.py +144 -0
  38. QVideo/dvr/__init__.py +14 -0
  39. QVideo/dvr/icons_rc.py +1082 -0
  40. QVideo/dvr/icons_rc_qt6.py +1106 -0
  41. QVideo/filters/Median.py +89 -0
  42. QVideo/filters/MoMedian.py +63 -0
  43. QVideo/filters/Normalize.py +142 -0
  44. QVideo/filters/QBlurFilter.py +101 -0
  45. QVideo/filters/QEdgeFilter.py +162 -0
  46. QVideo/filters/QRGBFilter.py +97 -0
  47. QVideo/filters/QSampleHold.py +141 -0
  48. QVideo/filters/_MedianBase.py +104 -0
  49. QVideo/filters/__init__.py +17 -0
  50. QVideo/lib/QCamera.py +387 -0
  51. QVideo/lib/QCameraTree.py +212 -0
  52. QVideo/lib/QFPSMeter.py +90 -0
  53. QVideo/lib/QFilterBank.py +118 -0
  54. QVideo/lib/QListCameras.py +87 -0
  55. QVideo/lib/QVideoReader.py +227 -0
  56. QVideo/lib/QVideoScreen.py +173 -0
  57. QVideo/lib/QVideoSource.py +196 -0
  58. QVideo/lib/QVideoWriter.py +123 -0
  59. QVideo/lib/VideoFilter.py +149 -0
  60. QVideo/lib/__init__.py +17 -0
  61. QVideo/lib/chooser.py +118 -0
  62. QVideo/lib/clickable.py +43 -0
  63. QVideo/lib/resolutions.py +46 -0
  64. QVideo/lib/types.py +6 -0
  65. QVideo/version.py +4 -0
  66. qvideo-3.0.0.dist-info/METADATA +161 -0
  67. qvideo-3.0.0.dist-info/RECORD +70 -0
  68. qvideo-3.0.0.dist-info/WHEEL +5 -0
  69. qvideo-3.0.0.dist-info/licenses/LICENSE.md +17 -0
  70. qvideo-3.0.0.dist-info/top_level.txt +1 -0
QVideo/QCamcorder.py ADDED
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env python3
2
+ '''Composite camcorder widget combining a video screen, camera controls, and DVR.
3
+
4
+ Run directly to launch a full camcorder application with camera selection::
5
+
6
+ python -m QVideo.QCamcorder [-c|-f|-s|-v] [cameraID]
7
+
8
+ Camera flags (mutually exclusive):
9
+
10
+ .. code-block:: text
11
+
12
+ -b [cameraID] Basler camera (requires pylon SDK)
13
+ -c [cameraID] OpenCV camera
14
+ -f [cameraID] FLIR camera (requires Spinnaker SDK)
15
+ -i [cameraID] IDS Imaging camera (requires IDS peak SDK)
16
+ -m [cameraID] MATRIX VISION mvGenTLProducer (universal GenICam, not FLIR)
17
+ -p [cameraID] Raspberry Pi camera module (requires picamera2)
18
+ -v [cameraID] Allied Vision VimbaX camera
19
+
20
+ If no flag is given, a noise camera is used as a fallback.
21
+ '''
22
+
23
+ from pyqtgraph.Qt.QtWidgets import QWidget
24
+ from pyqtgraph.Qt.QtCore import pyqtSlot
25
+ from pyqtgraph.Qt import QtGui, uic
26
+ from QVideo.lib import QCameraTree, QVideoSource
27
+ from pathlib import Path
28
+
29
+
30
+ __all__ = ['QCamcorder']
31
+
32
+
33
+ class QCamcorder(QWidget):
34
+ '''A widget combining a video screen, camera controls, and DVR.
35
+
36
+ Lays out a :class:`~QVideo.lib.QVideoScreen.QVideoScreen` alongside
37
+ a :class:`~QVideo.dvr.QDVRWidget.QDVRWidget` and an arbitrary
38
+ :class:`~QVideo.lib.QCameraTree.QCameraTree` control panel. Live
39
+ frames from the camera source are routed to the screen; when the DVR
40
+ starts playback the screen is switched to the playback stream and the
41
+ camera controls are disabled until playback ends.
42
+
43
+ Parameters
44
+ ----------
45
+ cameraWidget : QCameraTree
46
+ Camera control tree to embed in the controls panel.
47
+ *args :
48
+ Additional positional arguments forwarded to
49
+ :class:`~pyqtgraph.Qt.QtWidgets.QWidget`.
50
+ **kwargs :
51
+ Additional keyword arguments forwarded to
52
+ :class:`~pyqtgraph.Qt.QtWidgets.QWidget`.
53
+ '''
54
+
55
+ UIFILE = Path(__file__).parent / 'QCamcorder.ui'
56
+
57
+ def __init__(self,
58
+ cameraWidget: QCameraTree,
59
+ *args, **kwargs) -> None:
60
+ super().__init__(*args, **kwargs)
61
+ self.cameraWidget = cameraWidget
62
+ self._setupUi()
63
+ self._connectSignals()
64
+ self.screen.source = self.source
65
+ self.dvr.source = self.source
66
+
67
+ def _setupUi(self) -> None:
68
+ uic.loadUi(str(self.UIFILE), self)
69
+ self.controls.layout().addWidget(self.cameraWidget)
70
+
71
+ def _connectSignals(self) -> None:
72
+ self.dvr.playing.connect(self.dvrPlayback)
73
+
74
+ def closeEvent(self, event: QtGui.QCloseEvent) -> None:
75
+ '''Stop the camera source when the widget is closed.'''
76
+ self.cameraWidget.stop()
77
+ super().closeEvent(event)
78
+
79
+ @pyqtSlot(bool)
80
+ def dvrPlayback(self, playback: bool) -> None:
81
+ '''Switch the screen source between live camera and DVR playback.
82
+
83
+ Connected to :attr:`~QVideo.dvr.QDVRWidget.QDVRWidget.playing`.
84
+ When playback starts the camera source is disconnected from the
85
+ screen and the DVR's :attr:`~QVideo.dvr.QDVRWidget.QDVRWidget.newFrame`
86
+ signal is connected instead; the camera controls are disabled.
87
+ When playback ends the connections are reversed and the controls
88
+ are re-enabled.
89
+
90
+ Parameters
91
+ ----------
92
+ playback : bool
93
+ ``True`` when DVR playback begins, ``False`` when it ends.
94
+ '''
95
+ try:
96
+ if playback:
97
+ self.source.newFrame.disconnect(self.screen.setImage)
98
+ self.dvr.newFrame.connect(self.screen.setImage)
99
+ else:
100
+ self.dvr.newFrame.disconnect(self.screen.setImage)
101
+ self.source.newFrame.connect(self.screen.setImage)
102
+ except (RuntimeError, TypeError):
103
+ pass
104
+ self.cameraWidget.setDisabled(playback)
105
+
106
+ @property
107
+ def source(self) -> QVideoSource:
108
+ '''The :class:`~QVideo.lib.QVideoSource.QVideoSource` from the camera widget.'''
109
+ return self.cameraWidget.source
110
+
111
+
112
+ def main() -> None: # pragma: no cover
113
+ '''Launch the camcorder with an interactively chosen camera.'''
114
+ import pyqtgraph as pg
115
+ from QVideo.lib import choose_camera
116
+
117
+ pg.mkQApp()
118
+ camera = choose_camera()
119
+ widget = QCamcorder(camera.start())
120
+ widget.show()
121
+ pg.exec()
122
+
123
+
124
+ if __name__ == '__main__':
125
+ main()
QVideo/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ from QVideo.lib import QVideoScreen
2
+ from QVideo.version import *
3
+
4
+
5
+ __all__ = ['QVideoScreen']
@@ -0,0 +1,50 @@
1
+ from QVideo.cameras.Genicam import QGenicamCamera, QGenicamSource
2
+
3
+
4
+ __all__ = ['QBaslerCamera', 'QBaslerSource']
5
+
6
+
7
+ class QBaslerCamera(QGenicamCamera):
8
+
9
+ '''Camera backed by a Basler device via the pylon GenTL producer.
10
+
11
+ `pylon <https://www.baslerweb.com/en/software/pylon/>`_ is Basler's
12
+ SDK for machine-vision cameras. It installs separate GenTL producers
13
+ for USB3 Vision and GigE Vision cameras whose paths are discovered
14
+ automatically from the ``GENICAM_GENTL64_PATH`` environment variable
15
+ set by the pylon installer.
16
+
17
+ If pylon is not installed, instantiation raises :exc:`TypeError`.
18
+
19
+ Parameters
20
+ ----------
21
+ cameraID : int
22
+ Index of the Basler camera to open. Default: ``0``.
23
+ '''
24
+
25
+ producer = QGenicamCamera._findProducer('ProducerU3V.cti',
26
+ 'ProducerGEV.cti')
27
+
28
+
29
+ class QBaslerSource(QGenicamSource):
30
+
31
+ '''Threaded video source backed by :class:`QBaslerCamera`.
32
+
33
+ Parameters
34
+ ----------
35
+ camera : QBaslerCamera or None
36
+ Camera instance to wrap. If ``None``, a new
37
+ :class:`QBaslerCamera` is created from ``cameraID``.
38
+ cameraID : int
39
+ Index of the camera to open. Used only when *camera* is ``None``.
40
+ Default: ``0``.
41
+ '''
42
+
43
+ def __init__(self, camera: QBaslerCamera | None = None,
44
+ cameraID: int = 0) -> None:
45
+ camera = camera or QBaslerCamera(cameraID=cameraID)
46
+ super().__init__(camera)
47
+
48
+
49
+ if __name__ == '__main__': # pragma: no cover
50
+ QBaslerCamera.example()
@@ -0,0 +1,67 @@
1
+ from QVideo.cameras.Genicam import QGenicamTree
2
+ from QVideo.cameras.Basler.QBaslerCamera import QBaslerCamera
3
+ from QVideo.lib.QCameraTree import Source
4
+
5
+
6
+ __all__ = ['QBaslerTree']
7
+
8
+
9
+ class QBaslerTree(QGenicamTree):
10
+
11
+ '''Camera property tree for :class:`~QVideo.cameras.Basler.QBaslerCamera`.
12
+
13
+ Builds a :class:`~QVideo.lib.QCameraTree.QCameraTree` with a curated
14
+ set of controls and sensible default settings for Basler cameras.
15
+
16
+ Parameters
17
+ ----------
18
+ camera : QBaslerCamera or None
19
+ Camera instance to use. If ``None``, a new :class:`QBaslerCamera`
20
+ is created from ``cameraID``.
21
+ cameraID : int
22
+ Index of the Basler camera to open. Used only when *camera* is
23
+ ``None``. Default: ``0``.
24
+ controls : list of str or None
25
+ Names of GenICam nodes to show. Default: :attr:`_DEFAULT_CONTROLS`.
26
+ '''
27
+
28
+ _DEFAULT_CONTROLS = [
29
+ 'ReverseX',
30
+ 'ReverseY',
31
+ 'AcquisitionFrameRate',
32
+ 'AcquisitionResultingFrameRate',
33
+ 'ExposureTime',
34
+ 'ExposureAuto',
35
+ 'Gain',
36
+ 'GainAuto',
37
+ 'Gamma',
38
+ 'BlackLevel',
39
+ 'Width',
40
+ 'Height',
41
+ 'OffsetX',
42
+ 'OffsetY',
43
+ ]
44
+
45
+ _DEFAULT_SETTINGS = dict(
46
+ AcquisitionFrameRateEnable=True,
47
+ BlackLevelSelector='All',
48
+ GammaEnable=True,
49
+ ExposureAuto='Off',
50
+ GainAuto='Off',
51
+ )
52
+
53
+ def __init__(self, *args,
54
+ camera: Source | None = None,
55
+ cameraID: int = 0,
56
+ controls: list[str] | None = None,
57
+ **kwargs) -> None:
58
+ camera = camera or QBaslerCamera(cameraID=cameraID)
59
+ camera.setSettings(self._DEFAULT_SETTINGS)
60
+ super().__init__(*args,
61
+ camera=camera,
62
+ controls=controls or self._DEFAULT_CONTROLS,
63
+ **kwargs)
64
+
65
+
66
+ if __name__ == '__main__': # pragma: no cover
67
+ QBaslerTree.example()
@@ -0,0 +1,5 @@
1
+ from .QBaslerCamera import QBaslerCamera, QBaslerSource
2
+ from .QBaslerTree import QBaslerTree
3
+
4
+
5
+ __all__ = ['QBaslerCamera', 'QBaslerSource', 'QBaslerTree']
@@ -0,0 +1,48 @@
1
+ from QVideo.cameras.Genicam import QGenicamCamera, QGenicamSource
2
+
3
+
4
+ __all__ = ['QFlirCamera', 'QFlirSource']
5
+
6
+
7
+ class QFlirCamera(QGenicamCamera):
8
+
9
+ '''Camera backed by a FLIR device via the Spinnaker GenTL producer.
10
+
11
+ `Spinnaker <https://www.flir.com/products/spinnaker-sdk/>`_ is FLIR's
12
+ SDK for machine-vision cameras. It installs a GenTL producer whose
13
+ path is discovered automatically from the ``GENICAM_GENTL64_PATH``
14
+ environment variable set by the Spinnaker installer.
15
+
16
+ If Spinnaker is not installed, instantiation raises :exc:`TypeError`.
17
+
18
+ Parameters
19
+ ----------
20
+ cameraID : int
21
+ Index of the FLIR camera to open. Default: ``0``.
22
+ '''
23
+
24
+ producer = QGenicamCamera._findProducer('Spinnaker_GenTL.cti')
25
+
26
+
27
+ class QFlirSource(QGenicamSource):
28
+
29
+ '''Threaded video source backed by :class:`QFlirCamera`.
30
+
31
+ Parameters
32
+ ----------
33
+ camera : QFlirCamera or None
34
+ Camera instance to wrap. If ``None``, a new
35
+ :class:`QFlirCamera` is created from ``cameraID``.
36
+ cameraID : int
37
+ Index of the camera to open. Used only when *camera* is ``None``.
38
+ Default: ``0``.
39
+ '''
40
+
41
+ def __init__(self, camera: QFlirCamera | None = None,
42
+ cameraID: int = 0) -> None:
43
+ camera = camera or QFlirCamera(cameraID=cameraID)
44
+ super().__init__(camera)
45
+
46
+
47
+ if __name__ == '__main__': # pragma: no cover
48
+ QFlirCamera.example()
@@ -0,0 +1,70 @@
1
+ from QVideo.cameras.Genicam import QGenicamTree
2
+ from QVideo.cameras.Flir.QFlirCamera import QFlirCamera
3
+ from QVideo.lib.QCameraTree import Source
4
+
5
+
6
+ __all__ = ['QFlirTree']
7
+
8
+
9
+ class QFlirTree(QGenicamTree):
10
+
11
+ '''Camera property tree for :class:`~QVideo.cameras.Flir.QFlirCamera`.
12
+
13
+ Builds a :class:`~QVideo.lib.QCameraTree.QCameraTree` with a curated
14
+ set of controls and sensible default settings for FLIR cameras.
15
+
16
+ Parameters
17
+ ----------
18
+ camera : QFlirCamera or None
19
+ Camera instance to use. If ``None``, a new :class:`QFlirCamera`
20
+ is created from ``cameraID``.
21
+ cameraID : int
22
+ Index of the FLIR camera to open. Used only when *camera* is
23
+ ``None``. Default: ``0``.
24
+ controls : list of str or None
25
+ Names of GenICam nodes to show. Default: :attr:`_DEFAULT_CONTROLS`.
26
+ '''
27
+
28
+ _DEFAULT_CONTROLS = [
29
+ 'ReverseX',
30
+ 'ReverseY',
31
+ 'AcquisitionFrameRate',
32
+ 'AcquisitionResultingFrameRate',
33
+ 'ExposureTime',
34
+ 'ExposureAuto',
35
+ 'Gain',
36
+ 'GainAuto',
37
+ 'Gamma',
38
+ 'BlackLevel',
39
+ 'Width',
40
+ 'Height',
41
+ 'OffsetX',
42
+ 'OffsetY',
43
+ ]
44
+
45
+ _DEFAULT_SETTINGS = dict(
46
+ AcquisitionFrameRateEnable=True,
47
+ BlackLevelSelector='All',
48
+ GammaEnable=True,
49
+ AutoExposureControlPriority='Gain',
50
+ ExposureAuto='Off',
51
+ ExposureMode='Timed',
52
+ ExposureTimeMode='Common',
53
+ GainAuto='Off',
54
+ )
55
+
56
+ def __init__(self, *args,
57
+ camera: Source | None = None,
58
+ cameraID: int = 0,
59
+ controls: list[str] | None = None,
60
+ **kwargs) -> None:
61
+ camera = camera or QFlirCamera(cameraID=cameraID)
62
+ camera.setSettings(self._DEFAULT_SETTINGS)
63
+ super().__init__(*args,
64
+ camera=camera,
65
+ controls=controls or self._DEFAULT_CONTROLS,
66
+ **kwargs)
67
+
68
+
69
+ if __name__ == '__main__': # pragma: no cover
70
+ QFlirTree.example()
@@ -0,0 +1,31 @@
1
+ from QVideo.lib import QListCameras
2
+ from harvesters.core import Harvester
3
+ from QVideo.cameras.Flir.QFlirCamera import QFlirCamera
4
+
5
+
6
+ __all__ = ['QListFlirCameras']
7
+
8
+
9
+ class QListFlirCameras(QListCameras):
10
+ '''A QComboBox that lists available Flir cameras.
11
+
12
+ Inherits
13
+ --------
14
+ QVideo.lib.QListCameras
15
+ '''
16
+
17
+ def _model(self) -> type:
18
+ return QFlirCamera
19
+
20
+ def _listCameras(self) -> None:
21
+ h = Harvester()
22
+ h.add_file(QFlirCamera.producer())
23
+ h.update()
24
+ for n, c in enumerate(h.device_info_list):
25
+ p = c.property_dict
26
+ self.addItem(f'{p["model"]} (SN {p["serial_number"]})', n)
27
+ h.reset()
28
+
29
+
30
+ if __name__ == '__main__':
31
+ QListFlirCameras.example()
@@ -0,0 +1,5 @@
1
+ from .QFlirCamera import (QFlirCamera, QFlirSource)
2
+ from .QFlirTree import QFlirTree
3
+
4
+
5
+ __all__ = 'QFlirCamera QFlirSource QFlirTree'.split()