别再数钱了!用Python颜色矩+SVM,教你自动识别6种面额人民币(附240张图数据集处理技巧)
2026/6/3 12:21:34 网站建设 项目流程

用Python颜色矩与SVM打造智能零钱识别系统

每次从口袋里掏出一把零钱时,你是否也厌烦了手动分类的繁琐?作为一名经常需要处理零钱的便利店店主,我曾经花费大量时间在清点现金上,直到发现了计算机视觉的魔力。本文将带你从零开始,构建一个能够自动识别1元到100元人民币的智能系统,整个过程不需要复杂的深度学习框架,仅用Python基础图像处理库和Scikit-learn就能实现。

1. 理解颜色矩:纸币识别的数学基础

颜色矩(Color Moments)是图像处理中一种简单却有效的特征提取方法,特别适合处理颜色分布有明显差异的图像分类任务。对于人民币识别来说,不同面额的纸币在颜色分布上具有显著差异,这正是颜色矩大显身手的地方。

颜色矩包含三个核心指标:

  • 一阶颜色矩(均值):反映图像颜色的平均亮度
  • 二阶颜色矩(标准差):描述颜色分布的离散程度
  • 三阶颜色矩(偏度):表示颜色分布的不对称性

计算这三个指标时,我们需要分别处理图像的R、G、B三个通道,因此每张图像最终会得到9个特征值(3通道×3阶矩)。

import numpy as np from PIL import Image def calculate_color_moments(image_path): img = Image.open(image_path) img = img.resize((100, 100)) # 统一图像尺寸 r, g, b = img.split() # 分离RGB通道 def get_moments(channel): channel = np.array(channel, dtype=np.float32) mean = np.mean(channel) # 一阶矩 std = np.std(channel) # 二阶矩 skewness = np.mean((channel - mean)**3) ** (1/3) # 三阶矩 return [mean, std, skewness] r_moments = get_moments(r) g_moments = get_moments(g) b_moments = get_moments(b) return r_moments + g_moments + b_moments

提示:三阶颜色矩的计算公式有多种变体,这里使用的是最常用的立方根形式,能有效避免数值过大导致的问题。

2. 构建人民币数据集:从原始图像到特征矩阵

原始数据集包含240张人民币图像,涵盖6种面额(1元、5元、10元、20元、50元、100元),每种面额包含正反面及不同角度的照片。这种多样性对于构建鲁棒的分类器至关重要。

2.1 数据预处理流程

  1. 图像读取与尺寸统一化

    • 使用Pillow库读取图像
    • 将所有图像调整为相同尺寸(如100×100像素)
  2. 中心区域裁剪

    • 聚焦于纸币中心区域,减少背景干扰
    • 代码实现:
def crop_center(image, crop_size=80): width, height = image.size left = (width - crop_size)/2 top = (height - crop_size)/2 right = (width + crop_size)/2 bottom = (height + crop_size)/2 return image.crop((left, top, right, bottom))
  1. 特征提取与标签生成
    • 对每张图像计算9维颜色矩特征
    • 从文件名中提取面额作为标签

2.2 数据集划分策略

对于240张的小型数据集,合理的划分方式直接影响模型性能:

划分方式训练集数量测试集数量适用场景
随机划分192 (80%)48 (20%)基础验证
分层抽样保持各类比例保持各类比例类别不均衡时
按角度划分特定角度训练其他角度测试测试模型泛化性
from sklearn.model_selection import train_test_split # 基础随机划分 X_train, X_test, y_train, y_test = train_test_split( features, labels, test_size=0.2, random_state=42) # 分层抽样划分 X_train, X_test, y_train, y_test = train_test_split( features, labels, test_size=0.2, stratify=labels, random_state=42)

3. SVM模型构建与调优实战

支持向量机(SVM)在小样本分类任务中表现出色,特别适合我们的纸币识别场景。下面详细介绍如何构建和优化SVM分类器。

3.1 基础SVM模型搭建

