每天早上撕开速溶咖啡包装时,我总好奇自己到底摄入了多少咖啡因。市面上的健康应用只能手动记录,而作为计算机视觉工程师,我决定用摄像头自动解决这个问题。这个项目通过识别常见咖啡包装上的营养成分表,实时计算每日咖啡因摄入量。
核心原理并不复杂:用目标检测定位包装盒,OCR提取营养成分数据,再通过规则引擎换算实际摄入量。但实际开发中会遇到各种现实问题——反光包装的识别干扰、千奇百怪的标签排版、不同国家的单位换算等。经过三个版本迭代,最终系统的识别准确率达到了92%,比手动记录更可靠。
系统采用模块化设计,流程如下:
关键设计选择:没有直接识别咖啡品牌logo,而是定位标准化的营养成分表。因为不同地区/批次包装设计差异大,但营养成分表格式相对统一。
数据集构建:
YOLOv5改进:
OCR优化技巧:
bash复制# 基础环境
conda create -n caffeine python=3.8
pip install torch==1.10.0+cu113 -f https://download.pytorch.org/whl/torch_stable.html
# 安装YOLOv5
git clone https://github.com/ultralytics/yolov5
cd yolov5 && pip install -r requirements.txt
# 安装PaddleOCR
pip install paddlepaddle paddleocr
python复制# 数据准备
python yolov5/scripts/convert2yolo.py --dataset caffeine \
--output labels \
--img-size 640
# 训练命令
python yolov5/train.py --img 640 \
--batch 16 \
--epochs 100 \
--data caffeine.yaml \
--weights yolov5s.pt \
--hyp hyp.finetune.yaml
python复制def calculate_intake(detected_text):
# 匹配数字+单位模式
pattern = r"咖啡因.*?(\d+\.?\d*)\s*(mg|毫克|g|克)"
matches = re.findall(pattern, detected_text)
if not matches:
return None
value, unit = matches[0]
value = float(value)
# 单位标准化换算
if unit in ["g", "克"]:
value *= 1000
# 根据包装规格计算实际摄入
package_size = get_package_size() # 从数据库查询
return value * (consumed_amount / package_size)
| 问题现象 | 原因分析 | 解决方案 |
|---|---|---|
| 将"能量"误识别为咖啡因 | 中文OCR字符相似度 | 添加前后文语义校验 |
| 反光导致数字缺失 | 高光区域像素过曝 | 拍摄时自动提示补光 |
| 每份vs每100ml混淆 | 单位基准不统一 | 解析时提取基准量字段 |
这套方案稍作修改即可用于:
实际部署时发现,用户最需要的不是精确数值,而是相对变化趋势。因此最终界面突出了每日/每周的摄入曲线,并设置智能预警:"今日已摄入相当于3杯美式咖啡"。
经验教训:不要过度追求绝对精度。用户拍摄角度不规范、包装变形等因素必然存在,系统应该容忍合理误差,通过多次测量取均值来提高可靠性。