公司需要在项目中使用人脸识别SDK,并且对信息安全的要求非常高,在详细了解市场上几个主流人脸识别SDK后,综合来看虹软的Arcface SDK比较符合我们的需求,它提供了免费版本,并且可以在离线环境下使用,这一点非常符合我们对安全性的要求。但有个遗憾的事情,我们的项目主要使用了Python语言,虹软官方并没有提供Python版本的SDK,因此我自己使用Python封装了Arcface C++ SDK,便于在项目中使用,这里将主要过程写出来供大家探讨下。

1.环境说明
 a.注意Win64环境的Python必须使用ArcFace C++(Win64) SDK,如果平台不一致, 否则可能会出现以下错误。

OSError: [WinError 193] %1 不是有效的 Win32 应用程序

b.由于SDK中涉及到内存操作,本文使用了ctypes包和cdll包提供的以下几种方式

c_ubyte_p = POINTER(c_ubyte)
memcpy = cdll.msvcrt.memcpy
malloc = cdll.msvcrt.malloc
malloc.restype = c_void_p
free = cdll.msvcrt.free

2.Arcface SDK基本数据结构封装

在封装数据结构时,一定要注意参数类型,否则可能会导致程序出错。

class MRECT(Structure): # 人脸框
_fields_ = [(u'left', c_int32),
(u'top', c_int32),
(u'right', c_int32),
(u'bottom', c_int32)]class ASFVersion(Structure): # 版本信息 版本号 构建日期 版权说明
_fields_ = [
('Version', c_char_p),
('BuildDate', c_char_p),
('CopyRight', c_char_p)]class ASFSingleFaceInfo(Structure): # 单人脸信息 人脸框 人脸角度
_fields_ = [
('faceRect', MRECT),
('faceOrient', c_int32)]class ASFMultiFaceInfo(Structure): # 多人脸信息 人脸框数组 人脸角度数组 人脸数
_fields_ = [
(u'faceRect', POINTER(MRECT)),
(u'faceOrient', POINTER(c_int32)),
(u'faceNum', c_int32)]class ASFFaceFeature(Structure): # 人脸特征 人脸特征 人脸特征长度
_fields_ = [
('feature', c_void_p),
('featureSize', c_int32)]class ASFFace3DAngle(Structure): # 人脸角度信息
_fields_ = [
('roll', c_void_p),
('yaw', c_void_p),
('pitch', c_void_p),
('status', c_void_p),
('num', c_int32)]class ASFAgeInfo(Structure): # 年龄
_fields_ = [
(u'ageArray', c_void_p),
(u'num', c_int32)]class ASFGenderInfo(Structure): # 性别
_fields_ = [
(u'genderArray', c_void_p),
(u'num', c_int32)]class ASFLivenessThreshold(Structure): # 活体阈值
_fields_ = [
(u'thresholdmodel_BGR', c_float),
(u'thresholdmodel_IR', c_int32)]class ASFLivenessInfo(Structure): # 活体信息
_fields_ = [
(u'isLive', c_void_p),
(u'num', c_int32)]

3.Arcface SDK接口封装

a.接口封装之前需要加载dll库,Arcface SDK 提供的dll都需要加载。
b.本文中图片格式使用了ASVL_PAF_RGB24_B8G8R8。
c.每个接口都需要定义返回值以及参数类型,某些参数类型依赖前文所述的基本数据结构。

