UVC 模块 API 手册#
概述#
UVC 模块用于在 CanMV Python 中访问 USB 摄像头。
模块使用 FOURCC 描述视频格式。支持的主机输入格式为:
UVC.FOURCC_YUY2UVC.FOURCC_UYVYUVC.FOURCC_NV12UVC.FOURCC_I420UVC.FOURCC_MJPEG
默认只支持单个 UVC 摄像头。
推荐流程#
UVC.probe()检测摄像头UVC.list_video_mode()查看设备支持的模式UVC.video_mode(...)构造目标模式UVC.select_video_mode(...)选择并协商模式UVC.start(...)启动视频流循环调用
UVC.snapshot()获取图像UVC.stop()停止视频流
建议在 try/finally 中调用 UVC.stop(),确保异常退出时也能正确停流。
API 参考#
UVC.probe() - 检测摄像头#
功能
检测系统当前是否接入 UVC 摄像头,并返回厂商/产品字符串。
语法
from media.uvc import UVC
plugin, devname = UVC.probe()
返回值
返回值 |
类型 |
说明 |
|---|---|---|
|
|
是否检测到 UVC 摄像头 |
|
|
设备信息,格式为 |
示例
plugin, devinfo = UVC.probe()
print(f"detect: {plugin}, devinfo: {devinfo}")
UVC.video_mode() - 获取或构造视频模式#
功能
无参数调用时:返回当前已协商的视频模式
带参数调用时:构造一个目标视频模式对象
语法
# 获取当前模式
mode = UVC.video_mode()
# 构造目标模式
mode = UVC.video_mode(width, height, fourcc, fps)
参数
参数 |
类型 |
说明 |
|---|---|---|
|
|
图像宽度 |
|
|
图像高度 |
|
|
像素格式,使用 |
|
|
目标帧率 |
说明
fourcc省略时默认使用UVC.FOURCC_MJPEGfps省略时会以frameinterval = 0传入底层,由驱动选择默认帧率UVC.select_video_mode()成功后,返回的模式对象会被更新为协商后的实际值
UVC.list_video_mode() - 列举设备支持模式#
功能
枚举摄像头支持的全部模式列表。列表中的每一项都是一个 uvc_video_mode 对象,包含宽、高、fourcc 和 fps。
语法
modes = UVC.list_video_mode()
示例
for i, mode in enumerate(UVC.list_video_mode()):
print(f"{i}: {mode}")
UVC.select_video_mode(mode) - 选择视频模式#
功能
根据用户给定的目标模式初始化 UVC 设备,并返回协商后的实际模式。
语法
succ, actual_mode = UVC.select_video_mode(mode)
参数
参数 |
类型 |
说明 |
|---|---|---|
|
|
目标模式 |
返回值
返回值 |
类型 |
说明 |
|---|---|---|
|
|
是否初始化成功 |
|
|
协商后的实际模式 |
常用 FOURCC
UVC.select_video_mode() 中传入的 mode.fourcc 通常使用以下常量:
常量 |
说明 |
|---|---|
|
YUY2 / YUYV 4:2:2 |
|
UYVY 4:2:2 |
|
NV12 4:2:0 |
|
I420 4:2:0 |
|
MJPEG 压缩格式 |
UVC.start() - 启动视频流#
功能
启动 UVC 视频流,并配置 snapshot() 的返回类型。
语法
success = UVC.start(delay_ms=0, cvt=True)
参数
参数 |
类型 |
说明 |
|---|---|---|
|
|
启动后额外等待的毫秒数 |
|
|
是否对 |
cvt 语义
输入格式 |
|
|
|---|---|---|
|
|
返回 JPEG 图像 |
|
返回 RGB565 图像 |
返回 YUV422 图像 |
|
返回 RGB565 图像 |
返回 YUV422 图像 |
|
不支持,会在 |
返回 YUV420 图像 |
|
不支持,会在 |
返回 YUV420 图像 |
UVC.stop() - 停止视频流#
功能
停止 UVC 视频流并释放内部状态。
语法
UVC.stop()
UVC.snapshot() - 获取一帧图像#
功能
从当前视频流中取出一帧图像。
语法
frame = UVC.snapshot()
frame = UVC.snapshot(timeout_ms)
参数
参数 |
类型 |
说明 |
|---|---|---|
|
|
获取一帧的超时时间,单位毫秒 |
返回值
返回类型与当前 fourcc 及 UVC.start(cvt=...) 配置有关:
当前模式 |
返回对象 |
|---|---|
|
NV12 视频帧对象 |
|
JPEG |
|
RGB565 |
|
YUV422 |
|
YUV420 |
说明
超时或暂时没有新帧时,可能返回
NoneNV12/I420在cvt=True时会抛出RuntimeError
uvc_video_mode 对象#
字段#
字段 |
类型 |
说明 |
|---|---|---|
|
|
宽度 |
|
|
高度 |
|
|
像素格式 |
|
|
当前模式帧率 |
打印示例#
mode = UVC.video_mode(640, 480, UVC.FOURCC_MJPEG, 30)
print(mode)
输出示意:
{"width":640, "height":480, "format":mjpeg, "fourcc":0x47504a4d, "fps":30.00}
注意:
format仅体现在打印字符串中代码里真正用于判断格式的是
mode.fourcc
示例#
示例 1:MJPEG 软解显示#
对应工程示例:src/canmv/resources/examples/02-Media/uvc.py
import time, gc
from media.display import *
from media.uvc import *
DISPLAY_WIDTH = ALIGN_UP(800, 16)
DISPLAY_HEIGHT = 480
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
while True:
plugin, dev = UVC.probe()
if plugin:
print(f"detect USB Camera {dev}")
break
mode = UVC.video_mode(640, 480, UVC.FOURCC_MJPEG, 30)
succ, mode = UVC.select_video_mode(mode)
print(f"select mode success: {succ}, mode: {mode}")
UVC.start(cvt=False)
clock = time.clock()
try:
while True:
clock.tick()
img = UVC.snapshot()
if img is not None:
img = img.to_rgb565()
Display.show_image(img)
img.__del__()
gc.collect()
print(f"fps: {clock.fps()}")
finally:
UVC.stop()
time.sleep_ms(100)
Display.deinit()
示例 2:MJPEG 硬解后再做 CSC#
对应工程示例:src/canmv/resources/examples/02-Media/uvc_with_csc.py
import time, gc
from media.display import *
from media.uvc import *
from nonai2d import CSC
DISPLAY_WIDTH = ALIGN_UP(800, 16)
DISPLAY_HEIGHT = 480
csc = CSC(CSC.PIXEL_FORMAT_RGB_565)
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
while True:
plugin, dev = UVC.probe()
if plugin:
print(f"detect USB Camera {dev}")
break
time.sleep_ms(100)
mode = UVC.video_mode(640, 480, UVC.FOURCC_MJPEG, 30)
succ, mode = UVC.select_video_mode(mode)
print(f"select mode success: {succ}, mode: {mode}")
UVC.start(cvt=True)
clock = time.clock()
try:
while True:
clock.tick()
img = UVC.snapshot()
if img is None:
continue
img = csc.convert(img)
Display.show_image(img)
img.__del__()
gc.collect()
print(f"fps: {clock.fps()}")
finally:
UVC.stop()
time.sleep_ms(100)
csc.destroy()
Display.deinit()
示例 3:YUY2 直接转换为 RGB565 显示#
import time, gc
from media.display import *
from media.uvc import *
DISPLAY_WIDTH = ALIGN_UP(800, 16)
DISPLAY_HEIGHT = 480
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
while True:
plugin, dev = UVC.probe()
if plugin:
print(f"detect USB Camera {dev}")
break
time.sleep_ms(100)
mode = UVC.video_mode(640, 480, UVC.FOURCC_YUY2, 30)
succ, mode = UVC.select_video_mode(mode)
print(f"select mode success: {succ}, mode: {mode}")
UVC.start(cvt=True)
clock = time.clock()
try:
while True:
clock.tick()
img = UVC.snapshot()
if img is None:
continue
Display.show_image(img)
img.__del__()
gc.collect()
print(f"fps: {clock.fps()}")
finally:
UVC.stop()
time.sleep_ms(100)
Display.deinit()
注意事项#
UVC.stop()建议始终放在finally中调用。UVC.start(cvt=True)只影响snapshot()返回内容,不改变 USB 侧实际协商到的fourcc。NV12/I420当前不支持直接在snapshot(cvt=True)中转换。不建议通过 Hub 同时连接 UVC 摄像头和大量占用 USB 带宽的设备。
