基于OpenCV的行人检测 实战:基于openCV的行人检测(二)

任务描述
在前面的任务中我们介绍了使用OpenCV进行样本数据处理,以及HOG特征的提取,在本次任务中,我们将会基于OpenCV,使用提取的HOG特征来训练SVM分类器。

相关知识
为了完成本关任务,你需要了解:

Hard example的简单了解;
基于OpenCV,创建并训练SVM分类器。
Hard example的简单了解
Hard example是指利用第一次训练的分类器在负样本图片上(一定没有人体)进行行人检测时,所得到的检测矩形框,这些矩形框区域很明显都是误报,把这些误报的矩形框保存为图片,加入到初始的负样本集合中,重新进行SVM的训练,就可在一定程度上提升检测效果,这种方法又称为自举法(Bootstrap)。这种方法首先会使用原始负样本数据集合去训练得到一个模型,然后收集被这个模型错误分类的负样本,从而形成一个负样本难例集,再将其进行二次训练,用于新的模型,该过程可重复进行。换句话来说,hard example的意义就在于告诉训练的模型,“这个题目你之前做错过了,你再多做几遍,之后再碰到才能不出错”。


上图将树干误认为是人体,这些就是Hard example,将这些矩形框保存为64 * 128的图片文件,加入到负样本集合中。

基于OpenCV,使用HOG特征来训练SVM分类器
在第六个任务中,我们对SVM分类器有了一个简单了解,在本次任务中我们不再讨论这一部分内容,我们使用OpenCV中已经封装好的SVM相关内容。这里我们可以使用OpenCV中已经训练好的行人检测分类器,需要注意的是OpenCV自带的分类器是利用HOG论文作者Navneet Dalal和Bill Triggs提供的样本进行训练的,得到的模型不一定能够适用于你的应用场合,因此针对你的特定应用场景,很有必要进行重新训练得到适合的分类器,也就是创建并使用自己的数据训练一个SVM分类器。
检测有两种方式,如果仅仅使用线性核的话,只需要Hog类自带的setSVMDetector和detect(detectMultiScale),如果使用RBF,就需要使用SVM类的predict。但predict是判断“是与不是”的,如果要得区域的话,使用Hog类的setSVMDetector和detect(detectMultiScale),这里我们使用线性核。
线性SVM进行训练之后得到的文本文件里面,有一个数组,叫做support vector,还有一个数组,叫做alpha,有一个浮点数,叫做rho;将alpha矩阵同support vector相乘,注意,alpha * supportVector,将得到一个列向量。之后,再该列向量的最后添加一个元素rho。如此,变得到了一个分类器,利用该分类器,直接替换OpenCV中行人检测默认的那个分类器(HOGDescriptor::setSVMDetector()),就可以利用你的训练样本训练出来的分类器进行行人检测了。

import cv2
import numpy as np
#法一:使用OpenCV自带的已经训练好的SVM分类器
hog = cv2.HOGDecriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
#法二:创建一个SVM分类器
svm = cv2.ml.SVM_create()
###下面的为SVM参数的设置,之前没有进行设置,得到的支持向量sv维度较高,导致合并部分维度不匹配,报错
svm.setCoef0(0.0)
svm.setDegree(3)
criteria = (cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS, 1000, 1e-3)
svm.setTermCriteria(criteria)
svm.setGamma(0)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setNu(0.5)
svm.setP(0.1)
svm.setC(0.01)
svm.setType(cv2.ml.SVM_EPS_SVR)
###对SVM进行训练
svm.train(np.array(hosList), cv2.ml.ROW_SAMPLE, np.array(labels))
#获取所有的支持向量
sv = svm.getSupportVectors()
rho, _, _ = svm.getDecisionFunction(0)
sv = np.transpose(sv)
hog1 = cv2.HOGDescriptor()
###设置线性分类器参数
hog1.setSVMDetector(np.append(sv, [[-rho]], 0))
编程要求
本次任务主要实现Hard example数据提取,以及基于OpenCV训练SVM分类器。

根据提示,在右侧编辑器补充代码,针对给定的注释提示进行对应操作。具体要求如下:

获取Hard example,即使用数据集训练SVM分类器,并将其用于负样本的检测得到的矩形框保存为64 * 128大小的图像加入到训练数据中,用于二次训练;
使用OpenCV的ml.SVM_create函数创建SVM分类器,并使用数据对其进行训练;
使用自己训练的分类器替换OpenCV的HOGDescriptor()类中的默认行人检测分类器。

预期输出 ———

posImageList: 8

posList 8

hosList 8

negImageList: 5

negList 50

hosList 58

labels 58

hardNegList: 0

hosList 58

labels 58

 

import cv2
import numpy as np

#获取检测子
def getHOGDetector(svm):
    ######## Begin1 ########
        
    # 获取所有的支持向量
    sv = svm.getSupportVectors()
        
    ######## End1 ########
    rho, _, _ = svm.getDecisionFunction(0)
    sv = np.transpose(sv)
    return np.append(sv, [[-rho]], 0)

#获取Hard example
def getHardExamples(negImageList, svm):
    hardNegList = []
    ######## Begin2 ########
        
    # 声明HOG类,并使用参数svm代替默认检测器
    hog = cv2.HOGDescriptor()
    hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
        
    for i in range(len(negImageList)):
        rects, wei = hog.detectMultiScale(negImageList[i], winStride=(4, 4),padding=(8, 8), scale=1.05)
        for (x,y,w,h) in rects:
            hardExample = negImageList[i][y:y+h, x:x+w]
            
            # 将获取的矩形框使用resize函数将其保存为64 * 128大小的图片,并将其就如hardNegList中
            hardExample = cv2.resize(negImageList[i][y:y+h, x:x+w], (64, 128))
            hardNegList.append(hardExample)
            
    ######## End2 ########
    return hardNegList

#获取自己训练的SVM分类器
def getSVMClassifier(hosList, labels):
    ######## Begin3 ########
        
    # 声明一个空的SVM分类器
    svm = cv2.ml.SVM_create()
    
    svm.setCoef0(0.0)
    svm.setDegree(3)
    criteria = (cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS, 1000, 1e-3)
    svm.setTermCriteria(criteria)
    svm.setGamma(0)
    svm.setKernel(cv2.ml.SVM_LINEAR)
    svm.setNu(0.5)
    svm.setP(0.1)
    svm.setC(0.01)
    svm.setType(cv2.ml.SVM_EPS_SVR)
    
    # 训练SVM
    svm.train(np.array(hosList), cv2.ml.ROW_SAMPLE, np.array(labels))
    
    ######## End3 ########
    return svm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值