leondgarse / Keras_insightface

Insightface Keras implementation
MIT License
239 stars 55 forks source link

Real time face recognition with Android Problem #7

Closed c7934597 closed 4 years ago

c7934597 commented 4 years ago

作者你好,我接觸人臉辨識不久,我套用到Android實作有些問題想要請求幫助,我參考以下Android連結實作, https://github.com/estebanuri/face_recognition 這位作者是使用 https://github.com/sirius-ai/MobileFaceNet_TF 的訓練模型, 我想替換成使用你的方式訓練新模型套用,不過遇到以下問題。

我使用 Training example 或是 basic strategy 的方式去訓練,資料集是MS1M-ArcFace。 1.因為這位作者使用的模型是輸出是192,所以我是使用192份類別資料夾去訓練,你的模型輸出是256我是拿256份類別資料去訓練。所以基本策略這裡,classes我就依照我用幾份人臉類別資料就填多少,model_output = keras.layers.Dense(classes, activation="softmax")(basic_model.outputs[0]) ,這樣的訓練方式是對的嗎?

2.我用以上方式訓練後,基本策略套到該Android實作時的人臉輸入正常,可是辨識輸出的時候會有問題,多人辨識輸出的時候,明明我只有存其中一人照片,可是其他人也都會被偵測出同一個綠框,只是距離顯示不同。 可是使用sirius-ai這作者的模型,他會辨識輸出時,不同人就不會被偵測出綠框,而是會有存照片的人才有綠框,沒存的就是藍框。 我要請問的是你的mobilefacenet與這作者的mobilefacenet模型差別是哪裡呢? 因為我檢查網路層還有輸出測試找不出應該怎麼修改,修改很多次無法解決這問題,需要請你幫忙,謝謝。

leondgarse commented 4 years ago
  1. classes 是训练时候的人脸类别数量,正常不需要单独指定,是由训练数据集中判断的
  2. 这里的 192 / 256 是指 模型提取的人脸特征数量,使用这个特征对比不同人脸的相似程度,我的代码中是在初始化 basic_model 时指定的
    # emb_shape 指定特征数量
    basic_model = train.buildin_models("mobilenet", dropout=0, emb_shape=192)
  3. 距离计算可以有多种方式,python 中计算 cos 距离判断相似度示例,一般建议相似度 > 0.6 可以判断为同一个人
    
    iaa = np.zeros([1, 112, 112, 3]) # 图片 1
    ibb = np.ones([1, 112, 112, 3]) # 图片 2

mm = keras.models.load_model('model_path.h5') # 加载 basic_model 模型 eaa = mm(iaa) # 图片 1 的特征,可以是 192 / 256 / 512 ebb = mm(ibb) # 图片 2 的特征 print(eaa.shape, ebb.shape)

(1, 256) (1, 256)

from sklearn.preprocessing import normalize eea = normalize(eaa) # 归一化 eeb = normalize(ebb) print((eea 2).sum(), (eeb 2).sum())

1.0 1.0

print(np.dot(eea, eeb.T)) # 计算 cos 距离相似度

[[0.38431713]]