from sklearn.svm import SVC from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline # 创建包含数据标准化和SVM的管道 svm_pipeline = make_pipeline( StandardScaler(), SVC(kernel='rbf', class_weight='balanced') ) # 模型训练 svm_pipeline.fit(X_train, y_train) # 评估性能 train_score = svm_pipeline.score(X_train, y_train) test_score = svm_pipeline.score(X_test, y_test) print(f"训练集准确率: {train_score:.2%}, 测试集准确率: {test_score:.2%}")

3.2 关键参数解析与调优

SVM的核心参数及其对模型的影响:

  • 核函数(kernel)

    • linear:线性核,适合线性可分数据
    • rbf:高斯核,处理非线性问题
    • poly:多项式核,可调节多项式次数
  • C参数

    • 控制误分类的惩罚力度
    • 值越大,模型越复杂,可能过拟合
    • 值越小,模型越简单,可能欠拟合
  • gamma参数(仅对rbf/poly核有效)

    • 控制单个样本的影响范围
    • 值越大,决策边界越复杂

使用网格搜索进行参数优化:

from sklearn.model_selection import GridSearchCV param_grid = { 'svc__C': [0.1, 1, 10, 100], 'svc__gamma': [0.001, 0.01, 0.1, 1], 'svc__kernel': ['rbf', 'poly', 'linear'] } grid_search = GridSearchCV( svm_pipeline, param_grid, cv=5, scoring='accuracy', n_jobs=-1) grid_search.fit(X_train, y_train) print("最佳参数组合:", grid_search.best_params_) print("最佳交叉验证分数:", grid_search.best_score_)

4. 提升模型性能的进阶技巧

当基础模型的准确率不理想时,可以从以下几个方向进行优化:

4.1 特征工程扩展

除了颜色矩,可以引入更多特征类型:

  1. 纹理特征

    • 使用LBP(Local Binary Patterns)捕捉纸币纹理
    • 计算灰度共生矩阵(GLCM)特征
  2. 形状特征

    • 边缘检测后计算轮廓特征
    • 关键点检测与描述
  3. 颜色空间转换

    • 将RGB转换为HSV、Lab等颜色空间
    • 在不同颜色空间中计算特征
from skimage.feature import local_binary_pattern def extract_lbp_features(image_path): img = Image.open(image_path).convert('L') # 转换为灰度图 img = np.array(img) radius = 3 n_points = 8 * radius lbp = local_binary_pattern(img, n_points, radius, method='uniform') hist, _ = np.histogram(lbp, bins=np.arange(0, n_points + 3)) return hist / hist.sum() # 归一化直方图

4.2 数据增强策略

针对小数据集的常见增强方法:

  • 几何变换

    • 小角度旋转(±5度)
    • 轻微平移和缩放
  • 颜色扰动

    • 亮度/对比度微调
    • 添加轻微噪声
from torchvision import transforms transform = transforms.Compose([ transforms.RandomRotation(5), transforms.RandomAffine(0, translate=(0.05, 0.05)), transforms.ColorJitter(brightness=0.1, contrast=0.1), ])

4.3 模型集成与融合

结合多个模型的优势:

  1. 投票集成

    • 训练多个不同核函数的SVM
    • 采用多数投票决定最终分类
  2. 特征堆叠

    • 用不同特征集训练多个模型
    • 将预测概率作为新特征输入元分类器
from sklearn.ensemble import VotingClassifier from sklearn.svm import SVC svm_rbf = SVC(kernel='rbf', probability=True) svm_poly = SVC(kernel='poly', probability=True) svm_linear = SVC(kernel='linear', probability=True) voting_clf = VotingClassifier( estimators=[ ('svm_rbf', svm_rbf), ('svm_poly', svm_poly), ('svm_linear', svm_linear)], voting='soft') voting_clf.fit(X_train, y_train)

在实际项目中,我发现将颜色矩与LBP纹理特征结合,配合RBF核的SVM,能在人民币识别任务上达到约92%的准确率。对于光照变化较大的场景,建议在预处理阶段加入直方图均衡化,这能显著提升模型鲁棒性。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询