摄像头拍照不稳定的原因与优化要点

在嵌入式物联网项目落地过程中,摄像采集是车牌识别、人脸门禁、智能回收设备的核心基础功能。

设备投入实地使用后,各类运行异常接连出现,频繁的故障处理与设备返修极大拖慢项目进度。

摄像头启停不稳、拍摄失效、运行宕机等问题,根源集中在内存管控不到位。使用封装完善的 excamera 库,理顺底层运行逻辑,补齐场景化代码,能高效完成摄像功能开发部署。
图片

一、常规模式:长供电循环拍照

在长供电场景下,摄像头可以一直稳定上电,为了确保摄像头业务的正常执行,只需要做一次摄像头初始化,后续重复调用excamera.photo获取照片结果即可——原理是将摄像头业务执行时所使用的内存区域占好,确保摄像头业务正常执行。

根据照片保存路径不同,会有以下内存使用差异:

1.1 ZBUFF/RAM路径存储

这个路径是将照片结果存放在sys ram中,差异是使用ZBUFF方式存储时,excamera会将预占用足够存储照片的空间,确保照片可以输出,RAM路径存储可能会因为其他业务的内存占用导致照片输出异常。因为两个方式都是存在内存中,所以直接使用ZBUFF即可。

**内存占用大小计算方式为:**摄像头像素高 X 摄像头像素宽 X 3.5

**以GC032A摄像头为例:**像素高为640,像素宽为480,则640 X 480 X 3.5 = 1075200 (B) ≈ 1MB

也就是说:在使用GC032A,ZBUFF方式存储照片结果的环境下,当调用excamera.open() 后,sys ram就会被占用1MB。

后续只需要循环调用excamera.photo()获取照片即可,这1MB内存占用不会变大,当出现拍照报错时,再调用关闭接口重新初始化。

参考代码如下:

-- 引入excamera扩展库模块
local excamera = require "excamera"

-- 定义照片存储路径
local save_method = "ZBUFF"
-- local save_method = "/ram/test.jpg"

function camera_func()

    -- 出现异常后重新初始化
    while true do
        -- 配置gc032a摄像头参数表
        local spi_camera_param = {
            id = "gc032a", -- SPI摄像头仅支持"gc032a""gc0310""bf30a2",请带引号填写
            i2c_id = 1, -- 模块上使用的I2C编号
            work_mode = 0, -- 工作模式,0为拍照模式,1为扫描模式
            save_path = nil, -- 扫描结果为字符串返回,使用变量赋值既可
            camera_pwr = 2, -- 摄像头使能管脚,填写GPIO号即可,无则填nil
            camera_pwdn = 5, -- 摄像头pwdn开关脚,填写GPIO号即可,无则填nil
            camera_light = nil -- 摄像头补光灯控制管脚,填写GPIO号即可,无则填nil
        }

        -- 初始化摄像头,传入配置参数
        result = excamera.open(spi_camera_param)
        -- 记录摄像头初始化状态
        log.info("初始化状态", result)

        -- 循环触发拍照任务
        while result do
            -- 执行拍照操作
            result, data = excamera.photo()
            -- 判断拍照任务正常则上传,错误则重新初始化摄像头
            if result then
                -- 执行照片上传
                -- (upload...)
            end
        end
        -- 关闭摄像头,重新初始化
        excamera.close(true)
    end
end

sys.taskInit(camera_func)
1.2 文件系统存储

使用外挂SD卡或SoC内的FLASH来存储照片时,因为excamera.photo() 是直接将照片结果输出到路径的,内存不需要存储照片结果,所以excamera.open() 初始化后,只会占用摄像头业务所需要的内存。

**内存占用大小计算方式为:**摄像头像素高 X 摄像头像素宽 X 2

**以GC032A摄像头为例:**像素高为640,像素宽为480,则640 X 480 X 2 = 614400 (B) ≈ 620KB

参考代码同上,只需路将路径修改为文件路径:

-- 定义照片存储路径
local save_method = "/SD/ABC.jpg"
二、低功耗模式:电池供电间歇拍照