from arcsoft_face_struct import *
from ctypes import *
from enum import Enumface_dll = CDLL("libarcsoft_face.dll")
face_engine_dll = CDLL("libarcsoft_face_engine.dll")ASF_DETECT_MODE_VIDEO = 0x00000000
ASF_DETECT_MODE_IMAGE = 0xFFFFFFFFASF_NONE = 0x00000000
ASF_FACE_DETECT = 0x00000001
ASF_FACE_RECOGNITION = 0x00000004
ASF_AGE = 0x00000008
ASF_GENDER = 0x00000010
ASF_FACE3DANGLE = 0x00000020
ASF_LIVENESS = 0x00000080
ASF_IR_LIVENESS = 0x00000400ASVL_PAF_RGB24_B8G8R8 = 0x201class ArcSoftFaceOrientPriority(Enum):
ASF_OP_0_ONLY = 0x1,
ASF_OP_90_ONLY = 0x2,
ASF_OP_270_ONLY = 0x3,
ASF_OP_180_ONLY = 0x4,
ASF_OP_0_HIGHER_EXT = 0x5,activate = face_engine_dll.ASFActivation
activate.restype = c_int32
activate.argtypes = (c_char_p, c_char_p)init_engine = face_engine_dll.ASFInitEngine
init_engine.restype = c_int32
init_engine.argtypes = (c_long, c_int32, c_int32, c_int32, c_int32, POINTER(c_void_p))detect_face = face_engine_dll.ASFDetectFaces
detect_face.restype = c_int32
detect_face.argtypes = (c_void_p, c_int32, c_int32, c_int32, POINTER(c_ubyte), POINTER(ASFMultiFaceInfo))extract_feature = face_engine_dll.ASFFaceFeatureExtract
extract_feature.restype = c_int32
extract_feature.argtypes = (c_void_p, c_int32, c_int32, c_int32, POINTER(c_ubyte),
POINTER(ASFSingleFaceInfo), POINTER(ASFFaceFeature))compare_feature = face_engine_dll.ASFFaceFeatureCompare
compare_feature.restype = c_int32
compare_feature.argtypes = (c_void_p, POINTER(ASFFaceFeature),
POINTER(ASFFaceFeature), POINTER(c_float))set_liveness_param = face_engine_dll.ASFSetLivenessParam
set_liveness_param.restype = c_int32
set_liveness_param.argtypes = (c_void_p, POINTER(ASFLivenessThreshold))process = face_engine_dll.ASFProcess
process.restype = c_int32
process.argtypes = (c_void_p, c_int32, c_int32, c_int32, POINTER(c_ubyte),
POINTER(ASFMultiFaceInfo), c_int32)get_age = face_engine_dll.ASFGetAge
get_age.restype = c_int32
get_age.argtypes = (c_void_p, POINTER(ASFAgeInfo))get_gender = face_engine_dll.ASFGetGender
get_gender.restype = c_int32
get_gender.argtypes = (c_void_p, POINTER(ASFGenderInfo))get_3d_angle = face_engine_dll.ASFGetFace3DAngle
get_3d_angle.restype = c_int32
get_3d_angle.argtypes = (c_void_p, POINTER(ASFFace3DAngle))get_liveness_info = face_engine_dll.ASFGetLivenessScore
get_liveness_info.restype = c_int32
get_liveness_info.argtypes = (c_void_p, POINTER(ASFLivenessInfo))

4.封装接口调用

接下来按照下面的流程图介绍接口调用(此图使用 Microsoft Visio 2016自动生成)。

下图是按照此流程处理得到的效果图,由于画面有限,只显示了年龄、性别、活体信息。

a.激活
需要注意app_id和sdk_key需要使用字节类型。

app_id = b""
sdk_key = b""
ret = arcsoft_face_func.activate(app_id, sdk_key) # 激活
if ret == 0 or ret == 90114:
print("激活成功")
else:
print("激活失败:", ret)

b.初始化
初始化需要将所有需要的功能参数一次性传入,本文使用了人脸检测、特征提取等功能。

mask = arcsoft_face_func.ASF_FACE_DETECT | \
arcsoft_face_func.ASF_FACE_RECOGNITION | \
arcsoft_face_func.ASF_AGE | \
arcsoft_face_func.ASF_GENDER | \
arcsoft_face_func.ASF_FACE3DANGLE |\
arcsoft_face_func.ASF_LIVENESSengine = c_void_p()
ret = arcsoft_face_func.init_engine(arcsoft_face_func.ASF_DETECT_MODE_IMAGE,
arcsoft_face_func.ArcSoftFaceOrientPriority.ASF_OP_0_ONLY.value[0],
30, 10, mask, byref(engine))
if ret == 0:
print("初始化成功")
else:
print("初始化失败:", ret)

c.人脸检测

本文使用了opencv读图,兼容性更好,并且自定义的数据结构记录图片信息,注意 ArcFace C++ SDK 要求传入的图像宽度需要是4的倍数,下面做了裁剪。

