Linux友好的视频处理库
项目描述
v4l2py
从版本3.0开始,该项目现在是 linuxpy.video
的适配器
请考虑直接使用 linuxpy。
视频Linux 2 (V4L2) Python库
双用途API
- 为人类提供的高级设备API来玩耍 :-)
- 用于v4l2 (video4linux2) 用户空间API的原始Python绑定,使用ctypes(不要浪费时间在这里。你可能不会使用它)
仅适用于Python >= 3.7。
为什么?
那么,为什么还需要一个专门用于视频控制的库?我为什么不能只使用 cv2.VideoCapture
?
以下是这个库提供的功能列表,这些功能在其他库中找不到
- 列出可用的V4L2设备
- 获取设备详细信息(名称、驱动程序、功能、可用格式)
- 精细控制相机参数(例如:分辨率、格式、亮度、对比度等)
- 精细控制资源管理以利用内存映射、DMA或用户指针(缓冲区)
- 关于帧的详细信息(时间戳、帧号等)
- 写入VideoOutput
- 与非阻塞的基于协程的应用程序(如
gevent
和asyncio
)集成,无需使用asyncio.to_thread
等常规技巧
安装
在您喜欢的Python环境中
$ pip install v4l2py
使用方法
无需多言
>>> from v4l2py import Device
>>> with Device.from_id(0) as cam:
>>> for i, frame in enumerate(cam):
... print(f"frame #{i}: {len(frame)} bytes")
... if i > 9:
... break
...
frame #0: 54630 bytes
frame #1: 50184 bytes
frame #2: 44054 bytes
frame #3: 42822 bytes
frame #4: 42116 bytes
frame #5: 41868 bytes
frame #6: 41322 bytes
frame #7: 40896 bytes
frame #8: 40844 bytes
frame #9: 40714 bytes
frame #10: 40662 bytes
获取设备信息
>>> from v4l2py.device import Device, BufferType
>>> cam = Device.from_id(0)
>>> cam.open()
>>> cam.info.card
'Integrated_Webcam_HD: Integrate'
>>> cam.info.capabilities
<Capability.STREAMING|EXT_PIX_FORMAT|VIDEO_CAPTURE: 69206017>
>>> cam.info.formats
[ImageFormat(type=<BufferType.VIDEO_CAPTURE: 1>, description=b'Motion-JPEG',
flags=<ImageFormatFlag.COMPRESSED: 1>, pixelformat=<PixelFormat.MJPEG: 1196444237>),
ImageFormat(type=<BufferType.VIDEO_CAPTURE: 1>, description=b'YUYV 4:2:2',
flags=<ImageFormatFlag.0: 0>, pixelformat=<PixelFormat.YUYV: 1448695129>)]
>>> cam.get_format(BufferType.VIDEO_CAPTURE)
Format(width=640, height=480, pixelformat=<PixelFormat.MJPEG: 1196444237>}
>>> for ctrl in cam.controls.values(): print(ctrl)
<IntegerControl brightness min=0 max=255 step=1 default=128 value=128>
<IntegerControl contrast min=0 max=255 step=1 default=32 value=32>
<IntegerControl saturation min=0 max=100 step=1 default=64 value=64>
<IntegerControl hue min=-180 max=180 step=1 default=0 value=0>
<BooleanControl white_balance_automatic default=True value=True>
<IntegerControl gamma min=90 max=150 step=1 default=120 value=120>
<MenuControl power_line_frequency default=1 value=1>
<IntegerControl white_balance_temperature min=2800 max=6500 step=1 default=4000 value=4000 flags=inactive>
<IntegerControl sharpness min=0 max=7 step=1 default=2 value=2>
<IntegerControl backlight_compensation min=0 max=2 step=1 default=1 value=1>
<MenuControl auto_exposure default=3 value=3>
<IntegerControl exposure_time_absolute min=4 max=1250 step=1 default=156 value=156 flags=inactive>
<BooleanControl exposure_dynamic_framerate default=False value=False>
>>> cam.controls["saturation"]
<IntegerControl saturation min=0 max=100 step=1 default=64 value=64>
>>> cam.controls["saturation"].id
9963778
>>> cam.controls[9963778]
<IntegerControl saturation min=0 max=100 step=1 default=64 value=64>
>>> cam.controls.brightness
<IntegerControl brightness min=0 max=255 step=1 default=128 value=128>
>>> cam.controls.brightness.value = 64
>>> cam.controls.brightness
<IntegerControl brightness min=0 max=255 step=1 default=128 value=64>
(另见 v4l2py-ctl 示例)
asyncio
v4l2py 与 asyncio 兼容
$ python -m asyncio
>>> from v4l2py import Device
>>> with Device.from_id(0) as camera:
... async for frame in camera:
... print(f"frame {len(frame)}")
frame 10224
frame 10304
frame 10224
frame 10136
...
gevent
v4l2py 也与 gevent 兼容
$ python
>>> from v4l2py import Device, GeventIO
>>> with Device.from_id(0, io=GeventIO) as camera:
... for frame in camera:
... print(f"frame {len(frame)}")
frame 10224
frame 10304
frame 10224
frame 10136
...
(检查 基本 gevent 和 Web gevent 示例)
额外功能
您已经很有耐心地读到这里了,所以,仅为您准备了一个20行的宝贝:一个 flask Web 服务器,可以在网页上显示您的设备
$ pip install flask
# web.py
import flask
from v4l2py import Device
app = flask.Flask('basic-web-cam')
def gen_frames():
with Device.from_id(0) as cam:
for frame in cam:
yield b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + frame.data + b"\r\n"
@app.route("/")
def index():
return '<html><img src="/stream" /></html>'
@app.route("/stream")
def stream():
return flask.Response(
gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
运行方式
$ FLASK_APP=web flask run -h 0.0.0.0
将浏览器指向 127.0.0.1:5000,您应该能看到相机正在运行!
从 1.x 迁移到 2
帧从简单的字节对象更改为包含数据和所有帧元数据的 Frame。
因此,在从 1.x 迁移到 2 时,您需要使用 bytes
强制转换帧对象或访问 frame.data
项
之前
with Device.from_id(0) as cam:
for frame in cam:
buff = io.BytesIO(frame)
现在
with Device.from_id(0) as cam:
for frame in cam:
frame = bytes(frame) # or frame = frame.data
buff = io.BytesIO(frame)
改进的设备控制
设备控制已得到改进,以提供更符合 Python 风格的接口。新接口现在是默认设置;然而,旧接口可以通过以下方式请求:Device.from_id(x, legacy_controls=True)
。
之前
>>> from v4l2py import Device
>>> cam = Device.from_id(0)
>>> cam.open()
>>> for ctrl in cam.controls.values():
... print(ctrl)
... for item in ctrl.menu.values():
... print(f" - {item.index}: {item.name}")
<Control brightness type=integer min=0 max=255 step=1 default=128 value=255>
<Control contrast type=integer min=0 max=255 step=1 default=32 value=255>
<Control saturation type=integer min=0 max=100 step=1 default=64 value=100>
<Control hue type=integer min=-180 max=180 step=1 default=0 value=0>
<Control white_balance_automatic type=boolean min=0 max=1 step=1 default=1 value=1>
<Control gamma type=integer min=90 max=150 step=1 default=120 value=150>
<Control gain type=integer min=1 max=7 step=1 default=1 value=1>
<Control power_line_frequency type=menu min=0 max=2 step=1 default=2 value=2>
- 0: Disabled
- 1: 50 Hz
- 2: 60 Hz
<Control white_balance_temperature type=integer min=2800 max=6500 step=1 default=4000 value=4000 flags=inactive>
<Control sharpness type=integer min=0 max=7 step=1 default=2 value=7>
<Control backlight_compensation type=integer min=0 max=1 step=1 default=0 value=1>
<Control auto_exposure type=menu min=0 max=3 step=1 default=3 value=3>
- 1: Manual Mode
- 3: Aperture Priority Mode
<Control exposure_time_absolute type=integer min=10 max=333 step=1 default=156 value=156 flags=inactive>
<Control exposure_dynamic_framerate type=boolean min=0 max=1 step=1 default=0 value=1>
>>> type(cam.controls.exposure_dynamic_framerate.value)
<class 'int'>
现在
>>> from v4l2py.device import Device, MenuControl
>>> cam = Device.from_id(0)
>>> cam.open()
>>> for ctrl in cam.controls.values():
... print(ctrl)
... if isinstance(ctrl, MenuControl):
... for (index, name) in ctrl.items():
... print(f" - {index}: {name}")
<IntegerControl brightness min=0 max=255 step=1 default=128 value=255>
<IntegerControl contrast min=0 max=255 step=1 default=32 value=255>
<IntegerControl saturation min=0 max=100 step=1 default=64 value=100>
<IntegerControl hue min=-180 max=180 step=1 default=0 value=0>
<BooleanControl white_balance_automatic default=True value=True>
<IntegerControl gamma min=90 max=150 step=1 default=120 value=150>
<IntegerControl gain min=1 max=7 step=1 default=1 value=1>
<MenuControl power_line_frequency default=2 value=2>
- 0: Disabled
- 1: 50 Hz
- 2: 60 Hz
<IntegerControl white_balance_temperature min=2800 max=6500 step=1 default=4000 value=4000 flags=inactive>
<IntegerControl sharpness min=0 max=7 step=1 default=2 value=7>
<IntegerControl backlight_compensation min=0 max=1 step=1 default=0 value=1>
<MenuControl auto_exposure default=3 value=3>
- 1: Manual Mode
- 3: Aperture Priority Mode
<IntegerControl exposure_time_absolute min=10 max=333 step=1 default=156 value=156 flags=inactive>
<BooleanControl exposure_dynamic_framerate default=False value=True>
>>> type(cam.controls.white_balance_automatic.value)
<class 'bool'>
>>> cam.controls.white_balance_automatic.value
<BooleanControl white_balance_automatic default=True value=True>
>>> cam.controls.white_balance_automatic.value = False
<BooleanControl white_balance_automatic default=True value=False>
>>> wba = cam.controls.white_balance_automatic
>>> wba.value = "enable" # or "on", "1", "true", "yes"
>>> wba
<BooleanControl white_balance_automatic default=True value=True>
>>> wba.value = "off" # or "disable", "0", "false", "no"
>>> wba
<BooleanControl white_balance_automatic default=True value=False>
现有代码的初始升级路径是请求旧接口,在实例化 Device
对象时传递 legacy_controls=True
,使用 LegacyControl
替代 Control
进行实例化,以及使用 BaseControl
进行 isinstance()
检查。在不太可能的情况下,如果您的代码对 MenuItem
进行 isinstance()
检查,应将其更改为 LegacyMenuItem
。
参考
请参阅 linux/videodev2.h
头文件以获取详细信息。
Video for Linux Two 规范 <https://linuxkernel.org.cn/doc/html/v6.2/userspace-api/media/v4l/v4l2.html>
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。
源分布
构建分布
v4l2py-3.0.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 7e83c02f7393da883c791b9b7ba3dd11163b42d15e68dc09b3e3d99a6d75b7a4 |
|
MD5 | f592df60c4cfdd8266495259402f4616 |
|
BLAKE2b-256 | d8b9a578b5e7e24682ade09a0a60e3a312d58617d776f9ec2b72192ccef8e7c5 |