Als Programmierpraxis habe ich beschlossen, etwas zu implementieren und ein Lächeln zu erkennen. Deep Learning macht heute viel Lärm, wird aber ziemlich altmodisch implementiert. Da es sich um ein geeignetes System handelt, das ich mit meinen eigenen Ideen erstellt habe, würde ich es begrüßen, wenn Sie Kommentare abgeben könnten, wenn Sie Vorschläge haben.
Der Ablauf der Lächelnerkennung ist wie folgt.
Um den Kaskadenklassifikator verwenden zu können, benötigen Sie haarcascade_frontalface_alt.xml von hier. Klonen Sie ihn daher bitte.
SVM einer Klasse wird häufig bei Problemen verwendet, bei denen es schwierig ist, Lehrerdaten zu erfassen. Dieses Mal werde ich es als Problem bei der Erkennung von Anomalien verwenden. Mit anderen Worten, der Zustand des Lächelns wird als "normal" definiert, und die anderen Zustände werden als "abnormal" definiert.
In einer normalen SVM (Support Vector Machine) wird überwachtes Lernen durchgeführt, um eine Diskriminanzgrenze zu finden. Wenn man also vom Problem der Lächelnerkennung spricht, ist es ein Bild von Lerndaten wie "wahres Gesicht" zusätzlich zu "Lächeln". Andererseits führt One Class SVM unbeaufsichtigtes Lernen durch und bestimmt, ob es "normal" oder "abnormal" ist. Wenn Sie also die Lerndaten "Lächeln" haben, können Sie "Lächeln" von "Anders als das" unterscheiden.
Es gibt drei Phasen.
main.py
import numpy as np
import cv2
from skimage.feature import hog
from sklearn.svm import OneClassSVM
from sklearn.decomposition import PCA
import pickle
n = 3
n_dim = 4
alpha = - 1.0e+6
th = 20 #3
nu = 0.2 #0.1 #Prozentsatz der Ausreißer in den Eingabedaten
font = cv2.FONT_HERSHEY_COMPLEX
train_data = "./dataset/train/train.csv"
weights = "./dataset/weights/weights.sav"
weights_pca = "./dataset/weights/weights_pca.sav"
f_ = cv2.CascadeClassifier() # "./cascades/haarcascade_fullbody.xml"
f_.load(cv2.samples.findFile("./cascades/haarcascade_frontalface_alt.xml"))
def preprocess(image):
frame = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
frame = cv2.equalizeHist(frame)
return frame
def data_collect():
feature = []
capture = cv2.VideoCapture(0)
while (True):
ret, frame = capture.read()
frame = preprocess(frame)
face = f_.detectMultiScale(frame) # ,scaleFactor=1.2
for rect in face:
cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (255, 255, 0), thickness=2)
face_frame = frame[rect[1]:rect[1] + rect[3], rect[0]:rect[0] + rect[2]]
face_frame = cv2.resize(face_frame, (60, 60))
hog_f_, im = hog(face_frame, visualise=True,transform_sqrt=True)
feature = np.append(feature,hog_f_)
np.savetxt(train_data,feature.reshape(-1,2025), delimiter=",")
cv2.putText(frame, "please smile for collecting data!", (10, 100), font,
1, (255, 255, 0), 1, cv2.LINE_AA)
cv2.waitKey(1)
cv2.imshow("face", frame)
def train():
x_train = np.loadtxt(train_data,delimiter=",")
pca = PCA(n_components=n_dim)
clf = OneClassSVM(nu=nu, gamma=40/n_dim)#1/n_dim
z_train = pca.fit_transform(x_train)
clf.fit(z_train)
pickle.dump(pca, open(weights_pca, "wb"))
pickle.dump(clf,open(weights,"wb"))
def main():
clf = pickle.load(open(weights,"rb"))
pca = pickle.load(open(weights_pca, "rb"))
capture = cv2.VideoCapture(0)
while(True):
ret,frame = capture.read()
frame = preprocess(frame)
face = f_.detectMultiScale(frame)
for rect in face:
cv2.rectangle(frame,tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]),(255,255,0),thickness=2)
face_frame = frame[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
face_frame = cv2.resize(face_frame,(60,60))
feature , _ = hog(face_frame,visualise=True,transform_sqrt=True)
z_feature = pca.transform(feature.reshape(1,2025))
score = clf.predict(z_feature.reshape(1,n_dim))
if score[0]== 1:
cv2.putText(frame, "smile!", (10, 100), font,
1, (255, 255, 0), 1, cv2.LINE_AA)
cv2.waitKey(1)
cv2.imshow("face",frame)#Regentag v,Spezifiziert von u
if __name__ == '__main__':
data_collect() #Sammeln Sie zunächst Lächeln-Daten, indem Sie nur mit dieser Funktion drehen
#train() #Daten lächeln(csv)Lesen und lernen Sie svm
#main() #Lächelnerkennung mit dem erlernten Modell
(Die genaue Implementierung finden Sie unter hier. Eine Klasse SVM verwendete die Implementierung von Scicit-Learn. Wenn Sie es tatsächlich verwenden, erstellen Sie ein Verzeichnis wie unten gezeigt. Ich würde mich freuen, wenn Sie auf Fehler im Code hinweisen könnten. OneClassSVM/ ├ dataset/ │ └ train/ │ └ weights/ ├ cascades/ └ main.py
Nach dem Ausschneiden des Gesichtsbilds mit dem Kaskadenklassifikator wird die Größe auf 60 x 60 geändert. (Die Größe wurde entsprechend festgelegt.) Vor dem Erlernen von SVM reduziert PCA die Dimension der HOG-Funktionen. Der Grund dafür ist, dass ich mir Sorgen um den Fluch gemacht habe, weil die Dimension von HOG 2000 überschreitet. Sie können die Anzahl der Dimensionen nach der Reduzierung mit n_dim angeben. Diesmal wurde es auf 4 gesetzt. Beim Erlernen von One Class SVM dauerte es einige Zeit, um die Hyperparameter anzupassen. Das Fit-Argument von OneClass SVM enthält Nu und Gamma. Es scheint, dass nu die Abnormalitätsrate in den Trainingsdaten ist und Gamma die Anzahl der Dimensionen von 1 / Merkmalsmenge. Da die Trainingsdaten jedoch in erster Linie keine abnormalen Werte enthalten, suchte ich nach einem guten Parameter, während ich main () drehte und train () ausführte. Schließlich ist nu = 0,3, gamma = 50 / Merkmalsmengen-Dimensionsnummer. Möglicherweise müssen Sie Nu und Gamma anpassen, wenn Sie es verwenden.
Ich drehte main () und machte ein Experiment. Die Genauigkeit, wenn das Gesicht nach vorne zeigt, ist angemessen (ungefähr 80% werden wahrgenommen), aber da ich in den Trainingsdaten ein Lächeln auf der Ebene des Lächelns eingefügt habe, wurde es schwierig, die Grenze zwischen dem wahren Gesicht und dem Lächeln zu lernen. Es könnte getan worden sein.
Gesichtserkennung durch OpenCV Haar-Cascade Erkennung abnormaler Werte mit One Class SVM