基本出发点是想做一个C++版本的人脸识别,而caffe的C++库,或mxnet的C++库等,暂时还不会编译,而之前基于onnxruntime 搞过一个项目,对这个库稍微了解一些,所以尽量采用onnx搞定全部功能

核心的识别是基于https://github.com/onnx/models/blob/master/vision/body_analysis/arcfaceicon-default.png?t=LA92https://github.com/onnx/models/blob/master/vision/body_analysis/arcface

直接运行该工程,可以得到如下结果:

Distance = 0.461761
Similarity = 0.769120

是可以正常运行的

不过他这个mtcnn人脸检测,看起来是采用mxnet加载的caffemodel的网络,嗯,可能不太好转为C++

不过我在github上还是找到了一个用onn库的mtcnn,https://github.com/linxiaohui/mtcnn-opencvicon-default.png?t=LA92https://github.com/linxiaohui/mtcnn-opencv

暂时先用这个库来替换原来网络中的mtcnn,难度应该不大

接下来是用onnxruntime来替换mxnet,加载 arcfaceresnet100-8.onnx 来执行人脸识别,这个还是有点儿坑

如果直接替换的话,会报错:

2021-12-12 20:37:38.028783022 [E:onnxruntime:, sequential_executor.cc:346 Execute] Non-zero status code returned while running BatchNormalization node. Name:'stage1_unit1_bn1' Status Message: Invalid input scale: NumDimensions() != 3
Traceback (most recent call last):
  File "/home/luke/Download/onnx/myFaceRec/arcface_inference_remove_mxnet.py", line 254, in <module>
    out1 = get_feature(pre1)
  File "/home/luke/Download/onnx/myFaceRec/arcface_inference_remove_mxnet.py", line 217, in get_feature
    embedding = session.run([label_name], {'data': norm_img_data})
  File "/home/luke/miniconda3/lib/python3.9/site-packages/onnxruntime/capi/onnxruntime_inference_collection.py", line 192, in run
    return self._sess.run(output_names, input_feed, run_options)
onnxruntime.capi.onnxruntime_pybind11_state.InvalidArgument: [ONNXRuntimeError] : 2 : INVALID_ARGUMENT : Non-zero status code returned while running BatchNormalization node. Name:'stage1_unit1_bn1' Status Message: Invalid input scale: NumDimensions() != 3

如果搜索这个报错的话,可能可以搜索到issue:[ONNXRuntimeError] Arcface model fails during ONNX runtime session run · Issue #242 · onnx/models · GitHub在这个issue中有人给出了解决方案:

import onnx

model = onnx.load(r'arcfaceresnet100-8.onnx')

for node in model.graph.node:
    if(node.op_type == "BatchNormalization"):
        for attr in node.attribute:
            if (attr.name == "spatial"):
                attr.i = 1
                
onnx.save(model, r'updated_resnet100.onnx')

用该脚本执行后,就可以得到相同的结果,核心代码为:

session = onnxruntime.InferenceSession('updated_resnet100.onnx', None)

def get_feature(aligned):
    input_name = session.get_inputs()[0].name
    label_name = session.get_outputs()[0].name
    norm_img_data = aligned.reshape(1, 3, 112, 112).astype('float32')
    embedding = session.run([label_name], {'data': norm_img_data})
    embedding = sklearn.preprocessing.normalize(embedding[0]).flatten()
    return embedding

识别结果为:

Distance = 0.531714
Similarity = 0.734143

和原代码有点儿不同,但基本一致

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