k230使用摄像头
- 一.摄像头基础知识
- 1.图像传感器
- 2.分辨率和帧率
- 3.焦距和视场角
- 4.像素格式
- 5.镜像和翻转
- 6.曝光和白平衡
- 二.Sensor模块
- 1.reset
- 2.set_framesize
- 3.set_pixformat
- 4.set_hmirror
- 5.set_vflip
- 6.run
- 7.stop
- 8.snapshot
- 三.Display模块
- 1.初始化init
- 1.1.type
- 1.2.LAYER
- 1.3.flag
- 2.show_image
- 3.deinit
- 4.bind_layer
- 在Canmv IDE K230上显示画面
本教程皆来自立创官方教程,为博主学习使用所记录,使用开发板为立创的庐山派,如有需求可自行访问 立创官网
一.摄像头基础知识
使用摄像头之前,了解一些基础知识有助于更好地应用和开发
1.图像传感器
图像传感器是摄像头的核心组件,负责将光信号转换为电信号,这样电子设备才能处理和存储这些信息,目前常见的图像传感器类型有CCD和CMOS,我使用的庐山派开发板使用的GC2093摄像头是CMOS类型的传感器
特点 | CMOS传感器 | CCD传感器 |
---|---|---|
信噪比和图像质量 | 早期噪声较大,但技术进步已改善,现代CMOS噪声已大幅降低,图像质量接近甚至超越CCD | 高信噪比,图像质量高,低噪声表现优秀,适合弱光环境下的高质量成像 |
功耗和集成度 | 低功耗,适合电池供电设备,高集成度,可在芯片上集成图像处理电路和ADC,简化设计 | 高功耗,需要高电压驱动,低集成度,需外部电路支持,如模拟数字转换器(ADC) |
数据读取速度 | 读取速度快,支持高帧率和全局快门,可随机访问像素,适合高速成像 | 读取速度较慢,电荷逐行转移,帧率和高速成像能力受限 |
制造成本 | 利用标准CMOS工艺制造,成本较低,成本较低便于大规模生产 | 制造工艺复杂,生产成本较高,价格相对昂贵 |
适用场景 | 消费电子产品:智能手机、平板电脑、数码相机等。安防监控:监控摄像头、行车记录仪等。汽车电子:倒车影像、驾驶辅助系统等。 物联网和嵌入式系统:机器人、无人机等 | 专业摄影设备:高端数码相机、电影摄像机。科学研究:天文学、医学成像等。工业检测:精密测量、质量控制等 |
优点 | 低功耗- 高集成度,成本低- 读取速度快,支持高帧率 | 高图像质量- 低噪声,弱光性能优异,高信噪比 |
缺点 | 早期噪声较大(目前已大幅改善), 在极端弱光条件下可能不及CCD | 高功耗- 成本高,读取速度慢,帧率受限 |
技术发展趋势 | 技术不断进步,背照式和堆栈式CMOS提升了性能,全局快门技术改善了图像失真问题 | 技术成熟,但市场份额逐渐被CMOS取代,主要应用在特定高端领域 |
选择建议 | 适合对成本、功耗和尺寸敏感的应用,需要高速成像和高集成度的设备 | 适合追求极高图像质量的专业领域,弱光环境下的高性能成像需求 |
CMOS传感器在大多数应用中已成为主流选择,适合消费电子和需要高集成度的设备。是目前绝大多数的数码单反相机所用的图像传感器。
CCD传感器仍在专业摄影、科学研究等需要卓越图像质量的领域占有重要地位。做智能车的用户可能会比较熟悉,应该用过那种线性CCD摄像头来进行巡线。
2.分辨率和帧率
分辨率:简单来说,分辨率就是图像的清晰度。它表示为图像的宽度和高度的像素数,例如1920x1080。这意味着图像有1920个像素的宽度和1080个像素的高度,我家里以及在公司使用的显示屏也就这个分辨率,就是平常所说的1080P屏幕。像素数越高,图像就越清晰,能展示的细节就越多。
帧率(FPS):帧率表示每秒钟摄像头可以捕捉并传输的图像数量。帧率越高,视频就越流畅。比如,电影通常是24fps,打游戏的话一般都得144Hz以上。庐山派赠送的GC2093摄像头支持最高60fps的帧率,能提供非常流畅的图像,至少在嵌入式领域算是比较高的帧率了,毕竟嵌入式会落后计算机20年嘛。
3.焦距和视场角
焦距(EFL):焦距决定了摄像头能看到的范围,就像是人眼的视野。焦距越短,摄像头能看到的范围就越广,但看到的物体会显得较小。焦距越长,摄像头能看到的范围就越窄,但可以看得更远、更清楚。
视场角(View Angle):视场角是用角度来表示摄像头能看到的范围,包括:
对角线视角(D):从图像的一个角到对角线另一端的视角。
水平视角(H):摄像头水平方向能看到的范围。
垂直视角(V):摄像头垂直方向能看到的范围。
4.像素格式
像素格式是指图像数据的存储方式,它描述了每个像素如何表示颜色或亮度信息。选择合适的像素格式不仅影响图像的质量,还直接影响存储空间、数据传输速度和处理效率。
RGB565
定义:每个像素用16位表示,RGB通道分别分配5位、6位和5位。
红色 ( R):5位,32级灰度。
绿色 (G):6位,64级灰度(由于人眼对绿色更敏感,绿色多分配了一位)。
蓝色 (B):5位,32级灰度。
特点:
数据量较小,仅16位(2字节)每像素。
支持基本的颜色表现,但颜色精度较低。
应用场景:
低功耗嵌入式设备,如手持设备、工业屏幕显示。
对图像质量要求不高但注重内存占用的场景。
RGB888
定义:每个像素用24位表示,RGB通道分别分配8位(即每种颜色256级灰度)。
红色 ( R):8位。
绿色 (G):8位。
蓝色 (B):8位。
特点:
高颜色精度,适合高质量图像显示。
数据量较大,每像素3字节。
应用场景:
高分辨率图像处理。
用于显示要求高的场合,如智能手机屏幕、高清显示器。
RGBP888
定义:也叫分离的24位RGB格式,R、G、B通道数据分别存储在独立的内存区域中。
第一个内存块存储所有像素的R通道值。
第二个内存块存储所有像素的G通道值。
第三个内存块存储所有像素的B通道值。
特点:
更适合某些图像处理算法(如颜色分离、特征提取)。
数据访问更高效,但存储方式较复杂。
应用场景:
用于图像算法开发,如深度学习中的特征提取。
专业图像处理器的内部数据格式。
YUV420SP
定义:一种半平面 YUV 格式,主要用于视频压缩和处理。
Y:表示亮度(Luminance)。
U、V:表示色度(Chrominance),分别存储蓝色和红色的差异。
420:表示UV分量的分辨率为Y的1/4。
半平面:Y存储在一块连续内存中,UV分量交替存储在另一块连续内存中。
特点:
数据量小,压缩比高。
亮度和色度分开,便于色彩调整。
应用场景:
视频流处理和压缩,如H.264、H.265视频编码。
用于需要节省存储和带宽的实时视频传输场景。
GRAYSCALE
定义:灰度图,只有亮度信息,每像素用8位表示(256级灰度)。
无颜色信息,只有从黑到白的亮度变化。
特点:
数据量小,仅1字节每像素。
不包含色彩信息,但对亮度变化敏感。
应用场景:
图像识别和机器视觉,如边缘检测、特征提取。
黑白图像存储和处理。
像素格式 | 每像素数据量 | 优点 | 缺点 | 典型应用 |
---|---|---|---|---|
RGB565 | 2字节 | 数据量小,适合低功耗设备 | 颜色精度低 | 嵌入式显示屏、工业显示 |
RGB888 | 3字节 | 颜色精度高,适合高清显示 | 数据量大,占用更多内存 | 高清显示器、手机屏幕 |
RGBP888 | 3字节 | 更高效的通道访问 | 存储和处理较复杂 | 深度学习、专业图像处理 |
YUV420SP | 1.5字节 | 压缩比高,适合视频传输 | 色彩精度不如RGB | 视频流处理、实时视频传输 |
GRAYSCALE | 1字节 | 数据量小,专注亮度处理 | 无颜色信息 | 机器视觉、图像识别 |
性能与图像质量的平衡:
RGB565 和 YUV420SP 更注重性能,适合嵌入式场景
RGB888 和 RGBP888 更注重图像质量,适合高清显示或复杂算法
存储和带宽限制:
嵌入式设备通常内存和带宽有限,选择合适的像素格式可以降低资源占用
理解格式的用途:
如果需要处理彩色图像,优先选择 RGB 格式
如果主要关注亮度变化,比如说巡线,可以选择 GRAYSCALE 格式
实际开发经验:
在图像处理或视频传输项目中,YUV420SP 是视频压缩的主流格式
在AI模型中,经常会将RGB888转换为RGBP888格式,便于模型高效处理
5.镜像和翻转
在实际应用中,摄像头可能会因为安装方向的不同,导致拍摄的图像是倒置的或者是镜像的。为了让图像呈现正确的方向,我们就需要对图像进行镜像或翻转处理
水平镜像(H-Mirror):将图像左右颠倒,就像看镜子里的自己。
垂直翻转(V-Flip):将图像上下颠倒,使上方的物体显示在下方。
6.曝光和白平衡
曝光:曝光控制着传感器接收光线的时间,直接影响图像的亮度。曝光时间越长,传感器接收到的光线就越多,图像就会越亮;曝光时间越短,图像就会变暗。在光线不足的环境下,可以增加曝光时间来提高亮度。
白平衡:白平衡用于调整图像的色彩,使其看起来更加自然。不同的光源(如日光、白炽灯、荧光灯)会有不同的色温,影响图像的颜色表现。通过调整白平衡,可以纠正颜色偏差,使白色看起来真正是白色,从而使整个图像的颜色更加准确。
注意:K230芯片内部自带ISP,如果需要调节摄像头的亮度,对比度,曝光时间等就需要将ISP的AE模块关掉,会导致成像效果变差,所以目前还没有能调节曝光和白平衡的API接口,目前用户无法直接操作。
二.Sensor模块
K230的Sensor模块API提供了对这些硬件的底层控制,模块负责图像采集与数据处理
图中,sensor 0、sensor 1 和 sensor 2 分别代表三个图像输入传感器设备;Camera Device 0、Camera Device 1 和 Camera Device 2 对应相应的图像处理单元;output channel 0、output channel 1 和 output channel 2 表示每个图像处理单元最多支持三个输出通道。通过软件配置,不同的传感器设备可以灵活映射到相应的图像处理单元。
CanMV K230 的 sensor 模块最多支持三路图像传感器的同时接入,每一路均可独立完成图像数据的采集、捕获和处理。此外,每个视频通道可并行输出三路图像数据供后端模块进行进一步处理。实际应用中,具体支持的传感器数量、输入分辨率和输出通道数将受限于开发板的硬件配置和内存大小,因此需根据项目需求进行综合评估。
导入该模块
from media.sensor import *
构造函数
sensor = Sensor(id, width, height, fps)
参数 | 描述 |
---|---|
id | csi 端口,支持0,1,2,庐山派默认为CSI2 |
width | sensor 最大输出图像宽度,默认1920 |
height | sensor 最大输出图像高度,默认 1080 |
fps | sensor 最大输出图像帧率,默认 30 |
1.reset
# 初始化 sensor 以及传感器 GC2093
sensor.reset()
复位 sensor 对象。在构造 Sensor 对象后,必须调用此函数以继续执行其他操作
参数:无
返回值:无
2.set_framesize
sensor.set_framesize(framesize=FRAME_SIZE_INVALID, chn=CAM_CHN_ID_0, alignment=0, **kwargs)
kwargs是关键词参数(keyword argument)的缩写,目前可以输入的参数有width和height,这两个参数和framesize所设置的分辨率是一个东西,所以是互斥的,只能二选一。
参数 | 描述 |
---|---|
framesize | sensor 输出图像尺寸 ,640x480:Sensor.VGA,1280x720:Sensor.HD,1920x1080:Sensor.FHD |
width【**kwargs】 | 输出图像宽度,kw_arg,自行填写 |
height 【**kwargs】 | 输出图像高度,kw_arg,自行填写 |
chn | sensor 输出通道号,通道0:CAM_CHN_ID_0,通道1:CAM_CHN_ID_1,通道2:CAM_CHN_ID_2 |
framesize其余大小请查看官方文档
返回值:无
输出图像尺寸不得超过图像传感器的实际输出能力。
各通道的最大输出图像尺寸受硬件限制。
# 配置 sensor 设备,输出通道 0,输出图尺寸为 640x480
sensor.set_framesize(chn=CAM_CHN_ID_0, width=640, height=480)
# 配置 sensor 设备,输出通道 1,输出图尺寸为 320x240
sensor.set_framesize(chn=CAM_CHN_ID_1, width=320, height=240)
3.set_pixformat
sensor.set_pixformat(pix_format, chn=CAM_CHN_ID_0)
配置指定通道的图像传感器输出图像格式
参数 | 描述 |
---|---|
pix_format | 输出图像格式 |
chn | sensor 输出通道号 |
pix_format 可选参数:
Sensor.RGB565,Sensor.RGB888,Sensor.RGBP888,Sensor.YUV420SP,Sensor.GRAYSCALE。
返回值:无
# 配置 sensor 设备 0,输出通道 0,输出 NV12 格式
sensor.set_pixformat(sensor.YUV420SP, chn=CAM_CHN_ID_0)
# 配置 sensor 设备 0,输出通道 1,输出 RGB888 格式
sensor.set_pixformat(sensor.RGB888, chn=CAM_CHN_ID_1)
4.set_hmirror
sensor.set_hmirror(enable)
配置图像传感器是否进行水平镜像
参数:
True:开启水平镜像功能
Flase:关闭水平镜像功能
返回值:无
sensor.set_hmirror(True)
5.set_vflip
sensor.set_vflip(enable)
配置图像传感器是否进行垂直翻转
参数:
True:开启水平镜像功能
Flase:关闭水平镜像功能
返回值:无
sensor.set_vflip(True)
6.run
# 启动 sensor 设备输出数据流
sensor.run()
启动图像传感器的输出。必须在调用 MediaManager.init() 之前执行此操作
返回值:无
当同时使用多个传感器(最多 3 个)时,仅需其中一个执行 run 即可。
7.stop
# 停止 sensor 设备 0 的数据流输出
sensor.stop()
停止图像传感器输出。必须在 MediaManager.deinit() 之前调用此方法
返回值:无
如果同时使用多个图像传感器(最多 3 个),每个传感器都需单独调用 stop。
8.snapshot
sensor.snapshot(chn=CAM_CHN_ID_0)
从指定输出通道中捕获一帧图像数据。
参数:
chn:sensor 输出通道号
返回值:
image 对象 :捕获的图像数据
其他:捕获失败
# 从 sensor 设备 0 的通道 0 捕获一帧图像数据
sensor.snapshot()
三.Display模块
初始化 Display 通路,包括 VO 模块、 DSI 模块和 LCD/HDMI。
必须在 MediaManager.init()之前调用
1.初始化init
init(type=None, width=None, height=None, osd_num=1, to_ide=False, fps=None, quality=90)
参数 | 描述 |
---|---|
type | 显示设备类型 |
width | 分辨率宽度 |
heigth | 分辨率高度 |
osd_num | 在 show_image 时支持的 LAYER 数量,越大占用内存越多 |
to_ide | 是否将屏幕显示传输到 IDE 显示,开启时占用更多内存 |
fps | 显示帧率,仅支持 VIRT 类型 |
quality | 设置 Jpeg 压缩质量,仅在 to_ide=True 时有效,范围 [10-100] |
返回值:无
1.1.type
type类型 | 分辨率和帧率(fps) | 描述 |
---|---|---|
LT9611 | 1920x1080(30),1280x720(30),640x480(60) | 1920x1080(30)为默认值 |
ST7701 | 800x480(30),854x480(30) | 800x480(30)为默认值,两种分辨率都可设置为竖屏 |
VIRT | 640x480(90) | 默认值640x480(90),IDE 调试专用,不在外接屏幕上显示内容,用户可自定义设置分辨率 (64x64)-(4096x4096) 和帧率 (1-200) |
1.2.LAYER
K230 提供 2 层视频图层支持和 4 层 OSD 图层支持
显示层 | Value |
---|---|
LAYER_VIDEO1 | 仅可在 bind_layer 中使用 |
LAYER_VIDEO2 | 仅可在 bind_layer 中使用 |
LAYER_OSD0 | 支持 show_image 和 bind_layer 使用 |
LAYER_OSD1 | 支持 show_image 和 bind_layer 使用 |
LAYER_OSD2 | 支持 show_image 和 bind_layer 使用 |
LAYER_OSD3 | 支持 show_image 和 bind_layer 使用 |
1.3.flag
标志 | 说明 |
---|---|
FLAG_ROTATION_0 | 旋转 0 度 |
FLAG_ROTATION_90 | 旋转 90 度 |
FLAG_ROTATION_180管 | 旋转 180 度 |
FLAG_ROTATION_270 | 旋转 270 度 |
FLAG_MIRROR_NONE | 不镜像 |
FLAG_MIRROR_HOR | 水平镜像 |
FLAG_MIRROR_VER | 垂直镜像 |
FLAG_MIRROR_BOTH | 水平与垂直镜像 |
2.show_image
在屏幕上显示图像
show_image(img, x=0, y=0, layer=None, alpha=255, flag=0)
参数 | 描述 |
---|---|
img | 显示的图像 |
x | 起始坐标的 x 值 |
y | 起始坐标的 y 值 |
layer | 显示到 指定层,仅支持 OSD 层,若需要多层请在 init 中设置 osd_num |
alpha | 图层混合 alpha |
flag | 显示 标志 |
返回值:无
3.deinit
执行反初始化, deinit 方法会关闭整个 Display 通路,包括 VO 模块、 DSI 模块和 LCD/HDMI。
必须在 MediaManager.deinit()之前调用
必须在 sensor.stop()之后调用
`deinit()
参数:无
返回值:无
4.bind_layer
将 sensor 或 vdec 模块的输出绑定到屏幕显示。无需用户手动干预即可持续显示图像,必须在 init 之前调用
bind_layer(src=(mod, dev, layer), dstlayer, rect=(x, y, w, h), pix_format, alpha, flag)
参数 | 描述 |
---|---|
src | sensor 或 vdec 的输出信息,可通过 sensor.bind_info() 获取 |
dstlayer | 绑定到 Display 的 显示层,可绑定到 video 或 osd 层 |
rect | 显示区域,可通过 sensor.bind_info() 获取 |
pix_format | 图像像素格式,可通过 sensor.bind_info() 获取 |
alpha | 图层混合 alpha |
flag | 显示 标志,LAYER_VIDEO1 不支持 |
返回值:无
在Canmv IDE K230上显示画面
import time, os, sys
from media.sensor import *
from media.display import *
from media.media import *
try:
# 构造一个具有默认配置的摄像头对象,默认csi id==2
sensor = Sensor()
# 重置摄像头sensor
sensor.reset()
# 设置通道0的输出尺寸为1920x1080
sensor.set_framesize(Sensor.FHD, chn=CAM_CHN_ID_0)
# 设置通道0的输出像素格式为RGB888
sensor.set_pixformat(Sensor.RGB888, chn=CAM_CHN_ID_0)
# 使用IDE的帧缓冲区作为显示输出
Display.init(Display.VIRT, width=1920, height=1080, to_ide=True)
# 初始化媒体管理器
MediaManager.init()
# 启动传感器
sensor.run()
while True:
os.exitpoint()
# 捕获通道0的图像
img = sensor.snapshot(chn=CAM_CHN_ID_0)
# 显示捕获的图像
Display.show_image(img)
except KeyboardInterrupt as e:
print("用户停止: ", e)
except BaseException as e:
print(f"异常: {e}")
finally:
# 停止传感器运行
if isinstance(sensor, Sensor):
sensor.stop()
# 反初始化显示模块
Display.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)
# 释放媒体缓冲区
MediaManager.deinit()