在低功耗应用中,为了将功耗降到最低,都会在拍摄任务完成后将摄像头完全关断,等待下次唤醒后再上电重新初始化应用。

这种场景下为了确保摄像头业务能够正常执行,就必须要有足够的连续内存。

因为脚本各类功能持续的工作,内存被反复占用和释放后,即便此时内存有足够的余量,也没有连续的内存能够给摄像头使用,所以此时的最优解是——重启设备,把内存刷新,并且在刚开机的时候就将摄像头初始化完成,让摄像头业务先占用好足够的内存空间,以便后续业务随时调用摄像头使用。

参考代码如下:

-- 引入excamera扩展库模块
local excamera = require "excamera"

-- 定义照片存储路径
local save_method = "ZBUFF"
-- local save_method = "/ram/test.jpg"

function camera_func()

    -- 配置gc032a摄像头参数表
    local spi_camera_param = {
        id = "gc032a", -- SPI摄像头仅支持"gc032a""gc0310""bf30a2",请带引号填写
        i2c_id = 1, -- 模块上使用的I2C编号
        work_mode = 0, -- 工作模式,0为拍照模式,1为扫描模式
        save_path = nil, -- 扫描结果为字符串返回,使用变量赋值既可
        camera_pwr = 2, -- 摄像头使能管脚,填写GPIO号即可,无则填nil
        camera_pwdn = 5, -- 摄像头pwdn开关脚,填写GPIO号即可,无则填nil
        camera_light = nil -- 摄像头补光灯控制管脚,填写GPIO号即可,无则填nil
    }

    -- 初始化摄像头,传入配置参数
    local result = excamera.open(spi_camera_param)

    if not result then
        -- 记录摄像头初始化状态
        log.info("已无足够连续内存用于拍照业务执行,重启刷新内存后重试", result)
        reboot()
    end

    -- 执行拍照操作
    result, data = excamera.photo()
    -- 判断拍照任务正常则上传,错误则重新初始化摄像头
    if result then
        -- 执行照片上传
        -- (upload...)
    end
    -- 关闭摄像头,重新初始化
    excamera.close(true)
end

sys.taskInit(camera_func)
三、裁切照片应用:扫码/人脸/车牌识别…

在实际产品中,我们往往不需要整张照片,只关心其中一小块区域。

3.1 常见应用场景例如:
  • 二维码/条码识别码点在整图中占比很小,裁切后可减少干扰、提升识别速度。

  • 人脸识别门禁只需人脸区域,丢掉背景既保护隐私又降低传输流量。

  • 车牌识别路口监控只需截取车牌那一小条,上传体积从几百KB降到几十KB。

这时可以使用excamera.photo(x, y, w, h) 完成照片裁切,只输出你需要的矩形区域。

3.2 内存代价:

使用x,y,w,h参数裁切照片时,内存会额外占用空间=摄像头像素高 X 摄像头像素宽 X 1.5

这个内存额外占用仅在执行excamera.photo(x,y,w,h) 期间,当获取到照片结果时就会被释放掉,根据实际拍照应用需求,预备足够的内存余量再执行拍照业务。

四、小结——拍照方案最优解

根据上述的应用参考,假设使用GC032A时,内存会有1MB~1.5MB被占用,在Air780EPM这类4MB+4MB小内存的SoC上,sys ram分配只有2.3MB ,基本占用了一大半,剩余1MB左右可以给其他业务使用,极易造成内存爆满的情况。

所以当有摄像头需求时:
选择Air8000系列、Air780EHM/EHV/EGH等,8MB+8MB及其以上大内存的SoC才是最优解。

结合上述的应用参考,在脚本中增加足够的保护机制,就可以让摄像头业务稳定执行,增加产品的稳定性和更长的使用生命周期。

嵌入式设备拍照异常,几乎都来自内存问题。长供电要固定占用内存,低功耗要开机初始化,裁切要预留临时内存。小内存芯片容易爆满,建议使用更大内存硬件。正确管理内存,摄像头就能长期稳

今天的内容分享到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值