在我之前的文章中写过很多关于人脸识别和表情识别的文章,今天有一个项目的需求就是需要做两种或者是多种任务,我在开发完对应的模型之后就突然想到了之前做过的人脸识别和表情识别的项目,就想着是否可以基于机器学习/深度学习等方式来同时实现人脸识别和表情识别呢?
答案是可以的,基于深度学习的实现可以直接套用我项目上面开发的模型就可以实现了,但是基于机器学习的方式来实现我倒还没有想到特别好的办法,所以本文实现的方法还是先基于HOG和LBP分别完成对应图像特征的抽取存储,之后分别构建训练了人脸识别模型和表情识别两个模型,之后在推理阶段将对应的逻辑集成到一起,出来的效果的确是输入单张图像,能够同时识别出来是谁以及表情是什么?但是终归是两个独立的模型,目前已经有了初步的想法,后面有时间的话继续按照深度学习模型的实现方式来构建机器学习的多任务模型。
先来看下效果:
这里使用的是开源的数据集,如下:
【人脸识别数据集】
【表情识别数据集】
HOG单样本特征提取实现如下:
def singleImg2Vector(pic="16515631261.jpg"):"""单张图像向量化"""img = io.imread(pic)img = color.rgb2gray(img)x = filters.sobel_h(img)y = filters.sobel_v(img)print("img_shape: ", img.shape)hog_descriptor = HOG(img, block_size=3)hog_vector = hog_descriptor.hog_features()print("hog_vector_shape: ", hog_vector.shape)return hog_vector.tolist()
LBP单样本特征提取如下:
def singleImg2Vector(pic="16515631261.jpg"):"""单张图像向量化"""img = io.imread(pic)img = color.rgb2gray(img)print("img_shape: ", img.shape)lbp = LBP(img)features = lbp.extend_lbp(3, 8)vector = lbp.get_lbp_vector(features, 8)print("vector_shape: ", vector.shape)return vector.tolist()
在实际使用过程中发现:LBP特征提取器的时耗很大,而HOG特征提取器的时耗较小,速度差异还是很明显的,HOG和LBP的对应实现可以直接百度开源实现,这里我就不再赘述了,因为这里我只是调用的封装好的模块的方法。
之后会分别完成对应人脸特征和表情特征的提取存储,如下所示:
得到的特征文件之后就可以来构建自己的机器学习模型了。
这里做了很多种经典的机器学习模型,诸如:决策树、XGBOOST、GBDT、随机森林、支持向量机、逻辑回归等等,时间限制,这里就不再一一展开介绍了,这里主要以SVM模型的搭建实践为例来进行简单介绍,其他的模型pipeline是一模一样的,没有什么本质的区别。
X_train, X_test, y_train, y_test = split_data(x_list, y_list, ratio=rationum)
try:model = loadModel(model_path=model_path)
except:model = SVC(kernel="linear",C=10,gamma="auto",degree=5,tol=0.1,decision_function_shape="ovo",)model.fit(X_train, y_train)
y_predict = model.predict(X_test)
y_pred = y_predict.tolist()
accuracy = model.score(X_test, y_test)
print("SVM model accuracy: ", accuracy)
Precision, Recall, F1 = calThree(y_test, y_pred)
saveModel(model, save_path=model_path)
result = {}
result["accuracy"], result["F_value"] = accuracy, F1
result["precision"], result["recall"] = Precision, Recall
这里分别计算了:accuracy、precision、recall和F1值四种专门用于衡量分类任务模型性能好坏的指标,如下:
【人脸识别指标评估结果】
{"lbp": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"hog": {"accuracy": 0.984375,"F_value": 0.9856410256410257,"precision": 0.9857142857142858,"recall": 0.9875}
}
【表情识别指标评估结果】
{"lbp": {"accuracy": 0.8153846153846154,"F_value": 0.8113511202756054,"precision": 0.8309523809523809,"recall": 0.8218923933209649},"hog": {"accuracy": 0.7692307692307693,"F_value": 0.7667969899283477,"precision": 0.766192537621109,"recall": 0.780045351473923}
}
为了更加直观简洁地呈现结果对比分析,这里对其进行了可视化,如下:
从对比直方图可以直观地看出来:在两个分类任务上面,LBP效果都比HOG要好,这也印证了LBP方法的特征表达能力更为强悍一些,不过唯一的缺点就是时耗太高了点。
接下来为了更加细粒度地进行对比拆分,我专门划分计算了每个单独类别下面的四种评估指标,这里主要是对测试集进行归类处理一下即可,我就不再赘述了,直接看最终的结果,我将两种特征提取方法得到的评估结果放在了一起方便进行对比分析,如下:
【表情识别】
{"HOG": {"neutral": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"fear": {"accuracy": 0.5454545454545454,"F_value": 0.2352941176470588,"precision": 0.3333333333333333,"recall": 0.1818181818181818},"happiness": {"accuracy": 0.8181818181818182,"F_value": 0.3,"precision": 0.3333333333333333,"recall": 0.27272727272727279},"anger": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"sadness": {"accuracy": 0.6363636363636364,"F_value": 0.25925925925925927,"precision": 0.3333333333333333,"recall": 0.21212121212121214},"surprise": {"accuracy": 0.8888888888888888,"F_value": 0.47058823529411766,"precision": 0.5,"recall": 0.4444444444444444},"disgust": {"accuracy": 0.5714285714285714,"F_value": 0.24242424242424244,"precision": 0.3333333333333333,"recall": 0.19047619047619047}},"LBP": {"neutral": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"fear": {"accuracy": 0.7272727272727273,"F_value": 0.28070175438596497,"precision": 0.3333333333333333,"recall": 0.24242424242424244},"happiness": {"accuracy": 0.7272727272727273,"F_value": 0.28070175438596497,"precision": 0.3333333333333333,"recall": 0.24242424242424244},"anger": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"sadness": {"accuracy": 0.7272727272727273,"F_value": 0.4210526315789474,"precision": 0.5,"recall": 0.36363636363636367},"surprise": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"disgust": {"accuracy": 0.5714285714285714,"F_value": 0.24242424242424244,"precision": 0.3333333333333333,"recall": 0.19047619047619047}}
}
结果对比直方图如下所示:
【人脸识别】
{"HOG": {"KL": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"TM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"KM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"MK": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"KR": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"YM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"NA": {"accuracy": 0.875,"F_value": 0.4666666666666667,"precision": 0.5,"recall": 0.4375},"KA": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"UY": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"NM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0}},"LBP": {"KL": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"TM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"KM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"MK": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"KR": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"YM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"NA": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"KA": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"UY": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0},"NM": {"accuracy": 1.0,"F_value": 1.0,"precision": 1.0,"recall": 1.0}}
}
结果对比直方图如下:
两种任务对比来看:两种方法在人脸识别任务上的效果都很不错,在表情识别任务上的效果就稍有逊色了;另外LBP的整体表现和细粒度表现都是要优于HOG的,这个对于后续项目的特征提取器的选择来说可以是一种直接的参考。