K230 CanMV Camera 模块API手册#
前言#
概述#
本文档主要介绍K230 CanMV平台Camera模块 API使用说明及应用示例。
读者对象#
本文档(本指南)主要适用于以下人员:
技术支持工程师
软件开发工程师
缩略词定义#
简称 |
说明 |
---|---|
VICAP |
Video Input Capture,图像输入采集模块 |
MCM |
Multi Camera Management ,多摄像头管理 |
修订记录#
文档版本号 |
修改说明 |
修改者 |
日期 |
---|---|---|---|
V1.0 |
初版 |
汪成根 |
2023-09-18 |
V1.1 |
添加多sensor MCM 相关的API |
赵忠祥 |
2024-03-11 |
1. 概述#
该模块将在V1.0版本后废弃,请使用sensor模块
K230 CanMV平台Camera模块负责图像采集处理任务。本模块提供了一系列Highe Levl的API,应用开发者可以不用关注底层硬件细节,仅通过该模块提供的API即可获取不同格式和尺寸的图像。
K230 CanMV平台Camera模块包括三个独立的能力完全相同的camera设备,每个camera设备均可独立完成图像数据采集捕获处理,并可以同时输出3路图像数据。如下图所示:
sensor 0,sensor 1,sensor 2表示三个图像传感器;Camera Device 0,Camera Device 1,Camera Device 2表示三个camera设备;output channel 0,output channel 1,output channel 2表示camera设备的三个输出通道。三个图像传感器可以通过软件配置映射到不同的camera 设备。
2. API描述#
K230 CanMV平台Camera模块提供camera静态类,该类提供以下章节描述的方法。
2.1 sensor_init#
【描述】
根据指定的camera设备和sensor类型执行初始化
【语法】
def sensor_init(cls, dev_num, type)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
|
sensor_type |
sensor类型,CanMV平台定义的已经支持的各类sensor |
输入 |
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【注意】 这是使用camera模块需要调用的第一个方法。
用户不调用该方法,默认初始化camera设备0及sensor OV5647
【举例】
# 初始化camera设备0以及sensor OV5647
camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR)
【相关主题】
无
2.2 set_inbufs#
【描述】
设置指定camera设备使用的输入缓冲区个数
【语法】
def set_inbufs(cls, dev_num, num)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
输入 |
num |
输入缓冲区个数 |
输入 |
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【注意】 该方法仅在用户需要同时使用多个camera设备捕获图像时才有效。
当用户使用多个camera设备而不调用该方法时,将使用默认配置参数。这有可能存在默认配置输入缓冲区个数较少而引起丢帧问题。
【举例】
# 配置camera设备0 使用4个输入缓冲区
camera.set_inbufs(CAM_DEV_ID_0,4)
# 配置camera设备1 使用6个输入缓冲区
camera.set_inbufs(CAM_DEV_ID_1,6)
【相关主题】
无
2.3 set_outbufs#
【描述】
设置指定camera设备和通道的输出缓冲区个数
【语法】
def set_outbufs(cls, dev_num, chn_num, num)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
输入 |
chn_num |
camera输出通道号 |
输入 |
num |
输出缓冲区个数 |
输入 |
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【注意】 如果用户不调用方法,将使用默认配置。
【举例】
# 配置camera设备0,输出通道0, 使用4个输出缓冲区
camera.set_outbufs(CAM_DEV_ID_0, CAM_CHN_ID_0, 4)
# 配置camera设备0,输出通道1, 使用4个输出缓冲区
camera.set_outbufs(CAM_DEV_ID_0, CAM_CHN_ID_1, 4)
【相关主题】
无
2.4 set_outsize#
【描述】
设置指定camera设备和通道的输出图像尺寸
【语法】
def set_outsize(cls, dev_num, chn_num, width, height)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
输入 |
chn_num |
camera输出通道号 |
输入 |
width |
输出图像宽度 |
输入 |
height |
输出图像高度 |
输入 |
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【注意】
输出图像尺寸不能超过输入图像尺寸。
不同输出通道最大可输出图像尺寸由硬件限制。
用户不调用该方法,默认输出图像尺寸与输入图像一致。
【举例】
# 配置camera设备0,输出通道0, 输出图尺寸为640x480
camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, 640, 480)
# 配置camera设备0,输出通道1, 输出图尺寸为320x240
camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, 320, 240)
【相关主题】
无
2.5 set_outfmt#
【描述】
设置指定camera设备和通道的输出图像格式
【语法】
def set_outfmt(cls, dev_num, chn_num, pix_format)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
输入 |
chn_num |
camera输出通道号 |
输入 |
pix_format |
输出图像格式 |
输入 |
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【注意】 用户不调用方法,将使用默认配置。
【举例】
# 配置camera设备0,输出通道0, 输出NV12格式
camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, CAM_OUT_NV12)
# 配置camera设备0,输出通道1, 输出RGB888格式
camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, CAM_OUT_RGB888)
【相关主题】
无
2.5 start_stream#
【描述】
启动camera数据流
【语法】
def start_stream(cls, dev_num)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
输入 |
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【注意】 用户不调用方法,将使用默认配置。
【举例】
# 启动camera设备0输出数据流
camera.start_stream(CAM_DEV_ID_0)
【相关主题】
无
2.6 stop_stream#
【描述】
停止camera数据流
【语法】
def stop_stream(cls, dev_num)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
输入 |
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【注意】 用户不调用方法,将使用默认配置。
【举例】
# 停止camera设备0输出数据流
camera.stop_stream(CAM_DEV_ID_0)
【相关主题】
无
2.7 capture_image#
【描述】
从指定camera设备的支持输出通道中捕获一帧图像数据
【语法】
def capture_image(cls, dev_num, chn_num)
【参数】
参数名称 |
描述 |
输入/输出 |
---|---|---|
dev_num |
camera设备号 |
输入 |
chn_num |
camera输出通道号 |
【返回值】
返回值 |
描述 |
---|---|
image对象 |
成功 |
其他 |
失败 |
【注意】
该方法捕获的图像格式由set_outfmt方法指定。
【举例】
# 从camera设备0的通道0输出捕获一帧图像数据
camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_0)
【相关主题】
无
2.7 start_mcm_stream#
【描述】
多sensor时,启动camera数据流。多sensor时一定要先配置好各个sensor的参数,然后调该函数启动数据流。
【语法】
def start_mcm_stream(cls)
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【举例】
# 启动camera设备0输出数据流
camera.start_mcm_stream()
【相关主题】
无
2.8 stop_mcm_stream#
【描述】
多sensor时,停止camera数据流。与start_mcm_stream配套使用。
【语法】
def stop_mcm_stream(cls, dev_num)
【返回值】
返回值 |
描述 |
---|---|
0 |
成功。 |
非 0 |
失败,其值为[错误码] |
【举例】
# 停止camera设备0输出数据流
camera.stop_mcm_stream()
【相关主题】
无
3. 数据结构描述#
K230 CanMV平台Camera模块包含如下描述的各个数据定义。
3.1 sensor类型#
【说明】
下面是目前Canmv-K230板micropython支持的Sensor。 其中CSI1/2是可以使用树莓派的ov5647模组,如果使用Canmv-K230 V1.0/1.1版的板子,要修改该模组的电压。
【定义】
CAM_IMX335_2LANE_1920X1080_30FPS_12BIT_USEMCLK_LINEAR # Imx335 CSI0
CAM_OV5647_1920X1080_30FPS_10BIT_USEMCLK_LINEAR # OV5647 CSI0
CAM_OV5647_1920X1080_CSI1_30FPS_10BIT_USEMCLK_LINEAR # OV5647 CSI1
CAM_OV5647_1920X1080_CSI2_30FPS_10BIT_USEMCLK_LINEAR # OV5647 CSI2
# the default sensor type
CAM_DEFAULT_SENSOR = CAM_OV5647_1920X1080_30FPS_10BIT_USEMCLK_LINEAR # 默认的sensor使用OV5647 CSI0
【注意事项】
Canmv-K230 V1.0/1.1版的板子外设接口为1.8V,不能直接使用树莓派的ov5647模组,必须修改电压为1.8V。
【相关数据类型及接口】
3.2 输出图像尺寸#
【说明】
定义各个输出通道能够支持的输出图像最大尺寸和最小尺寸
【定义】
CAM_CHN0_OUT_WIDTH_MAX = 3072
CAM_CHN0_OUT_HEIGHT_MAX = 2160
CAM_CHN1_OUT_WIDTH_MAX = 1920
CAM_CHN1_OUT_HEIGHT_MAX = 1080
CAM_CHN2_OUT_WIDTH_MAX = 1920
CAM_CHN2_OUT_HEIGHT_MAX = 1080
CAM_OUT_WIDTH_MIN = 64
CAM_OUT_HEIGHT_MIN = 64
【注意事项】
无
【相关数据类型及接口】
4. 示例程序#
例程#
# 本示例程序包括以下内容:
# 1. 配置camera设备0同时输出三路图像数据
# 2. 通道0输出YUV格式用于预览显示,通道1、2输出RGB888P
# 3. 抓取三路输出的图像各100张
#
from media.camera import * #导入camera模块,使用camera相关接口
from media.display import * #导入display模块,使用display相关接口
from media.media import * #导入media模块,使用meida相关接口
from time import * #导入time模块,使用time相关接口
import time
import image #导入image模块,使用image相关接口
def canmv_camera_test():
print("canmv_camera_test")
#初始化HDMI显示
display.init(LT9611_1920X1080_30FPS)
#初始化默认sensor配置(OV5647)
camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR)
#camera.sensor_init(CAM_DEV_ID_0, CAM_IMX335_2LANE_1920X1080_30FPS_12BIT_LINEAR)
out_width = 1920
out_height = 1080
# 设置输出宽度16字节对齐
out_width = ALIGN_UP(out_width, 16)
#设置通道0输出尺寸
camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, out_width, out_height)
#设置通道0输出格式
camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420)
#创建媒体数据源设备
media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0)
#创建媒体数据接收设备
media_sink = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1)
#创建媒体链路,数据从源设备流到接收设备
media.create_link(media_source, media_sink)
#设置显示输出平面的属性
display.set_plane(0, 0, out_width, out_height, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1)
out_width = 640
out_height = 480
out_width = ALIGN_UP(out_width, 16)
#设置通道1输出尺寸
camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, out_width, out_height)
#设置通道1输出格式
camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888)
#设置通道2输出尺寸
camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_2, out_width, out_height)
#设置通道2输出格式
camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_2, PIXEL_FORMAT_RGB_888_PLANAR)
#初始化媒体缓冲区
ret = media.buffer_init()
if ret:
print("canmv_camera_test, buffer init failed")
return ret
#启动摄像头数据流
camera.start_stream(CAM_DEV_ID_0)
time.sleep(15)
capture_count = 0
while capture_count < 100:
time.sleep(1)
for dev_num in range(CAM_DEV_ID_MAX):
if not camera.cam_dev[dev_num].dev_attr.dev_enable:
continue
for chn_num in range(CAM_CHN_ID_MAX):
if not camera.cam_dev[dev_num].chn_attr[chn_num].chn_enable:
continue
print(f"canmv_camera_test, dev({dev_num}) chn({chn_num}) capture frame.")
#从指定设备和通道捕获图像
img = camera.capture_image(dev_num, chn_num)
if img == -1:
print("camera.capture_image failed")
continue
if img.format() == image.YUV420:
suffix = "yuv420sp"
elif img.format() == image.RGB888:
suffix = "rgb888"
elif img.format() == image.RGBP888:
suffix = "rgb888p"
else:
suffix = "unkown"
filename = f"/sdcard/dev_{dev_num:02d}_chn_{chn_num:02d}_{img.width()}x{img.height()}_{capture_count:04d}.{suffix}"
print("save capture image to file:", filename)
with open(filename, "wb") as f:
if f:
img_data = uctypes.bytearray_at(img.virtaddr(), img.size())
# save yuv data to sdcard.
#f.write(img_data)
else:
print(f"capture_image, open dump file failed({filename})")
time.sleep(1)
#释放捕获的图像数据
camera.release_image(dev_num, chn_num, img)
capture_count += 1
#停止摄像头输出
camera.stop_stream(CAM_DEV_ID_0)
#去初始化显示设备
display.deinit()
#销毁媒体链路
media.destroy_link(media_source, media_sink)
time.sleep(1)
#去初始化媒体缓冲区资源
ret = media.buffer_deinit()
if ret:
print("camera test, media_buffer_deinit failed")
return ret
print("camera test exit")
return 0
canmv_camera_test()