4. 一个 `android` 项目使用欧氏距离判断相似度的示例 [syaringan357/Android-MobileFaceNet-MTCNN-FaceAntiSpoofing MobileFaceNet.java](https://github.com/syaringan357/Android-MobileFaceNet-MTCNN-FaceAntiSpoofing/blob/master/app/src/main/java/com/zwp/mobilefacenet/mobilefacenet/MobileFaceNet.java)
c7934597 commented 4 years ago

你好,行動端部分我已經解決了,我使用那位作者的實作範例並且參考你的模型訓練方式得到模型,已經可以套用正常實作。 不過我在電腦上使用你這段辨識程式碼,辨識兩張照片相似度,以下這個部分是怎麼取出特徵的呢?

eaa = mm(iaa) # 图片 1 的特征,可以是 192 / 256 / 512
ebb = mm(ibb) # 图片 2 的特征

因為我測試時有問題卡住,之前我是只有用你上面寫的np那段圖片一圖片二來測試, 現在要套用OpenCV讀圖片辨識,兩張幾乎一樣的照片且同個人都會辨識失敗。

我觀念是這樣, 行動端Android 有ML Kit的方式類似像MTCNN偵測人臉和臉部特徵後才丟到TFLite編碼, 所以在本機端是不是應該也要用MTCNN取出特徵後,才再丟進模型來編碼計算相似度, 而不能直接用OpenCV直接讀圖來計算呢? 我這裡觀念不懂,希望你能幫我解答測試方式,謝謝。

我的寫法如下並且套用到你下面那段歸一化並計算COS距離,可是感覺他是把整張圖拿去編碼,所以一直出現辨識嚴重錯誤, 就連拿原本訓練資料的112*112圖片來辨識也是嚴重錯誤,所以是先使用MTCNN取出特徵後再丟這模型嗎?

iaa = cv2.imread(PATH+'/datasets/1.jpg')
iaa = cv2.resize(iaa, (112, 112))
iaa = np.array([iaa])

ibb = cv2.imread(PATH+'/datasets/2.jpg')
ibb  = cv2.resize(ibb, (112, 112))
ibb = np.array([ibb])

eaa = mm.predict(iaa)
ebb = mm.predict(ibb)
leondgarse commented 4 years ago

import insightface from sklearn.preprocessing import normalize from skimage import transform from skimage.io import imread import matplotlib.pyplot as plt import numpy as np from tensorflow import keras

''' skimage 人脸对齐,也可以使用 opencv ''' def face_align_landmarks_sk(img, landmarks, image_size=(112, 112), method='similar'): tform = transform.AffineTransform() if method == 'affine' else transform.SimilarityTransform() src = np.array([[38.2946, 51.6963], [73.5318, 51.5014], [56.0252, 71.7366], [41.5493, 92.3655], [70.729904, 92.2041]], dtype=np.float32) ret = [] for landmark in landmarks:

landmark = np.array(landmark).reshape(2, 5)[::-1].T

    tform.estimate(landmark, src)
    ret.append(transform.warp(img, tform.inverse, output_shape=image_size))
return (np.array(ret) * 255).astype(np.uint8)

''' mobilenet retinaface 人脸检测 ''' det = insightface.model_zoo.face_detection.retinaface_mnet025_v1() det.prepare(-1)

iaa = imread('test.jpg') bbs, pps = det.detect(iaa[:, :, ::-1]) # 输入图像 RGB -> BGR,返回值 bbs 为人脸位置坐标,pps 为 5 个人脸关键点坐标

''' 人脸对齐 ''' nimgs = face_align_landmarks_sk(iaa, pps) plt.imshow(np.hstack(nimgs)) # 显示对齐后的人脸 nimgs_norm = (nimgs - 127.5) / 127 # 图像数值 [0, 255] 处理成 [-1, 1],用于模型输入 print(nimgs_norm.shape, nimgs_norm.max(), nimgs_norm.min()) # 该图片中有两个人脸

(2, 112, 112, 3) 0.9960629921259843 -0.9409448818897638

''' 提取特征 ''' mm = keras.models.load_model('model_path.h5') ees = normalize(mm(nimgs_norm)) np.dot(ees, ees.T) # 计算 cos 距离

c7934597 commented 4 years ago

感謝,我現在可以正常辨識了,觀念也釐清。 以下忽略,剛剛發現是windows才會有錯誤,換台linux就正常可以跑了。 都不會有以下問題,感謝!! ==================================================== 主要是讀圖片那邊我增加resize的部分,然後有個問題問一下。 為什麼模型預測這邊你是使用mm(),而不是mm.predict。

# iaa_ees = normalize(mm.predict(iaa_nimgs_norm))
# ibb_ees = normalize(mm.predict(ibb_nimgs_norm))
iaa_ees = normalize(mm(iaa_nimgs_norm))
ibb_ees = normalize(mm(ibb_nimgs_norm))

因為我是tensorflow 2.3,使用mm()會跳出以下錯誤,查了一下這連結,貌似TF版本寫法不同而已?! https://github.com/tensorflow/tensorflow/issues/24828

Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above. [Op:Conv2D]

mobilenet_adamw_BS256_E80_arc_tripD_basic_agedb_30_epoch_123_0.955333.h5 話說我用這個模型進行你這段圖片辨識也會遇到類似問題,可是行動端正常,所以我這段圖片辨識只能用se_mobilefacenet的模型方式去訓練去辨識才能正常,還是cuDNN的版本差別嗎? 我是7.6.5。

Failed to get convolution algorithm. This is probably because cuDNN failed to initialize, so try looking to see if a warning log message was printed above.
     [[node functional_1/conv1/Conv2D (defined at <ipython-input-6-338eb5f9ee10>:49) ]] [Op:__inference_predict_function_3480]

Function call stack:
predict_function