用Python给人民币“验明正身”:一个基于颜色矩的SVM纸币面额识别Demo(附完整代码)
用Python给人民币“验明正身”:一个基于颜色矩的SVM纸币面额识别Demo
在超市收银台前,我们总能看到收银员快速清点钞票的场景。你有没有想过,如果让计算机来识别纸币面额会怎样?今天我们就用Python打造一个能自动识别人民币面额的"验钞小助手"。这个项目不仅有趣,还能带你入门计算机视觉的基础知识。
纸币识别看似简单,实则包含图像处理、特征提取和机器学习三个关键环节。我们不会追求工业级的超高准确率,而是聚焦如何用Python基础工具链(PIL+NumPy+sklearn)实现端到端的解决方案。通过计算RGB颜色矩特征,配合SVM分类器,240张纸币图片就能训练出不错的识别模型。
1. 项目准备与环境搭建
开始前需要准备以下工具和材料:
- Python 3.7+环境
- 安装必要的库:
pip install pillow numpy scikit-learn - 收集240张人民币图片(1元、5元、10元、20元、50元、100元各40张)
- 图片命名规范:
面额_序号.png(如5_12.png)
提示:实际项目中建议使用统一拍摄环境下的纸币照片,避免光照条件差异影响识别效果
核心工具库的作用:
from PIL import Image # 图像读取和处理 import numpy as np # 数值计算和特征提取 from sklearn import svm # 机器学习模型2. 数据预处理与特征工程
2.1 图像读取与标准化
首先需要批量读取图片并统一尺寸。人民币各面额尺寸相同(约150×70mm),但拍摄时可能存在角度差异:
def load_images(folder): images = [] for filename in os.listdir(folder): img = Image.open(os.path.join(folder, filename)) img = img.resize((150, 70)) # 统一尺寸 images.append(img) return images2.2 颜色矩特征计算
颜色矩是描述图像颜色分布的统计特征,包括:
- 一阶矩(均值):反映颜色整体亮度
- 二阶矩(标准差):表示颜色分布范围
- 三阶矩(偏度):体现颜色分布不对称性
计算RGB三通道的9个特征值:
def extract_features(img): # 分离RGB通道 r, g, b = img.split() channels = [np.array(ch)/255.0 for ch in [r,g,b]] features = [] for ch in channels: # 一阶矩(均值) mean = np.mean(ch) # 二阶矩(标准差) std = np.std(ch) # 三阶矩(偏度) skew = np.mean((ch - mean)**3)**(1/3) features.extend([mean, std, skew]) return features3. 构建SVM分类模型
3.1 数据集准备
将240张图片转换为特征矩阵和标签向量:
X = [] # 特征矩阵 y = [] # 标签向量 for i, img in enumerate(images): features = extract_features(img) X.append(features) # 从文件名提取面额标签 denomination = int(filenames[i].split('_')[0]) y.append(denomination) X = np.array(X) y = np.array(y)3.2 模型训练与评估
使用支持向量机(SVM)进行分类,按8:2划分训练集和测试集:
from sklearn.model_selection import train_test_split from sklearn.svm import SVC # 划分数据集 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42) # 创建SVM分类器 model = SVC(kernel='rbf', C=10, gamma=0.1) # 训练模型 model.fit(X_train, y_train) # 评估性能 train_acc = model.score(X_train, y_train) test_acc = model.score(X_test, y_test) print(f"训练集准确率: {train_acc:.2%}") print(f"测试集准确率: {test_acc:.2%}")典型输出结果:
训练集准确率: 92.71% 测试集准确率: 89.58%4. 模型优化与改进方向
4.1 特征工程优化
原始颜色矩特征的改进空间:
| 改进方向 | 具体方法 | 预期效果 |
|---|---|---|
| 增加纹理特征 | 提取LBP、HOG等特征 | 提升新旧纸币识别率 |
| 多区域采样 | 分区域计算特征 | 降低局部污损影响 |
| 颜色空间转换 | 使用HSV/Lab色彩空间 | 增强光照鲁棒性 |
4.2 模型调参技巧
SVM关键参数优化策略:
from sklearn.model_selection import GridSearchCV param_grid = { 'C': [0.1, 1, 10, 100], 'gamma': [1, 0.1, 0.01, 0.001], 'kernel': ['rbf', 'linear'] } grid = GridSearchCV(SVC(), param_grid, cv=5) grid.fit(X_train, y_train) print("最佳参数:", grid.best_params_)4.3 部署为实用工具
将训练好的模型封装成可交互的识别工具:
def predict_denomination(image_path): img = Image.open(image_path).resize((150, 70)) features = extract_features(img) denomination = model.predict([features])[0] return f"识别结果: {denomination}元"在实际测试中发现,新版人民币的识别准确率明显高于旧版,主要因为旧币颜色褪变导致特征变化。这提示我们在数据收集中要注意样本多样性。
