网上找的数据集,利用svm训练图片的HOG特征分类器,实现检测。
#python项目,使用opencv中的cv2.ml.svm
import cv2
import numpy as np
import os
def load_train(): #首先提取每个样本的hog特征,和标签
train_data=[]
label=[]
test_data=[]
file_positive='E:\\pedestrian_detect\\\Positive'
file_negative='E:\\pedestrian_detect\\Negative'
file_test='E:\\pedestrian_detect\\TestData'
fp=os.listdir(file_positive)
fn=os.listdir(file_negative)
ft=os.listdir(file_test)
for po in fp:
path1=os.path.join(file_positive,po)
print(path1)
img=cv2.imread(path1)
img=cv2.resize(img,(64,128))
hog=cv2.HOGDescriptor((64,128),(16,16),(8,8),(8,8),9)
descriptor1=hog.compute(img)
#print(descriptor1.shape) #(3780, 1),需要对数据进行降维,否则后面的SVM的特征向量为3维的了
descriptor1=np.concatenate((descriptor1),axis=0) #降维
train_data.append(descriptor1)
label.append(1)
for ne in fn:
path2=os.path.join(file_negative,ne)
print(path2)
img=cv2.imread(path2)
img=cv2.resize(img,(64,128))
descriptor2=hog.compute(img)
descriptor2=np.concatenate((descriptor2),axis=0) #降维
train_data.append(descriptor2)
label.append(-1)
## for te in ft:
## path3=os.path.join(file_test,te)
## img=cv2.imread(path3)
## img=cv2.resize(img,(64,128))
## descriptor3=hog.compute(img)
## descriptor3=np.concatenate((descriptor3),axis=0) #降维
## test_data.append(descriptor3)
label=np.int32(label) #类型转换
train_data=np.float32(train_data)
## test_data=np.float32(test_data)
## return train_data,label,test_data
return train_data,label
###使用sklearn.svm训练
##def train_svm_sklearn(sample,label,test):
## model=svm.SVC()
## #print(label.shape)
## #print(sample.shape)
## model.fit(X=sample,y=label)
## #result=model.predict(test)
## #print(result)
## print(model)
## vectors=model.support_vectors_ #返回支持向量
## vectors=vectors[0,:]
## print(vectors.shape)
## return vectors
#使用opencv库中的SVM训练
def train_svm_opencv(sample,label):
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) #使用线性分类器,因为后面的HogDescirptor检测函数只支持线性
svm.setNu(0.5)
svm.setP(0.1) # for EPSILON_SVR, epsilon in loss function?
svm.setC(0.01) # From paper, soft classifier
svm.setType(cv2.ml.SVM_EPS_SVR)
#对SVM进行训练
svm.train(sample,cv2.ml.ROW_SAMPLE,label)
pwd = os.getcwd()
model_path = os.path.join(pwd, 'svm.xml')
svm.save(model_path)
#SVM训练完成后得到的XML文件里面,有一个数组,叫做support vector,还有一个数组,叫做alpha,有一个浮点数,叫做rho;
#将alpha矩阵同support vector相乘,注意,alpha*supportVector,将得到一个行向量,将该向量前面乘以-1
#即alpha*sv*another-rho ,对于HOG,式子中another=-1
#合并
sv = svm.getSupportVectors() #得到模型的支持向量
print(sv.shape) #(1, 3780)
rho, _, _ = svm.getDecisionFunction(0) #得到决策函数参数,为一个float型数据
sv = np.transpose(sv) #默认为转置,(3780,1)
return np.append(sv, [[-rho]], 0) #axis=0
#rho加负号:由于svm.predict中,公式为:alpha*sv*another-rho ,another=-1
def Rectangle(detector):
file_test='E:\\pedestrian_detect\\TestData'
ft=os.listdir(file_test)
hog=cv2.HOGDescriptor()
#hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
hog.setSVMDetector(detector) #设置线性分类器系数
for i in ft:
file_test_img=os.path.join(file_test,i)
img=cv2.imread(file_test_img)
rects,_=hog.detectMultiScale(img,winStride=(4,4),padding=(8,8),scale=1.05)
for (x,y,w,h) in rects:
cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)
cv2.imshow('result',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
train,label=load_train()
detector=train_svm_opencv(train,label)
Rectangle(detector)