1、通过捕捉手在空中的运动手势,通过卷积进行图像特征提取和PCA特征降维最后通过SVM进行分类。具体代码如下,通过
sklearn、numpy等相关库实现。
#!usr/bin/python3
# -*- coding:utf-8 -*-
# author:SingWeek
import cv2
import numpy as np
import os
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.decomposition import PCA
from sklearn.svm import SVC
from sklearn.externals import joblib
class SVM(object):
def __init__(self,svmfile="svm.model",pcafile="pca.model"):
"""
初始化参数
:param svmfile: SVM模型保存的名称"svm.model"
:param pcafile: PCA模型保存的名称,"pca.model"
"""
self.svmfile=svmfile
self.pcafile=pcafile
def Load_Svm(self):
self.clf=joblib.load(self.svmfile)#加载模型
def Load_Pca(self):
self.pca=joblib.load(self.pcafile)#加载模型
def Train_Pca(self,X_Train,n_components = 100):
"""
PCA 模型训练
:param X_Train:训练数据
:param n_components: 特征数,PCA算法中所要保留的主成分个数n,也即保留下来的特征个数n
:return: None
"""
self.pca = PCA(svd_solver='auto', n_components=n_components, whiten=True).fit(X_Train) # 训练一个pca模型
joblib.dump(self.pca, self.pcafile) # 保存模型
def Train(self,X_train, Y_train):
"""
SVM模型训练
:param X_train:训练数据
:param Y_train: 训练标签
:return: None
"""
X_train=self.Pca_X(X_train)#数据转换
param_grid = {'C': [1e3, 5e3, 1e4, 5e4, 1e5], # C是对错误的惩罚
'gamma': [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.1], } # gamma核函数里多少个特征点会被使用}#对参数尝试不同的值
self.clf = GridSearchCV(SVC(kernel='rbf'), param_grid)
self.clf.fit(X_train, Y_train)
joblib.dump(self.clf, self.svmfile) # 保存模型
def Split_Data(self,X,Y,test_ratio=0.3):
"""
训练数据切分
:param X:数据
:param Y:数据标签
:param test_ratio:测试集占比
:return:X_train, X_test, Y_train, Y_test:训练数据,测试数据,训练数据标签,测试数据标签
"""
X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=test_ratio) # 选取test_ratio的测试集
return X_train, X_test, Y_train, Y_test
def Print_Score(self,X_Test,Y_Test):
"""
模型评分
:param X_Test: 测试数据
:param Y_Test: 测试数据标签
:return: 矩阵评分
"""
target_names = ['0', '1', '2', '3', '4', '5', '6']
n_classes = 7
X_Test=self.Pca_X(X_Test)
Y_pred=self.clf.predict(X_Test)
print(classification_report(Y_Test, Y_pred, target_names=target_names))#测试报告
matrix=confusion_matrix(Y_Test, Y_pred, labels=range(n_classes))
print(matrix)#矩阵评分
return matrix
def Pca_X(self,X_Test):
"""
PCA 降维处理
:param X_Test: 输入降维的数据
:return: 降维处理后的数据
"""
return self.pca.transform(X_Test)
def Conv_Pooling(self,frame):
"""
图像特征提取
:param frame:卷积池化的图像
:return:卷积池化后的图像20*20
"""
# fil = np.array([[1, 1, 1], [1, -2, 1], [-1, -1, -1]])
fil1 = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
# fil2 = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
fil3 = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
frame = cv2.filter2D(frame, -1, fil1) # 卷积,高通滤波
frame = cv2.resize(frame, (140, 140)) # 相当于池化
frame = cv2.resize(frame, (80, 80)) # 相当于池化
frame = cv2.filter2D(frame, -1, fil3) # 卷积,边缘特征提取
frame = cv2.resize(frame, (40, 40))
frame = cv2.resize(frame, (20, 20))
return frame
def Prect(self,img):
"""
对图像进行分类预测
:param img: 输入待分类的图像
:return:识别结果,0,1,2,3,4,5,6
"""
X_Test=self.Conv_Pooling(img).reshape(400)
X_Test=np.array([X_Test],dtype='float32')
X_Test=self.Pca_X(X_Test)
return self.clf.predict(X_Test)[0]
def Load_Data(self,file):
"""
从文件夹中读取图像,并进行特征提取转换
:param file:训练数据总的文件名
:return: 转换后的一维图像特征
"""
listsx = []
listsy = []
for i in os.listdir(file):#目录分层,类别
classfile = file + i + '/'
for j in os.listdir(classfile):#定位到具体一个数据读取
filename = classfile + j
img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
Conv_out = self.Conv_Pooling(img)#卷积特征提取,缩放降维
Conv_out = Conv_out.reshape(400)#二维转一维
listsx.append(Conv_out)
listsy.append(int(i))
listsx = np.array(listsx, dtype='float32')
return listsx, listsy
2、在通过3/7划分训练集和测试集,相关打印参数如下:
3、自己收集数据集手势数据集包含0,1,2,3,4,5,6数量分别为468,954,281,282,346,448,885 第6类是负样本:https://download.youkuaiyun.com/download/zx520113/12116992
4、参考:https://www.cnblogs.com/albert-yzp/p/9525162.html
5、总结:在实际应用中,手在空中运动的速度不同,后造成重影,会影响1与2,2与3,3与4之间的识别,0比划快了也会影响和1的识别,更多的将在后续中完善改进,增加数据集,把控好不同类别之间的特征关系。
6、简单的测试训练代码,需要根据自己的文件路径去修改。
# !usr/bin/python3
# -*- coding:utf-8 -*-
# author:SingWeek
from package import *
svm=SVM()#模型定义
x,y=svm.Load_Data("./TrainData/")#数据加载
x_train,x_test,y_train,y_test=svm.Split_Data(x,y,0.3)#数据切分
svm.Train_Pca(x)#训练
svm.Train(x_train,y_train)#训练
# svm.Load_Svm()
# svm.Load_Pca()
svm.Print_Score(x_test,y_test)#评分
#预测
img=cv2.imread("E:\\Write\\2\\879.jpg",cv2.IMREAD_GRAYSCALE)
img=svm.Conv_Pooling(img)
result=svm.Prect(img)
print(result)