人臉檢測系統在當今世界中具有巨大的用途,這個系統要求安全性,可訪問性和趣味性!今天,我們將建立一個可以在臉上繪制15個關鍵點的模型。
人臉特征檢測模型形成了我們在社交媒體應用程序中看到的各種功能。 您在Instagram上找到的面部過濾器是一個常見的用例。該算法將掩膜(mask)在圖像上對齊,並以臉部特征作為模型的基點。
Instagram自拍過濾器需要知道您的眼睛,嘴唇和鼻子在圖像上的確切位置
讓我們使用Keras(TensorFlow作為底層)開發模型!首先,我們需要一些數據來訓練我們的模型。
數據
我們使用Omri Goldstein Kaggle 上的帶有標記特征的人臉圖像數據集。數據集包含大約7000張圖像(96*96),這些圖像帶有可以在facial_keypoints.csv文件中找到的面部標志。
但是在這里我們有一個問題。大多數圖像沒有15個完整的點集。因此,我們只需要那些具有15個面部關鍵點的圖像即可。
可以使用此腳本,我已經做了一些清理,並將修改后的數據保存在Dataset Archives GitHub中。 Colab notebook需要使用wget命令下載ZIP文件。
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split # Download the dataset from Kaggle. Unzip the archive. You'll find the facial_keypoints.csv file there. facial_keypoints = pd.read_csv( "files/face-images-with-marked-landmark-points/facial_keypoints.csv") num_missing_keypoints = facial_keypoints.isnull().sum( axis=1 ) all_keypoints_present_ids = np.nonzero( num_missing_keypoints == 0 )[ 0 ] # face_images.npz is present the same archive. d = np.load( "files/face-images-with-marked-landmark-points/face_images.npz") dataset = d[ 'face_images' ].T dataset = np.reshape( dataset , ( -1 , 96 , 96 , 1 ) ) images = dataset[ all_keypoints_present_ids , : , : , : ] keypoints = facial_keypoints.iloc[ all_keypoints_present_ids , : ].reset_index( drop=True ).values x_train, x_test, y_train, y_test = train_test_split( images , keypoints , test_size=0.3 ) # Save all the processed data. np.save( "processed_data/x_train.npy" , x_train ) np.save( "processed_data/y_train.npy" , y_train ) np.save( "processed_data/x_test.npy" , x_test ) np.save( "processed_data/y_test.npy" , y_test )
我們還將圖像以及坐標(關鍵點)進行了標准化處理。 我們對y_train和y_test進行了重塑操作,因為它們將成為卷積層(Conv2D)而不是全連接層(Dense
)的輸出。
x_train = np.load( "face_landmarks_cleaned/x_train.npy" ) / 255 y_train = np.load( "face_landmarks_cleaned/y_train.npy" ) / 96 x_test = np.load( "face_landmarks_cleaned/x_test.npy" ) / 255 y_test = np.load( "face_landmarks_cleaned/y_test.npy" ) / 96 y_train = np.reshape( y_train , ( -1 , 1 , 1 , 30 )) y_test = np.reshape( y_test , ( -1 , 1 , 1 , 30 ))
提示:我們找到了另一個用於人臉特征檢測的數據集,稱為UTKFace。它包含68個面部關鍵點以及其他特征,例如年齡和性別。可以嘗試一下!
討論模型
下面讓我們討論該模型的結構。我對該模型做了一些實驗。我們需要一個模型,該模型采用尺寸為(96,96)的圖像作為輸入並輸出形狀為(30,)的數組(15個關鍵點* 2個坐標)
1.第一種模型讀取一張圖像,並將其通過預先訓練的VGG網絡。 接下來,將VGG的輸出展平並通過多個全連接層。問題在於,即使損失很小,模型也可以為每個圖像預測相同的關鍵點。
2.第二種模型是您可以在Colab notebook中找到的模型。 我們不使用全連接層。 相反,我們將圖像傳遞給卷積層,並獲得形狀為(1,1,30)的輸出。 因此,卷積層為我們提供了輸出。使用此模型,對於每張圖像甚至在數據集之外的圖像,預測值都是不同的!
我們的模型是這樣的。
model_layers = [
tf.keras.layers.Conv2D( 256 , input_shape=( 96 , 96 , 1 ) , kernel_size=( 3 , 3 ) , strides=2 , activation='relu' ), tf.keras.layers.Conv2D( 256 , kernel_size=( 3 , 3 ) , strides=2 , activation='relu' ), tf.keras.layers.BatchNormalization(), tf.keras.layers.Conv2D( 128 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.Conv2D( 128 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.BatchNormalization(), tf.keras.layers.Conv2D( 128 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.Conv2D( 128 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.BatchNormalization(), tf.keras.layers.Conv2D( 64 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.Conv2D( 64 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.BatchNormalization(), tf.keras.layers.Conv2D( 32 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.Conv2D( 32 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.BatchNormalization(), tf.keras.layers.Conv2D( 30 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.Conv2D( 30 , kernel_size=( 3 , 3 ) , strides=1 , activation='relu' ), tf.keras.layers.Conv2D( 30 , kernel_size=( 3 , 3 ) , strides=1 ), ] model = tf.keras.Sequential( model_layers ) model.compile( loss=tf.keras.losses.mean_squared_error , optimizer=tf.keras.optimizers.Adam( lr=0.0001 ) , metrics=[ 'mse' ] )
在執行回歸任務時,我們使用 均方誤差(MSE)。 如果您有大量的數據,那么較小的學習率總是好的。
訓練和相關推論
我們訓練模型約250次,批處理數量為50個。訓練后,我們將在測試集上進行一些預測。
import matplotlib.pyplot as plt fig = plt.figure(figsize=( 50 , 50 )) for i in range( 1 , 6 ): sample_image = np.reshape( x_test[i] * 255 , ( 96 , 96 ) ).astype( np.uint8 ) pred = model.predict( x_test[ i : i +1 ] ) * 96 pred = pred.astype( np.int32 ) pred = np.reshape( pred[0 , 0 , 0 ] , ( 15 , 2 ) ) fig.add_subplot( 1 , 10 , i ) plt.imshow( sample_image.T , cmap='gray' ) plt.scatter( pred[ : , 0 ] , pred[ : , 1 ] , c='yellow' ) plt.show()
生成預測值
注意:請記住輸入圖像的旋轉角度。 在旋轉90度的圖像上訓練的模型無法為沒有進行旋轉的圖像生成正確的預測。
如果您未對模型和訓練參數進行修改,則經過250次訓練后的模型應如下圖所示:
結果
印象相當深刻吧?就這樣!您剛剛從頭開始構建了一個人臉特征檢測模型。 在Colab notebook中,我設置了一個代碼單元,您可以將網絡上的圖像或攝像頭拍攝的圖像放入其中並運行模型。
作者:Shubham Panchal
deephub翻譯組:孟翔傑
原文連接:https://imba.deephub.ai/p/2aad31b06fc711ea90cd05de3860c663