共计 2292 个字符,预计需要花费 6 分钟才能阅读完成。
技术背景
词袋模型(Bag of Words, BoW)最初是在自然语言处理(NLP)中提出的,用于文本分类。在计算机视觉(CV)领域,BoW 模型被借鉴过来,用于图像分类。两者的核心思想都是忽略元素的顺序,只关注元素的出现频率。

- NLP vs CV 中的 BoW:
- 在 NLP 中,” 词 ” 就是单词,通过统计文档中单词的出现频率来表示文档。
-
在 CV 中,” 词 ” 是图像中的局部特征(如 SIFT、SURF 等),通过统计这些特征的出现频率来表示图像。
-
与传统手工特征的对比 :
- 传统手工特征(如 HOG)通常是对整个图像进行特征提取,而 BoW 模型则是先提取局部特征,再通过聚类构建视觉词典,最后统计特征在词典中的分布。
- BoW 模型能够更好地捕捉图像的局部信息,适用于复杂场景的分类任务。
核心实现
使用 OpenCV 提取 SIFT 特征
以下是使用 OpenCV 提取 SIFT 特征的代码示例:
import cv2
# 初始化 SIFT 检测器
sift = cv2.SIFT_create()
# 读取图像
gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# 检测关键点和计算描述符
keypoints, descriptors = sift.detectAndCompute(gray, None)
print(f"Number of keypoints: {len(keypoints)}")
print(f"Descriptor shape: {descriptors.shape}")
K-means 聚类构建视觉词典
K-means 聚类是将所有图像的 SIFT 特征聚类成 K 个视觉单词的过程。数学上,K-means 的目标是最小化以下损失函数:
$$
J = \sum_{i=1}^{K} \sum_{\mathbf{x} \in C_i} | \mathbf{x} – \mathbf{\mu}_i |^2
$$
其中,$C_i$ 是第 $i$ 个簇,$\mathbf{\mu}_i$ 是第 $i$ 个簇的中心。
特征向量归一化
特征向量归一化是为了消除图像大小对特征统计的影响。常用的归一化方法包括 L1 归一化和 L2 归一化:
- L1 归一化:$\mathbf{v} = \frac{\mathbf{v}}{|\mathbf{v}|_1}$
- L2 归一化:$\mathbf{v} = \frac{\mathbf{v}}{|\mathbf{v}|_2}$
实战演示
完整分类 pipeline
以下是基于 scikit-learn 的完整分类 pipeline 代码:
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
# 假设已经提取了所有图像的 SIFT 特征,存储在 descriptors 列表中
# descriptors = [desc1, desc2, ..., descN]
# 将所有描述符拼接成一个大的矩阵
all_descriptors = np.vstack(descriptors)
# 使用 K -means 构建视觉词典
kmeans = KMeans(n_clusters=100, random_state=42)
kmeans.fit(all_descriptors)
# 构建每张图像的 BoW 特征
bow_features = []
for desc in descriptors:
# 预测每个描述符所属的视觉单词
labels = kmeans.predict(desc)
# 统计视觉单词的出现频率
hist, _ = np.histogram(labels, bins=100, range=(0, 99))
bow_features.append(hist)
# 构建分类 pipeline
pipeline = Pipeline([('scaler', StandardScaler()),
('svm', SVC(kernel='linear'))
])
# 训练分类器
pipeline.fit(bow_features, labels)
生产考量
词典大小对准确率 / 速度的影响
词典大小(即 K -means 的簇数)是一个重要的超参数:
- 词典太小:视觉单词太少,无法捕捉图像的细节信息,准确率低。
- 词典太大:计算开销大,且容易过拟合。
建议通过交叉验证选择合适的词典大小,通常在 100-1000 之间。
内存占用优化
当特征维度很高时,可以使用 PCA 降维来减少内存占用:
from sklearn.decomposition import PCA
pca = PCA(n_components=50)
descriptors_reduced = pca.fit_transform(all_descriptors)
处理尺度 / 旋转变化
SIFT 特征本身对尺度和旋转具有一定的不变性,但在极端情况下,可以考虑使用其他特征(如 ORB)或数据增强技术。
避坑指南
特征维度灾难
当词典大小过大时,容易导致特征维度灾难。解决方法包括:
- 使用 PCA 降维
- 增加训练数据
- 使用正则化技术
聚类中心初始化陷阱
K-means 对初始聚类中心敏感,可以通过多次随机初始化或使用 K -means++ 算法来改善。
跨领域迁移时的词典污染
在不同领域的数据集上使用相同的视觉词典可能导致性能下降。建议在不同领域上分别训练视觉词典。
总结
本文详细介绍了 BoW 模型在计算机视觉中的应用,从原理到实战,涵盖了特征提取、词典构建、分类器训练等关键步骤。通过合理的参数选择和优化,BoW 模型能够在图像分类任务中取得不错的效果。希望这篇文章能帮助初学者快速入门 BoW 模型,并在实际项目中应用。
