引言:随着图像处理技术的不断发展,摄像头在嵌入式系统中的应用越来越广泛,尤其是在智能监控、自动驾驶、机器人视觉等领域。K230作为一款高性能的嵌入式处理器,提供了强大的图像处理能力,支持多种类型的摄像头接入与图像采集功能。在使用K230进行图像识别应用时,了解和掌握图像传感器(Sensor)的工作原理与控制方法是至关重要的。本文章将详细解析K230平台下如何通过操作摄像头Sensor模块,进行图像获取与处理,帮助开发者深入理解K230摄像头架构及其相关功能。
目录
[三、Sensor 部分函数解析](#三、Sensor 部分函数解析)
一、MIPI摄像头
摄像头用的是立创商城的 GC2093 如下图所示。
特性/比较维度 | CMOS传感器 | CCD传感器 |
---|---|---|
工作原理 | 每个像素独立工作,利用晶体管直接进行信号转换与放大。 | 光电信号通过一个连续的电荷传递链传输到信号输出端。 |
图像质量 | 成像质量逐年提高,特别在低光环境下的性能不断优化。 | 高动态范围和低噪声,特别在低光条件下表现出色。 |
功耗 | 相对较低,适合移动设备和功耗敏感的应用。 | 功耗较高,需要较大的电力支持,通常用于静态设备。 |
速度(帧率) | 通常较高,适合需要高速成像的应用,如视频流。 | 帧率较低,但在高分辨率下仍能提供稳定的输出。 |
尺寸和集成度 | 通常更小,更易于集成在紧凑的设备中。 | 尺寸较大,集成度较低,通常用于单独的成像模块。 |
噪声水平 | 相比 CCD,噪声较高,但随着技术进步有所改善。 | 噪声较低,成像效果更为平滑,尤其在低光条件下。 |
动态范围 | 动态范围在低光环境下较差,但在光照充足时表现较好。 | 动态范围较广,适用于对高对比度要求的场景。 |
色彩还原 | 在高光照条件下色彩还原较为准确,尤其是在高分辨率情况下。 | 色彩还原优秀,特别适合在复杂光照条件下的拍摄。 |
成本 | 相对较低,制造工艺成熟,成本优势明显。 | 较高,制造工艺复杂且成本较高。 |
温度稳定性 | 对温度变化的稳定性较差,可能导致信号失真。 | 对温度变化的稳定性较好,能够更好地适应环境变化。 |
使用场景 | - 智能手机、数码相机、安防监控、无人机等。 - 高帧率视频、实时图像处理、低功耗设备。 | - 专业相机、高端天文望远镜、医学影像设备等。 - 对图像质量要求极高、低光环境的成像。 |
优点 | - 成本低、功耗低、速度快、尺寸小。 - 适合大规模生产。 | - 成像质量高,噪声低,动态范围广。 - 适合高质量成像要求。 |
缺点 | - 图像噪声较高、低光表现差。 - 动态范围有限。 | - 成本高、功耗大、集成度差。 |
名称 | 参数 |
---|---|
焦距(EFL) | 4.3MM |
光圈(F.NO) | 2.0 |
视场角(View Angle) | D73°/H65°/V40° |
畸变 | <0.5% |
原理图如下所示,我们补充一下mipi线序的知识,如下为原理图中的2lane的案例。
如下为4lane的CSI 显示的接口,可以看出来数据差分线的个数变化。
二、K230的摄像头架构
K230芯片集成了两颗RISC-V处理器核心,双核玄铁C908,7nm 制程工艺,主频高达1.6GHz,是全球首款支持RISC-V Vector 1.0标准的商用SOC,配备第三代KPU处理单元,专为图像、视频、音频处理和AI加速设计,提供强劲的本地AI推理能力。支持三路MIPI CSI视频输入,最大分辨率可达4K。K230支持常见的AI计算框架如TensorFlow和PyTorch。下面是该处理器的框架图:
K230的Sensor模块API提供了对这些硬件的底层控制,模块负责图像采集与数据处理。该模块提供了一套高级 API,开发者可以利用这些接口轻松获取不同格式与尺寸的图像,而无需了解底层硬件的具体实现。其架构如下图所示:
图中,sensor 0 、sensor 1 和 sensor 2 分别代表三个图像输入传感器设备;这些传感器主要用于将环境中的光信号转化为数字图像信号。在实际系统中,这些传感器可以安装在不同的位置,用来捕获来自不同视角或者区域的图像数据。图中,sensor 0 、sensor 1 和 sensor 2 分别代表三个图像输入传感器设备;这些传感器主要用于将环境中的光信号转化为数字图像信号。在实际系统中,这些传感器可以安装在不同的位置,用来捕获来自不同视角或者区域的图像数据。
每个Camera Device支持 3个输出通道 (output channel 0
、output channel 1
和 output channel 2
)。这些输出通道的主要功能是将处理后的图像数据并行传输到后续的算法模块或显示设备,同时也支持多种数据格式和尺寸。这样的架构设计,让K230能够支持多路图像数据的高效并行处理,非常适合实时性要求较高的AI视觉任务。
K230 的 sensor
模块最多支持三路图像传感器的同时接入,每一路均可独立完成图像数据的采集、捕获和处理。此外,每个视频通道可并行输出三路图像数据供后端模块进行进一步处理。实际应用中,具体支持的传感器数量、输入分辨率和输出通道数将受限于开发板的硬件配置和内存大小,因此需根据项目需求进行综合评估。
三路图像输入:
同时接入3个传感器,适合多摄像头应用场景,比如:
- 自动驾驶中的多视角检测。
- 安防监控中的多区域捕获。
- 工业检测中的多面检测。
三路图像输出:
为每个输入提供并行的多通道输出,便于在不同模块中并发处理,比如:
- 一路用于实时显示。
- 一路用于AI算法推理。
- 一路用于视频存储或回放。
三、Sensor 部分函数解析
如下为导入的包,不多赘述。
python
from media.sensor import *
1.构造函数
在图像处理应用中,用户通常需要首先创建一个 Sensor
对象。CanMV K230 软件可以自动检测内置的图像传感器,无需用户手动指定具体型号,只需设置传感器的最大输出分辨率和帧率。
python
sensor = Sensor(id, [width, height, fps])
参数
参数名称 | 描述 | 输入/输出 | 说明 |
---|---|---|---|
id | csi 端口,支持 0,1,2 |
输入 | 可选,庐山派开发板默认摄像头为CSI2 |
width | sensor 最大输出图像宽度 |
输入 | 可选,默认 1920 |
height | sensor 最大输出图像高度 |
输入 | 可选,默认 1080 |
fps | sensor 最大输出图像帧率 |
输入 | 可选,默认 30 |
返回值
返回值 | 描述 |
---|---|
Sensor 对象 | 传感器对象 |
举例如下:
python
sensor = Sensor(0, [1920, 1080, 30])
sensor
是传感器对象。- 该传感器的
id
是0
。 - 图像的分辨率是
1920x1080
,即 1080p。 - 摄像头的帧率是
30
帧每秒。
python
sensor = Sensor(1, [640, 480, 15])
sensor
是另一个传感器对象。- 该传感器的
id
是1
。 - 图像的分辨率是
640x480
,即 VGA 分辨率。 - 摄像头的帧率是
15
帧每秒。
python
sensor = Sensor(2, [3840, 2160, 60])
sensor
是第三个传感器对象。- 该传感器的
id
是2
。 - 图像的分辨率是
3840x2160
,即 4K 分辨率。 - 摄像头的帧率是
60
帧每秒。
2.复位sensor
python
sensor.reset()
3.设置sensor
指定通道的输出图像尺寸
python
sensor.set_framesize(framesize=FRAME_SIZE_INVALID, chn=CAM_CHN_ID_0, alignment=0, **kwargs)
参数名称 | 描述 | 输入/输出 |
---|---|---|
framesize | sensor 输出图像尺寸 | 输入 |
width【**kwargs】 | 输出图像宽度,kw_arg | 输入 |
height 【**kwargs】 | 输出图像高度,kw_arg | 输入 |
chn | sensor 输出通道号 | 输入 |
参数可选值:
-
设置输出图像尺寸,【
framesize
】和【width
orheight
】二选一-
framesize
图像帧尺寸 分辨率 Sensor.VGA
640x480 Sensor.HD
1280x720 Sensor.FHD
1920x1080 -
width
orheight
- 这个就是自己填分辨率就行。
-
-
设置输出通道号
- chn
- 通道0:
CAM_CHN_ID_0
- 通道1:
CAM_CHN_ID_1
- 通道2:
CAM_CHN_ID_2
- 通道0:
- chn
假设你想将摄像头的分辨率设置为 VGA
(640x480),并选择通道 CAM_CHN_ID_0
python
sensor.set_framesize(framesize="FRAME_SIZE_VGA", chn="CAM_CHN_ID_0", alignment=0)
假设你要将摄像头的分辨率设置为 1080p
(1920x1080),并选择第一个摄像头通道:
python
sensor.set_framesize(framesize="FRAME_SIZE_1080P", chn="CAM_CHN_ID_0", alignment=0)
如果你使用的摄像头支持 4K 分辨率(3840x2160)
python
sensor.set_framesize(framesize="FRAME_SIZE_4K", chn="CAM_CHN_ID_0", alignment=0)
有时你可能想设置一个自定义的分辨率(例如 1280x960)
python
sensor.set_framesize(framesize=(1280, 960), chn="CAM_CHN_ID_0", alignment=0)
4.配置指定通道的图像传感器输出图像格式
python
sensor.set_pixformat(pix_format, chn=CAM_CHN_ID_0)
参数名称 | 描述 | 输入/输出 |
---|---|---|
pix_format | 输出图像格式(像素格式) | 输入 |
chn | sensor 输出通道号 | 输入 |
参数可选值:
-
设置像素格式(如果想知道这些像素格式的具体定义,请看后续的摄像头基础知识部分)
像素格式 说明 Sensor.RGB565
16 位 RGB 格式 Sensor.RGB888
24 位 RGB 格式 Sensor.RGBP888
分离的 24 位 RGB Sensor.YUV420SP
半平面 YUV Sensor.GRAYSCALE
灰度图 -
设置输出通道号
- chn
- 通道0:
CAM_CHN_ID_0
- 通道1:
CAM_CHN_ID_1
- 通道2:
CAM_CHN_ID_2
- 通道0:
- chn
假设我们要设置摄像头为 RGB565
格式(常用于图像显示和处理),并且选择第一个摄像头通道:
python
sensor.set_pixformat(pix_format="PIXFORMAT_RGB565", chn="CAM_CHN_ID_0")
如果你的应用是视频处理,可能会选择 YUV422
格式,它通常用于压缩视频流并具有较低的带宽要求:
python
sensor.set_pixformat(pix_format="PIXFORMAT_YUV422", chn="CAM_CHN_ID_0")
如果你只需要处理黑白图像,可以选择 GRAYSCALE
格式,它会将图像转换为单通道的灰度图像,每个像素占 1 字节:
python
sensor.set_pixformat(pix_format="PIXFORMAT_GRAYSCALE", chn="CAM_CHN_ID_0")
在图像存储或传输时,JPEG 格式通常用于压缩图像以减小文件大小:
python
sensor.set_pixformat(pix_format="PIXFORMAT_JPEG", chn="CAM_CHN_ID_0")
5.配置sensor
是否进行垂直翻转
python
sensor.set_vflip(enable)
True
开启垂直翻转功能
False
关闭垂直翻转功能
6.启动图像传感器的输出
python
sensor.run()
7.停止sensor
图像传感器输出
python
sensor.stop()
8.捕获sensor
一帧图像数据
python
sensor.snapshot(chn=CAM_CHN_ID_0)
四、获取sensor
的图像
- 初始化摄像头传感器和显示设备。
- 设置摄像头的帧大小和像素格式,启动摄像头。
- 初始化媒体管理器和时钟计算帧率。
- 进入主循环,每次捕获图像并显示,同时计算和打印当前的帧率。
- 在发生异常时(如用户中断或其他错误),进行异常处理。
- 最终释放资源,清理摄像头、显示设备和媒体管理器,进入睡眠模式。
python
import time, os, sys
import utime
from media.sensor import *
from media.display import *
from media.media import *
sensor_id = 2
sensor = None
try:
# 构造一个具有默认配置的摄像头对象
sensor = Sensor(id=sensor_id)
# 重置摄像头sensor
sensor.reset()
# 无需进行镜像翻转
# 设置水平镜像
# sensor.set_hmirror(False)
# 设置垂直翻转
# sensor.set_vflip(False)
# 设置通道0的输出尺寸为1920x1080
sensor.set_framesize(Sensor.FHD, chn=CAM_CHN_ID_0)
# 设置通道0的输出像素格式为RGB565
sensor.set_pixformat(Sensor.RGB888)
# 使用IDE的帧缓冲区作为显示输出
Display.init(Display.VIRT, width=1920, height=1080, to_ide=True)
# 初始化媒体管理器
MediaManager.init()
# 启动传感器
sensor.run()
#构造clock
clock = utime.clock()
while True:
os.exitpoint()
#更新当前时间(毫秒)
clock.tick()
# 捕获通道0的图像
img = sensor.snapshot(chn=CAM_CHN_ID_0)
# 显示捕获的图像
Display.show_image(img)
#打印当前fps
print("fps = ", clock.fps())
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()