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.
- QVideo/QCamcorder.py +125 -0
- QVideo/__init__.py +5 -0
- QVideo/cameras/Basler/QBaslerCamera.py +50 -0
- QVideo/cameras/Basler/QBaslerTree.py +67 -0
- QVideo/cameras/Basler/__init__.py +5 -0
- QVideo/cameras/Flir/QFlirCamera.py +48 -0
- QVideo/cameras/Flir/QFlirTree.py +70 -0
- QVideo/cameras/Flir/QListFlirCameras.py +31 -0
- QVideo/cameras/Flir/__init__.py +5 -0
- QVideo/cameras/Genicam/QGenicamCamera.py +382 -0
- QVideo/cameras/Genicam/QGenicamTree.py +224 -0
- QVideo/cameras/Genicam/__init__.py +5 -0
- QVideo/cameras/IDS/QIDSCamera.py +49 -0
- QVideo/cameras/IDS/QIDSTree.py +65 -0
- QVideo/cameras/IDS/__init__.py +5 -0
- QVideo/cameras/MV/QMVCamera.py +55 -0
- QVideo/cameras/MV/QMVTree.py +65 -0
- QVideo/cameras/MV/__init__.py +5 -0
- QVideo/cameras/Noise/QNoiseCamera.py +144 -0
- QVideo/cameras/Noise/QNoiseTree.py +35 -0
- QVideo/cameras/Noise/__init__.py +5 -0
- QVideo/cameras/OpenCV/QListCVCameras.py +73 -0
- QVideo/cameras/OpenCV/QOpenCVCamera.py +224 -0
- QVideo/cameras/OpenCV/QOpenCVTree.py +59 -0
- QVideo/cameras/OpenCV/__init__.py +5 -0
- QVideo/cameras/Picamera/QPicamera.py +229 -0
- QVideo/cameras/Picamera/QPicameraTree.py +47 -0
- QVideo/cameras/Picamera/__init__.py +5 -0
- QVideo/cameras/Vimbax/QVimbaXCamera.py +51 -0
- QVideo/cameras/Vimbax/QVimbaXTree.py +37 -0
- QVideo/cameras/Vimbax/__init__.py +5 -0
- QVideo/cameras/__init__.py +0 -0
- QVideo/dvr/QDVRWidget.py +354 -0
- QVideo/dvr/QHDF5Reader.py +93 -0
- QVideo/dvr/QHDF5Writer.py +89 -0
- QVideo/dvr/QOpenCVReader.py +98 -0
- QVideo/dvr/QOpenCVWriter.py +144 -0
- QVideo/dvr/__init__.py +14 -0
- QVideo/dvr/icons_rc.py +1082 -0
- QVideo/dvr/icons_rc_qt6.py +1106 -0
- QVideo/filters/Median.py +89 -0
- QVideo/filters/MoMedian.py +63 -0
- QVideo/filters/Normalize.py +142 -0
- QVideo/filters/QBlurFilter.py +101 -0
- QVideo/filters/QEdgeFilter.py +162 -0
- QVideo/filters/QRGBFilter.py +97 -0
- QVideo/filters/QSampleHold.py +141 -0
- QVideo/filters/_MedianBase.py +104 -0
- QVideo/filters/__init__.py +17 -0
- QVideo/lib/QCamera.py +387 -0
- QVideo/lib/QCameraTree.py +212 -0
- QVideo/lib/QFPSMeter.py +90 -0
- QVideo/lib/QFilterBank.py +118 -0
- QVideo/lib/QListCameras.py +87 -0
- QVideo/lib/QVideoReader.py +227 -0
- QVideo/lib/QVideoScreen.py +173 -0
- QVideo/lib/QVideoSource.py +196 -0
- QVideo/lib/QVideoWriter.py +123 -0
- QVideo/lib/VideoFilter.py +149 -0
- QVideo/lib/__init__.py +17 -0
- QVideo/lib/chooser.py +118 -0
- QVideo/lib/clickable.py +43 -0
- QVideo/lib/resolutions.py +46 -0
- QVideo/lib/types.py +6 -0
- QVideo/version.py +4 -0
- qvideo-3.0.0.dist-info/METADATA +161 -0
- qvideo-3.0.0.dist-info/RECORD +70 -0
- qvideo-3.0.0.dist-info/WHEEL +5 -0
- qvideo-3.0.0.dist-info/licenses/LICENSE.md +17 -0
- 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,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,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()
|