AI-on-the-edge-device 参数详解:ROIImagesRetention——数字/模拟 ROI 分离图片的保留天数
【免费下载链接】AI-on-the-edge-deviceEasy to use device for connecting "old" measuring units (water, power, gas, ...) to the digital world项目地址: https://gitcode.com/GitHub_Trending/ai/AI-on-the-edge-device
导读
ROIImagesRetention是 AI-on-the-edge-device(智能抄表设备固件)中用于控制 ROI(Region of Interest,感兴趣区域)分离图片保存时长的核心存储参数。它决定了设备将表盘读数区域裁剪出的数字图片([Digits])与模拟刻度图片([Analog])在 SD 卡上保留多少天,0表示永久保留。读完本文,你将掌握该参数在config.ini中的正确配置方法、0值与默认值的边界语义,以及它在固件源码中的解析与自动清理机制。
参数定义:做什么、默认值是什么
ROIImagesRetention定义在 param-docs/parameter-pages/Digits/ROIImagesRetention.md,其核心语义如下:
| 属性 | 值 |
|---|---|
| 参数名 | ROIImagesRetention |
| 默认值 | 3 |
| 单位 | 天(Days) |
| 取值范围 | 非负整数(0= 永久保留) |
| 所属配置段 | [Digits](数字表盘)、[Analog](模拟表盘) |
一句话概括:设备最多保留过去 N 天的分离 ROI 图片,超过 N 天的图片会被自动删除;设为0则永不删除。
这一参数在数字表盘与模拟表盘两个配置段中独立存在(见 Analog/ROIImagesRetention.md,语义相同,仅作用于模拟刻度图片),两者互不干扰,可分别设置不同的保留天数。
配置位置:config.ini中的写法
在设备 SD 卡的 sd-card/config/config.ini 中,ROIImagesRetention与ROIImagesLocation(图片存放目录)成对出现,位于[Digits]与[Analog]两个段落:
[Digits] Model = /config/dig-cont_0900_s3_q.tflite CNNGoodThreshold = 0.5 ;ROIImagesLocation = /log/digit ;ROIImagesRetention = 3 main.dig1 294 126 30 54 false main.dig2 343 126 30 54 false main.dig3 391 126 30 54 false [Analog] Model = /config/ana-cont_1500_s2_q.tflite CNNGoodThreshold = 0.5 ;ROIImagesLocation = /log/analog ;ROIImagesRetention = 3 main.ana1 432 230 92 92 falsesd-card/demo/config.ini(演示配置)中的写法与此完全一致。分号;开头表示注释,即当前配置未显式设置该参数,此时固件会采用内置默认值(见下文源码分析)。要启用定期清理,将注释去掉并按需修改天数即可,例如保留一周:
ROIImagesLocation = /log/digit ROIImagesRetention = 7存放目录/log/digit、/log/analog对应 SD 卡上的 sd-card/log/digit/、sd-card/log/analog/ 目录(仓库中仅含leer.txt占位文件,实际由固件按时间结构动态创建)。
底层实现:固件源码中的解析与清理逻辑
1. 参数解析:字符串到整数
ROIImagesRetention由流程控制组件在读取配置时解析。在 ClassFlowCNNGeneral.cpp 中,配置解析器将段内每一行拆分为键值对,并对键名做大小写不敏感匹配:
if ((toUpper(splitted[0]) == "ROIIMAGESRETENTION") && (splitted.size() > 1)) { if (isStringNumeric(splitted[1])) { this->imagesRetention = std::stoi(splitted[1]); } }注意两个细节:
- 键名匹配是大小写不敏感的(
toUpper后比较),因此ROIImagesRetention、roiimagesretention等写法均能生效; - 仅当值是数字字符串(
isStringNumeric)时才写入imagesRetention,非法值会被静默忽略,回退到默认值。
2. 默认值:文档与代码的差异说明
文档标注的默认值为3,而ClassFlowImage(ROI 图片保存的基类)构造函数中imagesRetention = 5,见 ClassFlowImage.cpp。从源码结构看,代码侧默认值是 5 天,而文档与示例配置(config.ini注释行)中的参考值为 3 天。实际生效值以config.ini中的显式设置为准——这也是为何官方示例配置总是把该参数与ROIImagesLocation成对给出、便于用户显式声明的原因。
3. 清理机制:RemoveOldLogs()的工作方式
图片的自动清理由 ClassFlowImage.cpp 中的RemoveOldLogs()实现,其关键逻辑如下:
if (imagesRetention == 0) { return; // 0 = 永久保留,直接跳过清理 } time_t rawtime; time(&rawtime); rawtime = addDays(rawtime, -1 * imagesRetention + 1); // 回溯到保留窗口的边界日期 timeinfo = localtime(&rawtime); strftime(cmpfilename, 30, LOGFILE_TIME_FORMAT, timeinfo); string folderName = string(cmpfilename).LOGFILE_TIME_FORMAT_DATE_EXTR; DIR *dir = opendir(imagesLocation.c_str()); // ... 遍历目录,删除日期早于 folderName 的子目录/文件要点:
0的语义是“永久保留”:RemoveOldLogs()首先判断imagesRetention == 0,为真时直接return,不做任何删除。这与文档中“0= forever”的说明完全对应;- 按天粒度清理:固件用
addDays(rawtime, -1 * imagesRetention + 1)计算出保留窗口的边界时间,再格式化为LOGFILE_TIME_FORMAT(日期格式)与目录名比较,删除更早的日期目录。因此清理粒度是“天”,同一天内的图片要么全部保留、要么全部删除; - 目录结构:
CreateLogFolder()(同文件 L48-L56)按imagesLocation + "/" + 日期 + "/" + 小时的层级创建目录(如/log/digit/2026-09-15/06/),小时目录内即该时段的分离 ROI 图片。按日期目录组织既方便人工排查读数问题,也让按天清理实现起来非常直接。
4. 触发时机
RemoveOldLogs()是图片保存流程的一部分,仅在isLogImage(即ROIImagesLocation已配置、图片保存已启用)时为真时执行。也就是说:如果未配置ROIImagesLocation,ROI 图片根本不落盘,ROIImagesRetention也就没有实际作用——两者必须配套使用。
与相邻参数的关系
ROIImagesLocation:决定“存哪里”
ROIImagesRetention控制“存多久”,而 ROIImagesLocation.md 控制“存哪里”,默认/log/digit。文档同时给出重要警告:SD 卡写入次数有限,而设备固件不做磨损均衡(Wear Leveling),频繁写入会加速 SD 卡老化。这也是ROIImagesRetention需要按需设置而非一律开大的原因——保留天数越长,写入与占用的平衡越需谨慎。
RawImagesRetention:区分原始图与 ROI 图
不要与[TakeImage]段的RawImagesRetention(原始整帧图片保留天数)混淆。两者是独立的两套存储策略:
RawImagesRetention:控制相机原始帧(RawImagesLocation)的保留;ROIImagesRetention:控制 CNN 推理前裁剪出的数字/模拟 ROI 小图的保留。
在 main.cpp 的旧配置迁移逻辑中,两者也分别由LogfileRetentionInDays演化而来:[TakeImage]段映射为RawImagesRetention,而[Digits]、[Analog]段映射为ROIImagesRetention。
旧版本配置迁移:LogfileRetentionInDays
早期版本中该参数名为LogfileRetentionInDays。固件在启动时会自动迁移旧配置,见 main.cpp:
else if (section == "[Digits]") { migrated = migrated | replaceString(configLines[i], "LogImageLocation", "ROIImagesLocation"); migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "ROIImagesRetention"); } else if (section == "[Analog]") { migrated = migrated | replaceString(configLines[i], "LogImageLocation", "ROIImagesLocation"); migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "ROIImagesRetention"); }同时[TakeImage]段的同名参数被迁移为RawImagesRetention(L732-L733),因此升级旧固件时无需手动改名,但要注意迁移后两段图片的保留策略是各自独立的。
通过 Web 界面配置
除直接编辑config.ini外,也可在设备 Web 配置界面(edit_config_template.html)中操作。前端表单定义在 edit_config_template.html:
<input required type="number" id="Digits_ROIImagesRetention_value1" min="0" step="1" oninput="(!validity.rangeUnderflow||(value=0)) && (!validity.stepMismatch||(value=parseInt(this.value)));">Daysmin="0":界面层直接禁止输入负数,保证“0 = 永久”语义不被破坏;step="1":只接受整数天数;- 参数在
[Digits]与[Analog]两组表单中各有独立输入框; - 前端参数注册表在 readconfigparam.js 中,分别挂载到
Digits与Analog分类下。
保存后,Web 界面会把值写回config.ini的对应段落,固件下次启动(或配置热加载)时经上述解析逻辑生效。
配置建议
- 默认按官方参考值 3 天即可:ROI 分离图片主要用于调参与排查识别异常,正常运行时 3 天窗口足够回溯;
- 需要长期故障诊断时临时调大:例如怀疑识别精度下降,可临时设为
7或14,保留更长的历史裁剪图用于比对,诊断完成后再调回; - 慎用
0(永久保留):在无磨损均衡的 SD 卡上,永久保留会持续累积文件并不断写入,加速存储介质损耗(对应 ROIImagesLocation.md 中的警告);仅在调试或取证场景短期使用; - 务必与
ROIImagesLocation配套:未配置存放目录时,本参数不生效; - 注意清理粒度为天:同一天的图片会整体保留或整体删除,无法按小时精确裁剪保留窗口。
小结
ROIImagesRetention是 AI-on-the-edge-device 存储管理体系中一个“小而关键”的参数:它把分离 ROI 图片的生命周期纳入了可配置范围,用最简单的“保留 N 天 / 0 = 永久”语义配合源码中按日期目录的自动清理机制,平衡了调参需求与 SD 卡寿命。理解其解析路径(ClassFlowCNNGeneral配置读取)、清理实现(ClassFlowImage::RemoveOldLogs)以及与ROIImagesLocation、RawImagesRetention的边界关系,即可在实战中精准控制设备的行为。
【免费下载链接】AI-on-the-edge-deviceEasy to use device for connecting "old" measuring units (water, power, gas, ...) to the digital world项目地址: https://gitcode.com/GitHub_Trending/ai/AI-on-the-edge-device
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考