class Image:
def __init__(self):
self.width = 0
self.height = 0
self.imageData = Nonedef load_image(file_path):
img = cv2.imread(file_path)
sp = img.shape
img = cv2.resize(img, (sp[1]//4*4, sp[0]))# 四字节对齐image = Image()
image.width = img.shape[1]
image.height = img.shape[0]
image.imageData = img
return image###################### 人脸检测 ##################################image1 = load_image(r"1.jpg")
image_bytes = bytes(image1.imageData)
image_ubytes = cast(image_bytes, c_ubyte_p)detect_faces = ASFMultiFaceInfo()
ret = arcsoft_face_func.detect_face(
engine,
image1.width,
image1.height,
arcsoft_face_func.ASVL_PAF_RGB24_B8G8R8,
image_ubytes,
byref(detect_faces)
)if ret == 0:
print("检测人脸成功")
else:
print("检测人脸失败:", ret)

d.特征提取

特征提取只支持单人脸,因此做了人脸处理操作,并且需要及时将提取的人脸特征拷贝一份,否则会被覆盖。

single_face1 = ASFSingleFaceInfo()
single_face1.faceRect = detect_faces.faceRect[0]
single_face1.faceOrient = detect_faces.faceOrient[0]face_feature = ASFFaceFeature()
ret = arcsoft_face_func.extract_feature(
engine,
image1.width,
image1.height,
arcsoft_face_func.ASVL_PAF_RGB24_B8G8R8,
image_ubytes,
single_face1,
byref(face_feature)
)if ret == 0:
print("提取特征1成功")
else:
print("提取特征1失败:", ret)feature1 = ASFFaceFeature()
feature1.featureSize = face_feature.featureSize
feature1.feature = malloc(feature1.featureSize)
memcpy(c_void_p(feature1.feature),
c_void_p(face_feature.feature),
feature1.featureSize)

e.特征比对

按照前文所述再提取一张人脸的特征,即可以进行下面的人脸特征比对操作

compare_threshold = c_float()
ret = arcsoft_face_func.compare_feature(
engine, feature1, feature2, compare_threshold
)free(c_void_p(feature1.feature))
free(c_void_p(feature2.feature))if ret == 0:
print("特征比对成功,相似度:", compare_threshold.value)
else:
print("特征比对失败:", ret)

f.年龄、性别、3D Angle

process接口目前提供了 年龄、性别、3D Angle、活体检测, 但年龄、性别、3D Angle支持多人脸,而活体只支持单人脸,因此下面分别处理。

process_mask = arcsoft_face_func.ASF_AGE | \
arcsoft_face_func.ASF_GENDER | \
arcsoft_face_func.ASF_FACE3DANGLEret = arcsoft_face_func.process(
engine,
image1.width,
image1.height,
arcsoft_face_func.ASVL_PAF_RGB24_B8G8R8,
image_ubytes,
byref(detect_faces),
c_int32(process_mask)
)if ret == 0:
print("process成功")
else:
print("process失败:", ret)######################## Age ################################age_info = ASFAgeInfo()
ret = arcsoft_face_func.get_age(engine, byref(age_info))if ret == 0:
print("get_age 成功")
age_ptr = cast(age_info.ageArray, POINTER(c_int))
for i in range(age_info.num):
print("face", i, "age:", age_ptr[i])
else:
print("get_age 失败:", ret)####################### Gender #################################gender_info = ASFGenderInfo()
ret = arcsoft_face_func.get_gender(engine, byref(gender_info))if ret == 0:
print("get_gender 成功")
gender_ptr = cast(gender_info.genderArray, POINTER(c_int))
for i in range(gender_info.num):
print("face", i, "gender:",
"女性" if (gender_ptr[i] == 1) else (
"男性" if (gender_ptr[i] == 0) else "未知"
))
else:
print("get_gender 失败:", ret)####################### 3D Angle #################################angle_info = ASFFace3DAngle()
ret = arcsoft_face_func.get_3d_angle(engine, byref(angle_info))if ret == 0:
print("get_3d_angle 成功")
roll_ptr = cast(angle_info.roll, POINTER(c_float))
yaw_ptr = cast(angle_info.yaw, POINTER(c_float))
pitch_ptr = cast(angle_info.pitch, POINTER(c_float))
status_ptr = cast(angle_info.status, POINTER(c_int32))
for i in range(angle_info.num):
print("face", i,
"roll:", roll_ptr[i],
"yaw:", yaw_ptr[i],
"pitch:", pitch_ptr[i],
"status:", "正常" if status_ptr[i] == 0 else "出错")else:
print("get_3d_angle 失败:", ret)

g.RGB活体

在活体检测之前建议按照实际场景设置活体阈值,不设置即使用默认阈值,这里设置了RGB活体的阈值为0.75。并将检测的多人脸分别转为单张人脸的参数传到接口中。

######################### 活体阈值设置 ###############################
threshold_param = ASFLivenessThreshold()
threshold_param.thresholdmodel_BGR = 0.75
ret = arcsoft_face_func.set_liveness_param(engine,threshold_param)if ret == 0:
print("set_liveness_param成功")
else:
print("set_liveness_param 失败:", ret)temp_face_info = ASFMultiFaceInfo()
temp_face_info.faceNum = 1
LP_MRECT = POINTER(MRECT)
temp_face_info.faceRect = LP_MRECT(MRECT(malloc(sizeof(MRECT))))
LP_c_long = POINTER(c_long)
temp_face_info.faceOrient = LP_c_long(c_long(malloc(sizeof(c_long))))for i in range(detect_faces.faceNum):
temp_face_info.faceRect[0] = detect_faces.faceRect[i]
temp_face_info.faceOrient[0] = detect_faces.faceOrient[i]ret = arcsoft_face_func.process(
engine,
image1.width,
image1.height,
arcsoft_face_func.ASVL_PAF_RGB24_B8G8R8,
image_ubytes,
byref(temp_face_info),
c_int32(arcsoft_face_func.ASF_LIVENESS)
)if ret == 0:
print("process成功")
else:
print("process失败:", ret)
## RGB活体检测
ret = arcsoft_face_func.process(
engine,
image1.width,
image1.height,
arcsoft_face_func.ASVL_PAF_RGB24_B8G8R8,
image_ubytes,
byref(temp_face_info),
c_int32(arcsoft_face_func.ASF_LIVENESS)
)if ret == 0:
print("process成功")
else:
print("process失败:", ret)liveness_info = ASFLivenessInfo()
ret = arcsoft_face_func.get_liveness_info(engine, byref(liveness_info))if ret == 0:
print("get_liveness_info 成功")
liveness_ptr = cast(liveness_info.isLive, POINTER(c_int))
print("face", i, "liveness:",
"非真人" if (liveness_ptr[0] == 0) else (
"真人" if (liveness_ptr[0] == 1) else (
"不确定" if (liveness_ptr[0] == -1) else (
"传入人脸数>1" if (liveness_ptr[0] == -2) else
(liveness_ptr[0])
)
)
))
else:
print("get_liveness_info 失败:", ret)

  写在最后,欢迎大家交流指正,若有需要下载其他语言的SDK或demo,可至其官网下载~https://ai.arcsoft.com.cn/product/arcface.html?utm_source=cnblogs&utm_medium=referral

转载于:https://www.cnblogs.com/jdjd123/p/11510224.html

如何使用 python 接入虹软 ArcFace SDK相关推荐

  1. python调用sdk的文章_如何使用 python 接入虹软 ArcFace SDK

    公司需要在项目中使用人脸识别SDK,并且对信息安全的要求非常高,在详细了解市场上几个主流人脸识别SDK后,综合来看虹软的Arcface SDK比较符合我们的需求,它提供了免费版本,并且可以在离线环境下 ...

  2. pb 调用虹软_如何使用 python 接入虹软 ArcFace SDK

    公司需要在项目中使用人脸识别SDK,并且对信息安全的要求非常高,在详细了解市场上几个主流人脸识别SDK后,综合来看虹软的Arcface SDK比较符合我们的需求,它提供了免费版本,并且可以在离线环境下 ...

  3. 使用Delphi接入虹软人脸识别ArcFace,开发人脸库服务器

    利用虹软 SDK 开发局域网人脸库服务器 一.选择开发平台 以前做单位食堂人脸识别就餐时,会用到在线人脸识别,终端设备必须并入互联网,单位对人脸信息比较敏感,客户会要求提供内部网人脸库使用. 利用人脸 ...

  4. Android人脸识别开发入门--基于虹软免费SDK实现

    转自:http://blog.csdn.net/feishixin/article/details/77718680 引言 人工智能时代快速来临,其中人脸识别是当前比较热门的技术,在国内也越来越多的运 ...

  5. 基于python,虹软sdk3.0实现的实时人脸识别

    前言: 虹软sdk3.0是目前用过的最方便,效果最好的且免费的离线人脸识别SDK. 提供的编程语音没有python,有大佬用c++代码接口转成python调用的, 我在此基础上完善了一些功能,能够实现 ...

  6. 【java】人脸识别 虹软ArcFace 2.0-抽取人脸特征并做比对

    虹软产品地址:http://ai.arcsoft.com.cn/product/arcface.html 虹软ArcFace功能简介 人脸检测 人脸跟踪 人脸属性检测(性别.年龄) 人脸三维角度检测 ...

  7. 人脸识别算法虹软arcface和Dlib对比

    我司最近要做和人脸识别相关的产品,原来使用的是其他的在线平台,识别率和识别速度很满意,但是随着量起来的话,成本也是越来越不能接受(目前该功能我们是免费给用户使用的),而且一旦我们的设备掉线了就无法使用 ...

  8. 虹软 ArcFace 与 Dlib 人脸识别对比

    我司最近要做和人脸识别相关的产品,原来使用的是某在线人脸识别平台,识别率和识别速度很满意,但是随着量起来的话,成本也是越来越不能接受(目前该功能我们是免费给用户使用的),而且一旦我们的设备掉线了就无法 ...

  9. 用C#二次封装虹软arcface

    相信很多用C#又想用虹软的SDK的童鞋要花很多心思去研究怎么转换,所以写了一篇文章和一个demo方便用C#的童鞋方便调用虹软的接口,文章的地址是:https://blog.xgcos.com/show ...

最新文章

  1. vector iterator not incrementable 的问题
  2. java break在switch_java中switch case语句需要加入break的原因解析
  3. HBase基本概念与基本使用
  4. 【codevs1040】【01NOIPTG】统计单词个数,字符串的划分DP
  5. Python可以这样学(第七季:pillow扩展库图像编程)-董付国-专题视频课程
  6. php/eq,thinkphp中eq标签的使用
  7. mysql语句事务回滚_mysql语句,事务处理回滚的问题。
  8. 数据可视化——tableau 数据报表样例(报表模板)二
  9. 测试工具ApiPost和Postman及Apifox
  10. 自动控制原理学习笔记(五)
  11. 【单片机基础篇】51单片机流水灯
  12. 问题:office应用(word、ppt、excel、oneNote) 您的组织策略阻止我们为您完成此操作 解决办法
  13. 如何实现批量截取整个网页完整长截图?内容很多很高浏览器看不全Chrome插件崩溃无需安FireShot,优爱酷批量长网页整页截图系统,设计师推荐的必备好工具好方法web2pic,html2jpeg
  14. javaSE探赜索隐之三<类与对象的爱恨情仇中>
  15. OCP最新题库收集,052新加的考题及答案整理-19
  16. 适合学生写的请假管理系统
  17. Excel如何批量加大列宽
  18. 给老孙做了个排班表!
  19. 如何判断一个数是不是素数?
  20. there's not enought memory to perform the requrested operation.解决方法

热门文章

  1. DUToj1085 Water Problem(矩阵快速幂)
  2. 虚拟机VMware忘记密码如何重置密码?
  3. 飞书获取user_id
  4. Keras中保存和加载权重及模型结构
  5. 牛客每日练习----逆序对,星图,小周的曲射炮
  6. android 多进程关系,小议Android多进程以至Application屡次初始化
  7. python微信验证码_python:代码访问weixin.sogou.com的时候会出现验证码,但是浏览器打开就不会...
  8. 清理C盘垃圾,设置默认安装到其他盘
  9. m3 pcb开孔 螺丝_一种结构定位螺丝孔PAD的设计方法和PCB与流程
  10. 大学计算机英语句子,英语经典句子(精选100句)