00.数据学习的开始:HOG
数据学习的开始:HOG + SVM
本篇文章直接来自我学习 OpenCV 的笔记:https://github.com/masterAllen/LearnOpenCV
在 HOG 中,里面提到 SVM+HOG 是一种非常经典的图像分类或识别方法。其实又何止 HOG 呢,任何一个特征提取方法(如SIFT等),都可以和 SVM 结合起来,形成一种分类器。至于 SVM 原理,我想不用多写了,现在估计已经成了那群小孩大一大二就要学习的基础知识了。
介绍 HOG 的文章 中的代码是用 OpenCV 自带的行人检测模型实现检测,那么这里就着重来进行 SVM 训练。图片、代码和学习记录参考了两篇文章,特此感谢(文章一、文章二,整体代码在 test_hog_svm.ipynb 中。
1. 整体出训练集和测试集,这个其实就是每次读一张图片,然后存储 HOG 特征 和 正负标签。
# 以负样本为例,每次读取图片,计算 HOG
for fname in os.listdir(f'{datadir}/neg'):
img = cv2.imread(f'{datadir}/neg/{fname}', -1)
datas.append((hog.compute(img), -1))
2. 使用 SVM 训练
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6))
# 训练 SVM,train_features 就是各个图片的 HOG,train_labels 就是各个图片的标签
svm.train(np.array(train_features), cv2.ml.ROW_SAMPLE, np.array(train_labels))
# 训练完可以检测,看看训练出来的怎么样
predict_labels = svm.predict(np.array(test_features))[1].flatten()
print('Wrong rate:', sum(predict_labels != np.array(test_labels))/len(predict_labels))
3. HOG + SVM 融合
# 新建 HOG 类,将其检测设为训练好的 SVM
hog = cv2.HOGDescriptor()
hog.setSVMDetector(svm.getSupportVectors()[0])
# 从训练集图片中读取一张图片进行检测
img = cv2.imread(f'test.jpg', -1)
(rects, weights) = hog.detectMultiScale(img, winStride=(4, 4), padding=(8, 8), scale=1.05)
x, y, w, h = rects[np.argmax(weights.flatten())]
cv2.rectangle(img, (x, y), (x+w, y+h), (255,0,0), 1)
show_image(img)