From 67a6e3b8c0c6b26ba00aa99e51eb813c24e27e5e Mon Sep 17 00:00:00 2001 From: Michael Renzmann Date: Fri, 19 May 2023 02:01:34 +0200 Subject: [PATCH 1/3] Make the web example work with Python < 3.10 (again). Closes otaku42/v4l2py#21. --- examples/web/common.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/examples/web/common.py b/examples/web/common.py index 9e87cfc..3216bea 100644 --- a/examples/web/common.py +++ b/examples/web/common.py @@ -35,22 +35,21 @@ def __init__(self, device: Device) -> None: def frame_to_image(frame, output="jpeg"): - match frame.pixel_format: - case PixelFormat.JPEG | PixelFormat.MJPEG: - if output == "jpeg": - return to_image_send(frame.data, type=output) - else: - buff = io.BytesIO() - image = PIL.Image.open(io.BytesIO(frame.data)) - case PixelFormat.GREY: - data = frame.array - data.shape = frame.height, frame.width, -1 - image = PIL.Image.frombuffer("L", (frame.width, frame.height), data) - case PixelFormat.YUYV: - data = frame.array - data.shape = frame.height, frame.width, -1 - rgb = cv2.cvtColor(data, cv2.COLOR_YUV2RGB_YUYV) - image = PIL.Image.fromarray(rgb) + if frame.pixel_format in (PixelFormat.JPEG, PixelFormat.MJPEG): + if output == "jpeg": + return to_image_send(frame.data, type=output) + else: + buff = io.BytesIO() + image = PIL.Image.open(io.BytesIO(frame.data)) + elif frame.pixel_format == PixelFormat.GREY: + data = frame.array + data.shape = frame.height, frame.width, -1 + image = PIL.Image.frombuffer("L", (frame.width, frame.height), data) + elif frame.pixel_format == PixelFormat.YUYV: + data = frame.array + data.shape = frame.height, frame.width, -1 + rgb = cv2.cvtColor(data, cv2.COLOR_YUV2RGB_YUYV) + image = PIL.Image.fromarray(rgb) buff = io.BytesIO() image.save(buff, output) From 398f9b3646a2e07f7d58c27f79809fc9a8726233 Mon Sep 17 00:00:00 2001 From: Michael Renzmann Date: Fri, 19 May 2023 02:45:32 +0200 Subject: [PATCH 2/3] Update installation instructions for extra dependencies: OpenCV package is named opencv-python; call pip as module, as suggested in the pip manual. Closes otaku42/v4l2py#22. --- examples/qt/widget.py | 7 +++++-- examples/web.py | 3 +++ examples/web/async.py | 3 ++- examples/web/common.py | 6 ------ examples/web/sync.py | 2 +- examples/web_async.py | 2 +- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/qt/widget.py b/examples/qt/widget.py index b11ff09..b72e529 100644 --- a/examples/qt/widget.py +++ b/examples/qt/widget.py @@ -4,8 +4,11 @@ # Copyright (c) 2021 Tiago Coutinho # Distributed under the GPLv3 license. See LICENSE for more info. -# install requirements: pip install cv2 qtpy pyqt6 -# run with: QT_API=pyqt6 python widget.py +# install extra requirements: +# python3 -m pip install opencv-python qtpy pyqt6 + +# run from this directory with: +# QT_API=pyqt6 python widget.py import cv2 from qtpy import QtCore, QtGui, QtWidgets diff --git a/examples/web.py b/examples/web.py index 4fc9a5b..4b6cd76 100644 --- a/examples/web.py +++ b/examples/web.py @@ -4,6 +4,9 @@ # Copyright (c) 2021 Tiago Coutinho # Distributed under the GPLv3 license. See LICENSE for more info. +# Extra dependency required to run this example: +# python3 -m pip install flask + # run from this directory with: FLASK_APP=web flask run -h 0.0.0.0 import flask diff --git a/examples/web/async.py b/examples/web/async.py index cac586e..af5ee50 100644 --- a/examples/web/async.py +++ b/examples/web/async.py @@ -5,7 +5,8 @@ # Distributed under the GPLv3 license. See LICENSE for more info. # Extra dependencies required to run this example: -# pip install fastapi jinja2 python-multipart cv2 pillow uvicorn +# python3 -m pip install fastapi jinja2 python-multipart opencv-python \ +# pillow uvicorn # run from this directory with: # uvicorn async:app diff --git a/examples/web/common.py b/examples/web/common.py index 3216bea..2245995 100644 --- a/examples/web/common.py +++ b/examples/web/common.py @@ -4,12 +4,6 @@ # Copyright (c) 2023 Tiago Coutinho # Distributed under the GPLv3 license. See LICENSE for more info. -# Extra dependencies required to run this example: -# pip install fastapi jinja2 python-multipart cv2 pillow uvicorn - -# run from this directory with: -# uvicorn async:app - """Common tools for async and sync web app examples""" import io diff --git a/examples/web/sync.py b/examples/web/sync.py index bbe1601..72a5ef0 100644 --- a/examples/web/sync.py +++ b/examples/web/sync.py @@ -5,7 +5,7 @@ # Distributed under the GPLv3 license. See LICENSE for more info. # Extra dependencies required to run this example: -# pip install pillow cv2 flask gunicorn gevent +# python3 -m pip install pillow opencv-python flask gunicorn gevent # run from this directory with: # gunicorn --bind=0.0.0.0:8000 --log-level=debug --worker-class=gevent sync:app diff --git a/examples/web_async.py b/examples/web_async.py index e7420db..cdf6c49 100644 --- a/examples/web_async.py +++ b/examples/web_async.py @@ -5,7 +5,7 @@ # Distributed under the GPLv3 license. See LICENSE for more info. # install dependencies with: -# pip install uvicorn fastapi +# python3 -m pip install uvicorn fastapi # # run from this directory with: # uvicorn web_async:app From a98df12f1cdc84ec8d4ba169c9e1d86bcba2c880 Mon Sep 17 00:00:00 2001 From: Michael Renzmann Date: Fri, 19 May 2023 21:52:31 +0200 Subject: [PATCH 3/3] Fix error reported by @tiagocoutinho at tiagocoutinho/v4l2py#42. --- examples/web/async.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/web/async.py b/examples/web/async.py index af5ee50..e0cd1fe 100644 --- a/examples/web/async.py +++ b/examples/web/async.py @@ -89,7 +89,7 @@ def cameras() -> list[Camera]: global CAMERAS if CAMERAS is None: cameras = {} - for device in iter_video_capture_devices(): + for device in iter_video_capture_devices(legacy_controls=True): cameras[device.index] = Camera(device) CAMERAS = cameras return CAMERAS