人工智慧與機器學習----基於SVM實現微笑識別
SVM演算法應用綜合練習--人臉表情識別
利用所提供的人臉微笑資料集(genki4k),訓練一個微笑/非微笑識別模型,完成對人臉圖片的微笑與非的識別,輸出訓練(train)和測試(test)的精度值(F1-score和ROC);然後儲存這個模型,將其應用到人臉實時採集視訊的微笑檢測中,當檢測到微笑人臉,視訊視窗輸出“smile”,否則輸出“non smile”;當識別結果準確時,按“s”鍵,儲存10張對應分類的圖片到本地目錄。人臉表情特徵的選擇不限,可以是HoG、SIFT、dlib(68個關鍵點), 訓練演算法採用SVM(sklearn或libsvm)。
一、提取圖片特徵
下載genki4k資料集
預覽一下它資料夾中所有圖片如下
檢視他的label檔案得知他的每張圖片標籤以及相關資訊
通過之前學習人臉識別時使用的dlib的68個特徵值的模型,將genki4k中的4000張圖片每一張都進行提取特徵進行儲存。
程式碼如下
from cv2 import cv2 as cv2 import os import dlib from skimage import io import csv import numpy as np from libsvm.svmutil import * #要讀取人臉影象檔案的路徑 path_images_from_camera = "D:\\baidu\\genki4k" # Dlib 正向人臉檢測器 detector = dlib.get_frontal_face_detector() # Dlib 人臉預測器 predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") # Dlib 人臉識別模型 # Face recognition model, the object maps human faces into 128D vectors face_rec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat") # 返回單張影象的 128D 特徵 def return_128d_features(path_img): img_rd = io.imread(path_img) img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB) faces = detector(img_gray, 1) if len(faces)==0: return [0] shape = predictor(img_gray, faces[0]) face_descriptor = face_rec.compute_face_descriptor(img_gray, shape) return face_descriptor # 按順序讀取每一張圖片輸出每一個特徵值將其先進行儲存 for i in range (1,4001): if i<10: a="000"+str(i) elif i<100: a="00"+str(i) elif i<1000: a="0"+str(i) else : a=str(i) path="file"+a+".jpg" folder_path="D:\\baidu\\genki4k\\files\\" file_path=folder_path+path with open('smile_face.csv','a', newline="") as f: f_csv = csv.writer(f) f_csv.writerow(return_128d_features(file_path)) print("完成了第"+str(i)+"張圖片完成")
二、劃分資料集並通過svm進行分類訓練
在genki4k中有label.txt裡面資料是每一張圖片的標籤第一個數字中的1或零就是笑或者不笑,將特徵資料通過這個0和1進行分類
首先手動劃分一個訓練集和測試集,由於這個圖片集前半部分為笑後半為不笑,取出1-50和3950-4000號作為測試集合,其他的作為訓練集.
將測試集手動分隔到另一個txt檔案中。
首先分別讀取資料
# -*- coding: utf-8 -*- """ Created on Mon Nov 29 13:30:13 2021 @author: 13774 """ from libsvm.svmutil import * import pickle #讀取標籤資料 y=open('labels.txt') yy = y.readlines() datay = [] index=[] formatdatax= [] for i in range(1,129): index.append(i) #對資料進行整理 for i in range(0,3900): if(len(datax[i])==1): continue datay.append(int(yy[i][0])) tempx=[] for ii in range (0,len(datax[i])): tempx.append(float(datax[i][ii])) formatdatax.append(dict(zip(index,tempx))) #讀取測試標籤 ty=open('labels.txt') testy=[] tyy = ty.readlines() formattestx=[] #讀取測試面部特徵資料 tx = open("testx.txt") testx = [i[:-1].split(',') for i in tx.readlines()] x=open("smile_face.csv") datax = [i[:-1].split(',') for i in x.readlines()]
進行訓練並將模型儲存
options = '-t 0 -c 0.9 -b 1' # 訓練引數設定
model = svm_train(datay,formatdatax,options) # 進行訓練
svm_save_model('mymodel.txt',model)
三、對訓練完成的模型進行測試
再讀取測試集的資料並且根據剛剛儲存的模型進行測試
from libsvm.svmutil import *
#讀取剛剛儲存的模型
model=svm_load_model("../mymodel.txt")
#讀取一開始分割的測試集的50張笑臉以及50張不笑的特徵
x=open("testx.txt")
#設定好測試集的標籤a
datay=[]
for i in range(0,50):
datay.append(1)
for i in range(0,50):
datay.append(0)
#設定測試集資料
datax = [i[:-1].split(',') for i in x.readlines()]
index=[]
for i in range(1,129):
index.append(i)
formatx=[]
for dx in datax:
for i in range(0,len(dx)):
dx[i]=float(dx[i])
for dx in datax:
formatx.append(dict(zip(index,dx)))
p_label, p_acc, p_val = svm_predict(datay,formatx, model,"-b 1") # 使用得到的模型進行預測
print(p_label)
結果如下,可以發現準確率似乎並不是十分理想
將它分開看可以發現判斷的圖片是笑臉的時候誤判的概率更小一點
四、檢測別的圖片的效果
雖然正確率不是很高但是在一些微笑的比較標準的圖片還是可以檢測出來的。
實現我們剛剛自己的模型檢測圖片的程式碼步驟也很簡單,就是先提取圖片人臉的特徵值,再用這個模型進行檢測就可以了。
from cv2 import cv2 as cv2
import os
import dlib
from skimage import io
import csv
import numpy as np
from libsvm.svmutil import *
#要讀取人臉影象檔案的路徑
path_images_from_camera = "D:\\baidu\\genki4k"
# Dlib 正向人臉檢測器
detector = dlib.get_frontal_face_detector()
# Dlib 人臉預測器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
# Dlib 人臉識別模型
# Face recognition model, the object maps human faces into 128D vectors
face_rec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat")
# 返回單張影象的 128D 特徵
def return_128d_features(path_img):
img_rd = io.imread(path_img)
img_gray = cv2.cvtColor(img_rd, cv2.COLOR_BGR2RGB)
faces = detector(img_gray, 1)
if len(faces)==0:
return [0]
shape = predictor(img_gray, faces[0])
face_descriptor = face_rec.compute_face_descriptor(img_gray, shape)
return face_descriptor
model=svm_load_model("../mymodel.txt")
index=[]
for i in range(1,129):
index.append(i)
testy=[]
testy.append(1)
testx=[]
testx.append(dict(zip(index,return_128d_features("test1.jpg"))))
p_label, p_acc, p_val = svm_predict(testy,testx , model,"-b 1")
# 使用得到的模型進行預測
if p_label==[1.0]:
res="simle"
else:
res="no simle"
img = cv2.imread("test1.jpg")
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, res, (30, 30),font, 1.2, (0, 0, 0),2)
cv2.imshow('video', img)
cv2.waitKey(0)
現在我們去找兩張圖片來試試吧
這樣看來結果還是勉強算是成功的吧。
五、總結
通過這次實驗,學習了自己實現一個基於SVM的機器學習的這樣一個微笑識別的小專案,瞭解了對影象處理以及資料處理的簡單方法和如何將實際的方面使用機器學習。