camera - 摄像头
作者:陈取德
一、概述
camera 核心库是 LuatOS 的一个特色功能库,按照顺序调用就可以非常快捷的使用上摄像头外设,完成拍照,扫描任务,并将扫描结果和拍照文件存储。根据摄像头类型的不同分为三种使用逻辑:
-
SPI 摄像头:
-
适用于 Air700 系列、Air780 系列、Air8000 系列产品;
- 目前合宙支持 GC0320、GC032A、BF30A2 三款摄像头,并且已经制作好了官方配置表,使用时只需要使用配置的函数初始化摄像头后,就可以调用 camera.capture()接口完成拍照或扫描的任务,再通过 camera.on()函数接收回调数据即可完成拍照或扫描业务;
-
USB 摄像头:
-
适用于 Air8101 系列、Air6101 系列产品;
- 支持多路 USB 摄像头,但是同时只能使用一路摄像头,根据 USB 端口号选择对应的摄像头,调用对应的初始化和拍照接口即可完成拍照业务;
-
DVP 摄像头:
-
适用于 Air8101 系列、Air6101 系列产品;
- 支持单路 DVP 摄像头,camera.init()初始化完成后执行 camera.capture()接口完成拍照或扫描任务即可完成拍照任务;
二、核心示例
1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;
2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;
3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/camera
--[[
本核心示例的的业务逻辑为:
1、创建并启动一个基础task,task名称为"camera_capture_func",在task的任务开始时阻塞等待拍照任务触发,触发后处理拍照业务的完整过程;
2、创建并启动一个基础task,task名称为"camera_press",在task的任务设定循环定时器,定时触发拍照任务;
]]
PROJECT = "camera_test"
VERSION = "001.000.000"
-- 导入GC032A摄像头驱动模块
require "gc032a"
-- 摄像头扫描模式设置:0表示拍照模式,1表示扫描模式
local scanmode = 0
-- 图像数据格式设置:0表示使用完整的YUV/RGB格式,1表示仅Y通道
local only_Y = 0
-- CAM_3V3: 控制摄像头3.3V电源的GPIO(引脚2),初始状态为关闭(0)
local CAM_3V3 = gpio.setup(2, 0)
-- CAM_PD: 控制摄像头电源使能的GPIO(引脚5),初始状态为使能(1),注意这里是高电平关闭摄像头
local CAM_PD = gpio.setup(5, 1)
-- LED: 控制补光灯的GPIO(GPIO25),初始状态为关闭(0)
local LED = gpio.setup(25, 0)
-- 摄像头事件处理函数
-- 当摄像头捕获到数据或状态变化时触发
-- 参数id: 摄像头ID
-- 参数str: 摄像头返回的数据或状态标志
local function camera_event(id, str)
-- 如果返回字符串,表示扫码成功并获得结果
if type(str) == 'string' then
log.info("扫码结果", str)
-- 如果返回false,表示摄像头没有有效数据
elseif str == false then
log.error("摄像头没有数据")
-- 如果返回true或数字,表示成功捕获到图像文件大小
elseif str == true or type(str) == 'number' then
log.info("摄像头数据", str)
-- 发布CAPTURE_DONE事件,通知其他任务拍照已完成
sys.publish("CAPTURE_DONE", true)
end
end
-- 摄像头拍照功能核心函数
local function camera_capture_func()
-- 初始化SPI和I2C接口ID
local cspiId, i2cId = 1, 1
-- 摄像头ID变量,将在初始化时赋值
local camera_id
-- 无限循环,持续监听并响应拍照请求
while true do
log.debug("摄像头拍照")
-- 等待ONCE_CAPTURE事件触发拍照流程
sys.waitUntil("ONCE_CAPTURE")
-- 删除上一次拍摄的照片,为新照片准备空间
os.remove("/text.jpg")
log.info("上一张照片已删除")
-- 初始化I2C接口,使用快速模式(400kHz)
i2c.setup(i2cId, i2c.FAST)
-- 打开摄像头电源
CAM_3V3(1) -- 开启3.3V电源
CAM_PD(0) -- 关闭电源使能(低电平有效,此时摄像头开始工作)
LED(1) -- 点亮LED指示灯,表示摄像头开始工作
-- 初始化GC032A摄像头
-- 参数依次为:SPI ID、I2C ID、时钟频率(24MHz)、扫描模式、数据格式标志
camera_id = gc032aInit(cspiId, i2cId, 24000000, scanmode, only_Y)
log.info("初始化状态", camera_id)
-- 注册摄像头数据扫描事件回调函数
camera.on(0, "scanned", camera_event)
-- 拍摄照片并保存到指定路径
-- 参数:摄像头ID、保存路径、照片质量(1为高质量)
camera.capture(camera_id, "/text.jpg", 1)
log.info("拍完了")
-- 等待拍照完成事件,设置5秒超时
local result, data = sys.waitUntil("CAPTURE_DONE", 5000)
log.info("等待结果是", result)
-- 清理资源,关闭外设
camera.close(camera_id) -- 关闭摄像头
i2c.close(i2cId) -- 关闭I2C接口
LED(0) -- 关闭LED指示灯
CAM_3V3(0) -- 关闭3.3V电源
CAM_PD(1) -- 开启电源使能(高电平,关闭摄像头)
end
end
-- 定时触发拍照的函数
local function camera_press()
-- 等待网络连接就绪,超时时间为30秒
-- 如果在30秒内没有获得网络连接,函数将继续执行
sys.waitUntil("IP_READY", 30000)
-- 设置定时器,每15秒触发一次拍照事件
while true do
sys.publish("ONCE_CAPTURE")
sys.wait(15 * 1000) -- 发布拍照事件,触发拍照流程
end
end
-- 启动两个任务:摄像头拍照任务和定时触发任务
-- 这两个任务将并行执行
-- 1. camera_capture_func:负责执行实际的拍照操作
-- 2. camera_press:负责定时触发拍照事件
sys.taskInit(camera_capture_func)
sys.taskInit(camera_press)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
三、常量详解
核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;
3.1 camera.AUTO
常量含义:摄像头自动模式,即:摄像头拍照模式;
因为当前摄像头的功能代码仅支持拍照模式和扫描模式,且摄像头在初始化时就必须指定使用模式
所以在初始化时,拍照模式使用camera.AUTO,扫描模式使用camera.SCAN;
注意!!!自动模式仅拍照功能,不会自动跳转扫描功能,如需扫描模式需要重新初始化!
数据类型:number;
适用产品:Air780E系列、Air700E系列、Air8000系列、Air8101系列、Air6101系列、Air72X系列、Air820系列;
示例代码:--如下方所示,配置摄像头初始化中第九个参数为摄像头工作在自动模式;
camera.init(1,25500000,1,1,2,1,0x00010101,0,camera.AUTO,640,480)
3.2 camera.SCAN
常量含义:摄像头扫描模式;
因为当前摄像头的功能代码仅支持拍照模式和扫描模式,且摄像头在初始化时就必须指定使用模式
所以在初始化时,拍照模式使用camera.AUTO,扫描模式使用camera.SCAN;
注意!!!自动模式仅拍照功能,不会自动跳转扫描功能,如需切换模式需要重新初始化!
数据类型:number;
适用产品:Air780E系列、Air700E系列、Air8000系列;
示例代码:--如下方所示,配置摄像头初始化中第九个参数为摄像头工作在扫描模式;
camera.init(1,25500000,1,1,2,1,0x00010101,0,camera.SCAN,640,480)
3.3 camera.USB
常量含义:摄像头接口类型为USB的摄像头;
数据类型:number;
适用产品:Air8101系列、Air6101系列;
示例代码:--如下方所示,初始化一个USB摄像头;
local usb_camera_table = {
id = camera.USB,
sensor_width = 1280,
sensor_height = 720 }
camera.init(usb_camera_table)
3.4 camera.DVP
常量含义:摄像头接口类型为DVP的摄像头;
数据类型:number;
适用产品:Air8101系列、Air6101系列;
示例代码:--如下方所示,初始化一个DVP摄像头;
local dvp_camera_table = {
id = camera.DVP,
sensor_width = 1280,
sensor_height = 720 }
camera.init(dvp_camera_table)
3.5 camera.ROTATE_0
常量含义:摄像头预览,画面不旋转;
数据类型:number;
适用产品:Air8101系列、Air6101系列;
示例代码:--如下方所示,第三个参数为配置摄像头的预览画面不旋转,默认不旋转,可不配置;
camera.config(0, camera.CONF_PREVIEW_ROTATE, camera.ROTATE_0)
3.6 camera.ROTATE_90
常量含义:摄像头预览,画面顺时针旋转90度;
数据类型:number;
适用产品:Air8101系列、Air6101系列;
示例代码:--如下方所示,第三个参数配置摄像头的预览画面顺时针旋转90度;
camera.config(0, camera.CONF_PREVIEW_ROTATE, camera.ROTATE_90)
3.7 camera.ROTATE_270
常量含义:摄像头预览,画面顺时针旋转270度;
数据类型:number;
适用产品:Air8101系列、Air6101系列;
示例代码:--如下方所示,第三个参数配置摄像头的预览画面顺时针旋转270度;
camera.config(0, camera.CONF_PREVIEW_ROTATE, camera.ROTATE_270)
3.8 camera.CONF_PREVIEW_ENABLE
常量含义:摄像头预览功能,默认开启;
数据类型:number;
适用产品:Air8101系列、Air6101系列;
示例代码:--如下方所示,第三个参数配置开启摄像头预览;
camera.config(0, camera.CONF_PREVIEW_ENABLE, 1)
3.9 camera.CONF_PREVIEW_ROTATE
常量含义:摄像头预览画面的旋转角度;
数据类型:number;
适用产品:Air8101系列、Air6101系列;
示例代码:--如下方所示,第二个参数为配置摄像头旋转角度功能,第三个参数则是实际的旋转角度参数;
camera.config(0, camera.CONF_PREVIEW_ROTATE, camera.ROTATE_90)
四、函数详解
4.1 camera.init(InitReg_or_cspi_id, cspi_speed, mode, is_msb, rx_bit, seq_type, is_ddr, only_y, scan_mode, w, h)
功能
-
SPI 摄像头:
-
初始化摄像头,因为摄像头的初始化配置参数需要向摄像头对应的配置寄存器中写入参数,一般会有一两百个参数需要配置,所以我们制作了 GC0320、GC032A、BF30A2 这三款当前支持的摄像头参数配置表,并且将摄像头初始化参数的默认值已经写好,在使用这三个型号的摄像头时只需要 require 对应的配置表,并且调用对应的初始化函数(例如:gc0310Init())即可;
-
USB、DVP 摄像头:
-
在 Air8101 系列和 Air6101 系列上支持多路 USB 摄像头,在多路摄像头使用时需要注意摄像头初始化动作,详情可参考文档 8101 多摄像头使用指南;
参数
InitReg_or_cspi_id
参数含义:摄像头参数根据摄像头接口分三种情况
1、SPI摄像头:此处需填写使用的spi编号,如使用的是SPI1,则填1;
2、USB摄像头:此处填写摄像头类型常量、分辨率和USB端口号;
3、DVP摄像头:此处填写摄像头类型常量、分辨率;
数据类型:table/number;
取值范围:1、SPI摄像头(number):0-1;
2、USB摄像头(table):camera.USB、分辨率和USB端口号;
3、DVP摄像头(table):camera.DVP、分辨率;
是否必选:必须传入此参数;
注意事项:USB摄像头和DVP摄像头均以table形式传入,不需要配置后续参数;
SPI摄像头只需要传入所使用的SPI线号,需要配置后续参数;
参数示例:--如下方所示,为DVP摄像头初始化传入的第一个参数;
local camera_id = camera.DVP
local dvp_camera_table = {
id = camera_id,
sensor_width = 1280,
sensor_height = 720
}
local result = camera.init(dvp_camera_table)
--如下方所示,为USB摄像头初始化传入的第一个参数;
local camera_id = camera.USB
local usb_camera_table = {
id = camera_id,
sensor_width = 1280,
sensor_height = 720,
usb_port = 1
}
local result = camera.init(usb_camera_table)
--如下方所示,为SPI摄像头初始化传入的第一个参数;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
cspi_speed
参数含义:摄像头SPI速率参数;
数据类型:number;
取值范围:24000000;
是否必选:必须传入此参数;
注意事项:GC0320和GC032A的最大输入时钟频率为24 MHz;
所以默认输入24000000,其余摄像头需根据摄像的规格书决定;
参数示例:--如下方所示,第二参数为SOC和摄像头之间的通信速率为24MHz;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
mode
参数含义:摄像头SPI工作模式;
数据类型:number;
取值范围:0-3;
是否必选:必须传入此参数;
注意事项:根据摄像头的SPI协议工作模式决定;
GC032A/GC0320均是SPI工作模式1;
BF30A2是SPI工作模式0;
参数示例:--如下方所示,第三参数为SOC的SPI工作模式为1;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
is_msb
参数含义:SPI传输中的BIT顺序是否为MSB;
数据类型:number;
取值范围:0为否、1为是;
是否必选:必须传入此参数;
注意事项:参考摄像头规格书;
GC032A/GC0320为1;
BF30A2为0;
参数示例:--如下方所示,第四参数为以MSB最高有效位开始传输;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
rx_bit
参数含义:摄像头SPI传输中单个时钟周期内能够接收的数据位数量;
数据类型:number;
取值范围:1、2、4;
是否必选:必须传入此参数;
注意事项:参考摄像头规格书;
GC032A/GC0320为2;
BF30A2为1;
参数示例:--如下方所示,第五参数为单个时钟周期内能够接收的数据位数量为2个bit;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
seq_type
参数含义:摄像头SPI传输中的字节顺序;
数据类型:number;
取值范围:1为大端序,0为小端序;
是否必选:必须传入此参数;
注意事项:参考摄像头规格书;
GC032A/GC0320为1;
BF30A2为0;
参数示例:--如下方所示,第六参数为字节顺序以大端序传输;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
is_ddr
参数含义:摄像头SPI-ddr模式;
数据类型:number;
取值范围:0x00010101;
是否必选:必须传入此参数;
注意事项:参考摄像头规格书,开始DDR模式后支持双边采样;
可在单个时钟周期内能够接收2个数据位,GC032A/GC0320为0x00010101;
BF30A2为0;
参数示例:--如下方所示,第七参数为开始SPI-ddr模式,双边采样;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
only_y
参数含义:摄像头是否只采集亮度信息;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:应用于扫码模式,扫码时只需要采集Y分量,即亮度信息即可,不需要采集颜色信息;
拍照模式此参数为0,扫描模式此参数为1;
参数示例:--如下方所示,第七参数为关闭只采集Y分量,即关闭扫描模式;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
scan_mode
参数含义:是否为扫描模式;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:拍照模式传入0,扫描模式传入1,扫描模式时,only_y需要填1;
参数示例:--如下方所示,第八参数为非扫描模式,所以only_y也为0;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
w
参数含义:摄像头分辨率宽度;
数据类型:number;
取值范围:参考摄像头规格书;
是否必选:必须传入此参数;
注意事项:各类摄像头分辨率不同,以GC032A/GC0320举例,他们的分辨率宽度均为640像素,所以传入640;
BF30A2为的分辨率宽度为240,所以传入240;
参数示例:--如下方所示,第九参数为分辨率宽度640;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
h
参数含义:摄像头分辨率高度;
数据类型:number;
取值范围:参考摄像头规格书;
是否必选:必须传入此参数;
注意事项:各类摄像头分辨率不同,以GC032A/GC0320举例,他们的分辨率高度均为480像素,所以传入480;
BF30A2为的分辨率高度为320,所以传入320;
参数示例:--如下方所示,第十参数为分辨率宽度480;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
返回值
local result = camera.init(InitReg_or_cspi_id, cspi_speed, mode, is_msb, rx_bit, seq_type, is_ddr, only_y, scan_mode, w, h)
会有一个返回值 result
result
参数含义:摄像头初始化结果;
数据类型:boolean or number;
取值范围:成功时返回摄像头ID,失败时返回false;
注意事项:摄像头执行时都是通过回调函数来通知结果,并且都是推送至初始化成功后返回的摄像头ID;
参数示例:--如下方所示,摄像头初始化成功后会返回摄像头ID给result,需要用这个ID注册回调;
local result = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
例子
--如下方所示,为DVP摄像头初始化传入的第一个参数;
local camera_id = camera.DVP
local dvp_camera_table = {
id = camera_id,
sensor_width = 1280,
sensor_height = 720
}
local result = camera.init(dvp_camera_table)
--如下方所示,为USB摄像头初始化传入的第一个参数;
local camera_id = camera.USB
local usb_camera_table = {
id = camera_id,
sensor_width = 1280,
sensor_height = 720,
usb_port = 1
}
local result = camera.init(usb_camera_table)
--如下方所示,为SPI摄像头初始化传入的第一个参数;
local id = camera.init(1,24000000,1,1,2,1,0x00010101,0,0,640,480)
4.2 camera.on(id , event , func)
功能
注册摄像头事件回调
注意事项
初始化摄像头成功后,所有摄像头事件均是由回调函数触发,所以在初始化成功后需马上注册回调,及时接收到摄像头执行任务后的结果;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,注册ID为1的摄像头相关回调事件;
local function camera_event(id, str)
if type(str) == 'string' then
log.info("扫码结果", str)
elseif str == false then
log.error("摄像头没有数据")
else
log.info("摄像头数据", str)
sys.publish("CAPTURE_DONE", true)
end
end
camera.on(1, "scanned", camera_event(id, str))
event
参数含义:摄像头事件topic;
数据类型:string;
取值范围:"scanned";
是否必选:必须传入此参数;
注意事项:所有摄像头事件均是推送至"scanned"这个topic里,通过判断这个topic所携带的ID和数据即可;
参数示例:--如下方所示,注册ID为1的摄像头相关回调事件
--判断触发回调时所携带的ID和数据并做出对应的处理;
local function camera_event(id, str)
if type(str) == 'string' then
log.info("扫码结果", str)
elseif str == false then
log.error("摄像头没有数据")
elseif str == true or type(str) == 'number' then
log.info("摄像头数据", str)
sys.publish("CAPTURE_DONE", true)
end
end
camera.on(1, "scanned", camera_event(id, str))
--摄像头会出现四种事件
false 摄像头没有正常工作,检查硬件和软件配置;
true 拍照模式下拍照成功并保存完成,可以读取照片文件数据进一步处理,比如读出数据上传;
number 拍照完成后的照片文件大小;
string 扫码完成后的扫码结果;
func
参数含义:摄像头回调函数;
数据类型:function;
取值范围:0;
是否必选:必须传入此参数;
注意事项:处理底层推送的摄像头事件所携带的id和数据,参考event的实际事件;
参数示例:--如下方所示,第三个参数是处理各种EVENT事件的回调函数;
local function camera_event(id, str)
if type(str) == 'string' then
log.info("扫码结果", str)
elseif str == false then
log.error("摄像头没有数据")
elseif str == true or type(str) == 'number' then
log.info("摄像头数据", str)
sys.publish("CAPTURE_DONE", true)
end
end
camera.on(1, "scanned", camera_event(id, str))
返回值
无
例子
--如下方所示,注册ID为1的摄像头相关回调事件
--判断触发回调时所携带的ID和数据并做出对应的处理;
local function camera_event(id, str)
if type(str) == 'string' then
log.info("扫码结果", str)
elseif str == false then
log.error("摄像头没有数据")
elseif str == true or type(str) == 'number' then
log.info("摄像头数据", str)
sys.publish("CAPTURE_DONE", true)
end
end
camera.on(1, "scanned", camera_event(id, str))
--摄像头会出现四种事件
false 摄像头没有正常工作,检查硬件和软件配置;
true 拍照模式下拍照成功并保存完成,可以读取照片文件数据进一步处理,比如读出数据上传;
number 拍照完成后的照片文件大小;
string 扫码完成后的扫码结果;
4.3 camera.start(id)
功能
开始指定的摄像头,在初始化完摄像头后如果并不是马上需要拍照,可以先调用 camera.stop()暂停摄像头,拍照前再调用 camera.start()打开即可;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后,后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,打开ID为1的摄像头,并将打开结果赋值给result;
local result = camera.start(1)
返回值
local result = camera.start(id)
会有一个返回值 result
result
参数含义:摄像头打开的结果;
数据类型:boolean;
取值范围:成功时返回true,失败时返回false;
注意事项:合宙官方的配置表中有执行camera.start(),不需要额外执行;
参数示例:--如下方所示,摄像头打开成功后返回true;
local result = camera.start(1)
例子
camera.start(0)
4.4 camera.stop(id)
功能
暂停指定的 camera;
注意事项
是暂停不是关闭,暂停后可直接调用 camera.start()再开启摄像头拍照或者扫描,不需要再初始化;
合宙官方摄像头配置表内已经调用了 camera.start(),如果调用接口 camera.init 初始化后不,需要立马拍照需及时调用 camera.stop()暂停摄像头,避免造成资源浪费;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,暂停ID为1的摄像头,并将暂停结果赋值给result;
local result = camera.stop(1)
返回值
local result = camera.stop(id)
会有一个返回值 result
result
参数含义:摄像头暂停的结果;
数据类型:boolean;
取值范围:成功时返回true,失败时返回false;
注意事项:合宙官方的配置表中有执行camera.start(),如果不是马上需要拍照或扫描,需要及时暂停;
参数示例:--如下方所示,摄像头暂停成功后返回true;
local result = camera.stop(1)
例子
camera.stop(0)
4.5 camera.close(id)
功能
关闭指定的 camera,释放相应的 IO 资源
注意事项
Air780 系列、Air700 系列、Air8000 系列:
SPI 摄像头会占用 2 路 I2C、1 路 UART 和 2 路 onewire,在 SPI 摄像头启动时无法复用,所以摄像头业务执行完毕后可以调用 camera.close()关闭摄像头,释放 IO 资源;
Air8101 系列、Air6101 系列:
DVP 摄像头会占用 1 路 UART、1 路 I2C、6 路 PWM 并且同样管脚可复用一路 SPI 或一路以太网,DVP 摄像头启用时无法复用,所以摄像头业务执行完毕后可以调用 camera.close()关闭摄像头,释放 IO 资源;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,关闭ID为1的摄像头,并将关闭结果赋值给result;
local result = camera.close(1)
返回值
local result = camera.close(id)
会有一个返回值 result
result
参数含义:摄像头关闭的结果;
数据类型:boolean;
取值范围:成功时返回true,失败时返回false;
注意事项:摄像头业务完成后可关闭SPI摄像头,释放IO资源复用其他业务;
参数示例:--如下方所示,摄像头关闭成功后返回true;
local result = camera.close(1)
例子
camera.close(0)
4.6 camera.capture(id, save_path, quality, x, y, w, h)
功能
摄像头初始化成功后执行拍照或扫描业务;
可根据参数直接在这个接口里完成照片的裁切动作;
注意事项
执行拍照任务前一定要调用 camera.start()接口将摄像头打开;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,ID为1的摄像头执行一次拍照任务;
local result = camera.capture(1, "/capture.jpg", 80)
save_path
参数含义:执行完成拍照任务后的文件保存路径;
数据类型:string/zbuff/nil;
取值范围:0;
是否必选:否;
注意事项:这个参数一般存在3种情况
1、将文件保存在模块内存中,在模块运行过程中会有内存占满风险,如果没有做好内存管理,将有可能会造成内存不够,导致拍照执行成功,但是没有照片文件的情况;
2、将文件保存在外挂SD卡或者FLASH里;
3、使用ZBUFF存储结果,这种方式可以主动判断ZBUFF空间的大小来确保拍照后照片文件有足够地方存储,避免因空间不够导致的拍照执行成功,但是没有照片文件的情况;
为确保拍照任务能够正确执行并返回结果,请使用ZBUFF存储照片文件再写至内存、外挂FLASH或执行联网上传;
参数示例:--如下方所示,参数二是将拍照结果保存至/capture.jpg路径下;
local result = camera.capture(1, "/capture.jpg", 80)
quality
参数含义:jpeg压缩质量;
数据类型:number;
取值范围:50-95;
是否必选:必须传入此参数;
注意事项:jpeg压缩质量,请使用 50 - 95 之间的数值,超出范围会导致质量过高,拍照执行失败;
数值越大,照片质量越好,但是照片的整体质量是通过配置表的参数配置去优化的
目前的官方配置表已经是最优配置,调整压缩质量效果已经微乎其微;
参数示例:--如下方所示,第三个参数为输出jpeg压缩质量为80的照片;
local result = camera.capture(1, "/capture.jpg", 80)
x
参数含义:裁剪起始横坐标;
数据类型:number;
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:X参数为从左开始的横向裁切宽度;
例如X为10,则裁切掉左边10列像素;
参数示例:--如下方所示,第四个参数为输出的照片结果裁切掉左边10列像素;
local result = camera.capture(1, "/capture.jpg", 80,10,15 , 310 , 465)
y
参数含义:裁剪起始纵坐标;
数据类型:number;
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:y参数为从最下开始向上的纵向裁切高度;
例如y为15,则裁切掉最下面15行像素;
参数示例:--如下方所示,第五个参数为输出的照片结果裁切掉下面15行像素;
local result = camera.capture(1, "/capture.jpg", 80,10,15 , 310 , 465)
w
参数含义:裁剪后的宽度;
数据类型:number;
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:w参数为从w像素列开始至摄像头初始化时配置的照片宽度裁切;
例如w为310,则裁切掉310列以后的所有像素;
参数示例:--如下方所示,第六个参数为输出的照片结果裁切掉右边310列以后的所有像素;
local result = camera.capture(1, "/capture.jpg", 80,10,15 , 310 , 465)
h
参数含义:裁剪后的高度;
数据类型:number;
取值范围:根据所使用摄像头实际支持的像素尺寸决定;
是否必选:不填写则默认按照摄像头初始化时的像素原尺寸输出;
注意事项:h参数为从h像素行开始至摄像头初始化时配置的照片高度裁切;
例如h为465,则裁切掉465行以后的所有像素;
参数示例:--如下方所示,第七个参数为输出的照片结果裁切掉上边465列以后的所有像素;
local result = camera.capture(1, "/capture.jpg", 80,10,15 , 310 , 465)
返回值
local result = camera.capture(1, "/capture.jpg", 80,10,15 , 310 , 465)
会有一个返回值 result
result
参数含义:拍照或扫描的结果;
数据类型:boolean;
取值范围:成功时返回true,失败时返回false;
注意事项:该返回值只反馈拍照或扫码是否成功执行;
不携带拍照或扫描的文件,文件需要通过camera.on设置的回调函数接收;
参数示例:--如下方所示,拍照或扫描成功执行则返回true;
local result = camera.capture(1, "/capture.jpg", 80,10,15 , 310 , 465)
例子
-- 保存到文件,质量为80
camera.capture(0, "/capture.jpg", 80)
-- 保存到内存文件系统
camera.capture(0, "/ram/123.jpg", 80)
-- 保存到zbuff,质量为80
camera.capture(0, buff, 80)
-- 拍一张经过裁切了左右10个像素列,上下15个像素行的照片
camera.capture(1, "/capture.jpg", 80,10,15 , 310 , 465)
4.7 camera.preview(id, mode)
功能
启停 camera 预览功能
注意事项
直接输出到 LCD 上,只有硬件支持 LCD 的 SOC 可以运行,启动预览前必须调用 lcd.int 等 api 初始化 LCD,预览时自动选择已经初始化过的 LCD;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,打开ID为1的摄像头预览,输出到LCD上;
local result = camera.preview(1, true)
mode
参数含义:摄像头预览开关;
数据类型:boolean;
取值范围:打开填true,关闭则填false;
是否必选:必须传入此参数;
注意事项:默认开启摄像头预览,必须要在LCD初始化之后执行预览,否则不能输出;
参数示例:--如下方所示,第二参数为打开摄像头预览;
local result = camera.preview(1, true)
返回值
local result = camera.preview(id, mode)
会有一个返回值 result
result
参数含义:摄像头预览打开的结果;
数据类型:boolean;
取值范围:成功时返回true,失败时返回false;
注意事项:必须在打开摄像头预览前执行LCD初始化,底层默认开启;
参数示例:--如下方所示,摄像头预览成功执行则返回true;
local result = camera.preview(1, true)
例子
camera.preview(1, true)
4.8 camera.pwdn_pin(id, level)
功能
摄像头 PWDN 控制脚控制;
注意事项
该接口仅用于 Air72X 系列无法用 GPIO 控制 camera pwdn 脚的平台,手动控制 camera pwdn 脚拉高或者拉低;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,控制ID为1的摄像头;
camera.pwdn_pin(1, 0)
level
参数含义:pwdn脚电平;
数据类型:number;
取值范围:1高电平,0低电平;
是否必选:必须传入此参数;
注意事项:拉高暂停摄像头,拉低开启摄像头;
参数示例:--如下方所示,第二个参数为拉低pwdn开启ID为1的摄像头;
camera.pwdn_pin(1, 0)
返回值
无
例子
-- 拉低camera pwdn脚电平,开启摄像头
camera.pwdn_pin(camera_id, 0)
4.9 camera.reset_pin(id, level)
功能
重启摄像头;
注意事项
该接口仅用于 Air72X 系列无法用 GPIO 控制 camera reset 脚的平台,手动控制 camera reset 脚拉高或者拉低;
参数
id
参数含义:摄像头初始化后返回的摄像头ID号;
数据类型:number;
取值范围:0-1;
是否必选:必须传入此参数;
注意事项:camera.init()后的返回值;
可以赋值变量后后续所有camera函数均使用该变量传入,避免造成ID错误配置错误问题;
参数示例:--如下方所示,控制ID为1的摄像头;
camera.reset_pin(1, 0)
level
参数含义:reset脚电平;
数据类型:number;
取值范围:1高电平,0低电平;
是否必选:必须传入此参数;
注意事项:拉低重启摄像头,使用时保持拉高;
参数示例:--如下方所示,第二个参数拉低reset脚重启ID为1的摄像头;
camera.reset_pin(1, 0)
返回值
无
例子
-- 拉低camera reset脚电平,重启摄像头
camera.reset_pin(camera_id, 1)
五、产品支持说明
支持 LuatOS 开发的所有产品都支持 camera 核心库。