1. 实验概述与目标
这个计算机视觉实验项目围绕图像分类任务展开,通过对比传统机器学习方法和深度学习方法在CIFAR-10数据集上的表现,让学生深入理解不同算法的特点和适用场景。实验包含四个主要部分:
- 基于SVM的分类系统:使用HOG特征+PCA降维+SVM分类器的传统机器学习流程
- 基于CNN的分类系统:构建卷积神经网络实现端到端的图像分类
- 红叶数据集构建与测试:采集真实场景的红叶图像,测试模型的迁移能力
- 视频处理与分类:对RoboCup比赛视频进行预处理和分类
实验的核心价值在于:
- 对比传统特征工程与深度学习特征提取的差异
- 实践从数据准备到模型评估的完整机器学习流程
- 理解模型在不同数据集上的泛化能力
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 实验环境配置
2.1 基础环境搭建
实验采用Python 3.8+作为开发环境,主要依赖以下库:
bash复制pip install numpy opencv-python scikit-learn tensorflow pillow scikit-image
关键库的版本要求:
- TensorFlow ≥ 2.0 (用于CNN模型构建)
- scikit-learn ≥ 1.0 (用于SVM和特征处理)
- OpenCV ≥ 4.5 (用于图像处理)
注意:不同版本的库可能在API上有细微差异,建议使用虚拟环境管理依赖
2.2 数据集准备
实验涉及多个数据集,需要按以下结构组织:
code复制./datasets/
├── cifar-10/ # 自动下载
├── custom_images/ # 自定义训练集
│ ├── cat1.jpg
│ ├── other1.jpg
│ └── ...
├── test_images/ # 测试集
└── 2332-1红叶数据集/ # 红叶数据集
对于视频处理任务,需要额外安装FFmpeg:
bash复制# Ubuntu
sudo apt install ffmpeg
# MacOS
brew install ffmpeg
3. 基于SVM的图像分类实现
3.1 HOG特征提取原理
方向梯度直方图(HOG)是一种常用的图像特征描述方法,其核心思想是:
- 将图像划分为小的连通区域(细胞)
- 计算每个细胞内的梯度方向直方图
- 对这些直方图进行对比度归一化
实验中使用的HOG参数配置:
- 图像尺寸:32×32像素
- 方向数(orientations):9
- 细胞尺寸(cell_size):8×8像素
- 块尺寸(block_size):2×2细胞
python复制from skimage.feature import hog
def extract_hog_features(image):
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
features = hog(gray, orientations=9, pixels_per_cell=(8,8),
cells_per_block=(2,2), transform_sqrt=True)
return features
3.2 PCA降维实现
主成分分析(PCA)用于降低HOG特征的维度,保留95%的方差:
python复制from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
pca = PCA(n_components=0.95)
# 在训练集上拟合
train_features_scaled = scaler.fit_transform(train_hog_features)
pca.fit(train_features_scaled)
# 转换新数据
test_features_reduced = pca.transform(scaler.transform(test_hog_features))
3.3 SVM分类器训练
使用线性SVM分类器,关键参数:
- 正则化参数C=0.1
- 最大迭代次数max_iter=20000
python复制from sklearn.svm import LinearSVC
svm = LinearSVC(C=0.1, max_iter=20000, random_state=42)
svm.fit(train_features, train_labels)
实际技巧:对于小样本数据集,适当减小C值可以防止过拟合
4. 基于CNN的图像分类实现
4.1 CNN模型架构设计
实验采用的CNN结构包含3个卷积块,每个块包含:
- Conv2D层:3×3卷积核,使用ReLU激活
- BatchNormalization:加速训练并提高稳定性
- MaxPooling2D:2×2池化
- Dropout:随机失活防止过拟合
python复制from tensorflow.keras import layers, models
def build_cnn():
model = models.Sequential([
layers.Conv2D(32, (3,3), activation='relu', padding='same',
input_shape=(32,32,3)),
layers.BatchNormalization(),
layers.Conv2D(32, (3,3), activation='relu', padding='same'),
layers.BatchNormalization(),
layers.MaxPooling2D((2,2)),
layers.Dropout(0.25),
# 第二个卷积块
layers.Conv2D(64, (3,3), activation='relu', padding='same'),
layers.BatchNormalization(),
layers.Conv2D(64, (3,3), activation='relu', padding='same'),
layers.BatchNormalization(),
layers.MaxPooling2D((2,2)),
layers.Dropout(0.25),
# 全连接层
layers.Flatten(),
layers.Dense(512, activation='relu'),
layers.Dropout(0.5),
layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
4.2 模型训练技巧
- 数据增强:通过随机翻转、旋转增加数据多样性
python复制from tensorflow.keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=15,
horizontal_flip=True,
width_shift_range=0.1,
height_shift_range=0.1
)
- 学习率调度:训练过程中动态调整学习率
python复制def lr_scheduler(epoch, lr):
if epoch < 5:
return lr
else:
return lr * tf.math.exp(-0.1)
- 早停机制:防止过拟合
python复制early_stopping = tf.keras.callbacks.EarlyStopping(
monitor='val_loss', patience=5, restore_best_weights=True)
5. 红叶数据集构建与分析
5.1 数据采集规范
为确保数据集质量,制定以下采集标准:
- 每人采集20张不同红叶图像
- 包含多种光照条件(顺光、逆光、侧光)
- 不同拍摄角度(正面、侧面、俯视)
- 叶片状态多样(完整、破损、卷曲)
5.2 预处理流程
- 尺寸归一化:统一调整为32×32像素
- 颜色空间转换:确保RGB格式
- 直方图均衡化:增强对比度
- 数据增强:生成更多训练样本
python复制def preprocess_leaf(image_path):
img = Image.open(image_path)
img = img.resize((32,32))
img = img.convert('RGB')
img_array = np.array(img)
# CLAHE对比度增强
lab = cv2.cvtColor(img_array, cv2.COLOR_RGB2LAB)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
l = clahe.apply(l)
lab = cv2.merge((l,a,b))
img_array = cv2.cvtColor(lab, cv2.COLOR_LAB2RGB)
return img_array
6. 视频处理与分类
6.1 视频预处理技术
- 下采样:将视频分辨率降低到原始尺寸的25%
python复制frame = cv2.resize(frame, None, fx=0.25, fy=0.25)
- 关键区域裁剪:手动选择ROI区域
python复制roi = cv2.selectROI("Select Area", frame)
cropped = frame[roi[1]:roi[1]+roi[3], roi[0]:roi[0]+roi[2]]
- 背景减除:使用MOG2算法分离前景
python复制fgbg = cv2.createBackgroundSubtractorMOG2()
fgmask = fgbg.apply(frame)
6.2 实时分类实现
构建视频分类流水线:
- 读取视频帧
- 预处理(下采样+裁剪)
- 特征提取(HOG或CNN)
- 模型预测
- 结果显示
python复制cap = cv2.VideoCapture('RoboCup2024.mp4')
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 预处理
processed = preprocess_frame(frame)
# 特征提取
if method == 'svm':
features = extract_hog_features(processed)
features = pca.transform(scaler.transform([features]))
pred = svm.predict(features)[0]
else:
features = cnn.predict(np.expand_dims(processed, 0))
pred = np.argmax(features)
# 显示结果
cv2.putText(frame, f"Class: {classes[pred]}", (10,30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)
cv2.imshow('Result', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
7. 实验结果对比与分析
7.1 准确率对比
| 方法 | CIFAR-10准确率 | 自定义数据准确率 | 红叶数据集准确率 |
|---|---|---|---|
| SVM+HOG | 50.2% | 85.7% | 62.3% |
| CNN | 82.5% | 92.1% | 78.6% |
7.2 性能对比
| 指标 | SVM+HOG | CNN |
|---|---|---|
| 训练时间 | 30秒 | 5分钟 |
| 预测速度 | 120帧/秒 | 45帧/秒 |
| 内存占用 | 150MB | 1.2GB |
7.3 关键发现
- 特征表达能力:CNN在复杂纹理和语义理解上优势明显
- 计算效率:SVM在小数据场景下训练和预测速度更快
- 数据依赖性:CNN需要更多数据才能发挥优势
- 迁移学习:预训练CNN特征在红叶数据集上表现更好
8. 常见问题与解决方案
8.1 模型训练问题
问题1:SVM训练不收敛
- 原因:学习率或正则化参数不合适
- 解决:调整C值(通常尝试0.01-1范围),增加max_iter
问题2:CNN过拟合
- 解决策略:
- 增加Dropout比例
- 使用更多数据增强
- 添加L2正则化
- 使用早停机制
8.2 特征提取问题
问题:HOG特征维度不一致
- 检查点:
- 确保所有图像尺寸相同
- 验证HOG参数一致性
- 检查灰度转换是否正确
8.3 实践建议
- 数据质量优先:清洗和标注比模型选择更重要
- 从小开始:先用小模型验证思路,再逐步复杂化
- 可视化检查:定期查看中间结果(特征图、预测样本)
- 版本控制:记录每次实验的参数和结果
9. 扩展与改进方向
9.1 算法层面
- 尝试更先进的CNN架构(ResNet, EfficientNet)
- 使用自监督预训练提升特征质量
- 集成多个模型提升鲁棒性
9.2 工程优化
- 使用ONNX加速模型推理
- 实现TensorRT优化部署
- 开发Web界面方便交互测试
9.3 应用扩展
- 结合目标检测实现区域分类
- 添加时序信息处理视频序列
- 部署到移动端实现实时应用
在实际操作中发现,图像分类任务的成功往往取决于对细节的关注。例如,在预处理阶段花费时间确保数据一致性,通常比后续调参带来的提升更显著。另一个重要体会是,没有"最好"的算法,只有最适合特定场景和约束的解决方案。
