Source code for QVideo.lib.chooser
'''Command-line camera selection utility for QVideo applications.'''
import importlib
import logging
from argparse import ArgumentParser
from typing import NamedTuple
from QVideo.lib import QCameraTree
from ._camera import Camera, _BACKENDS
__all__ = ['camera_parser', 'choose_camera']
logger = logging.getLogger(__name__)
class _CameraEntry(NamedTuple):
flag: str
help: str
_CAMERAS: dict[str, _CameraEntry] = {
'opencv': _CameraEntry('-c', 'OpenCV camera'),
'basler': _CameraEntry('-b', 'Basler pylon camera'),
'flir': _CameraEntry('-f', 'Flir camera'),
'ids': _CameraEntry('-i', 'IDS Imaging camera'),
'mv': _CameraEntry('-m', 'MATRIX VISION mvGenTLProducer (universal GenICam)'),
'vimbax': _CameraEntry('-v', 'Allied Vision VimbaX camera'),
'picamera': _CameraEntry('-p', 'Raspberry Pi camera module'),
}
[docs]
def camera_parser(parser: ArgumentParser | None = None) -> ArgumentParser:
'''Returns a command-line argument parser with camera selection options.
Adds a mutually exclusive group of camera flags and an optional
positional cameraID argument to the parser.
If the parser already defines any of these arguments,
they are left as-is.
Parameters
----------
parser : ArgumentParser | None
An optional ArgumentParser to extend with camera options.
If None, a new ArgumentParser is created.
Returns
-------
ArgumentParser
Parser with mutually exclusive flags::
-b -> Basler (pylon)
-c -> OpenCV
-f -> Flir
-i -> IDS Imaging
-m -> MATRIX VISION mvGenTLProducer (universal GenICam)
-p -> Raspberry Pi camera module
-v -> Allied Vision VimbaX
The flag can be followed by an optional positional
cameraID argument.
'''
parser = parser or ArgumentParser()
registered = parser._option_string_actions
first_flag = next(iter(_CAMERAS.values())).flag
if first_flag not in registered:
group = parser.add_mutually_exclusive_group()
for dest, entry in _CAMERAS.items():
group.add_argument(entry.flag, dest=dest, help=entry.help,
action='store_true')
if not any(a.dest == 'cameraID' for a in parser._actions):
parser.add_argument('cameraID', nargs='?', type=int, default=0,
help='camera ID number (default: %(default)d)')
return parser
[docs]
def choose_camera(parser: ArgumentParser | None = None) -> QCameraTree:
'''Chooses and returns a camera tree based on command-line arguments.
Tries to import and instantiate the camera backend selected by the
command-line flags. Falls back to :class:`QNoiseTree` if the
requested backend cannot be imported or instantiated.
Parameters
----------
parser : ArgumentParser | None
An optional ArgumentParser to parse command-line arguments.
If provided, camera options will be added to it.
If None, a new ArgumentParser is created.
Returns
-------
QCameraTree
The chosen camera tree widget.
'''
args, _ = camera_parser(parser).parse_known_args()
model = 'noise'
for dest in _CAMERAS:
if getattr(args, dest, False):
model = dest
break
try:
proxy = Camera(model, args.cameraID)
proxy._ensure_open()
except (RuntimeError, ValueError) as ex:
logger.warning(str(ex))
proxy = Camera('noise', args.cameraID)
proxy._ensure_open()
key = object.__getattribute__(proxy, '_selected_key')
backend = _BACKENDS[key]
module = importlib.import_module(backend.module)
tree_cls = getattr(module, backend.tree_cls)
camera = object.__getattribute__(proxy, '_camera')
return tree_cls(camera=camera)
if __name__ == '__main__': # pragma: no cover
choose_camera().show()