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

公司需要在项目中使用人脸识别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 Enum

face_dll = CDLL("libarcsoft_face.dll")

face_engine_dll = CDLL("libarcsoft_face_engine.dll")

ASF_DETECT_MODE_VIDEO = 0x00000000

ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF

ASF_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 = 0x00000400

ASVL_PAF_RGB24_B8G8R8 = 0x201

class 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_LIVENESS

engine = 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 = None

def 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_FACE3DANGLE

ret = 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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245914.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java web 导出word_JavaWeb Project使用FreeMaker导出Word文件

基本思路1. 导入freemaker2.3.jar2. 需要导出的Word模板3. 在Word内填入值的标签4. Word另存为xml(2003版本)5. Coding6. 导出Word文件具体操作1. Intellij IDEA > FIle > Project Structure > Libraries > ""(左下角) > OK导入Freemaker Jar2. Word模…

机器人编程与python语言的区别_儿童编程和机器人编程有啥区别?

这是最全面的回答!一篇文章让你彻底了解少儿编程和机器人编程的区别!虽然都带有“编程”二字,但少儿编程和机器人编程还是有本质区别的,有哪些不一样呢?偷懒的家长可以直接看下面这张表格:想要详细了解的话…

php中tables,php显示TABLE数据

php显示TABLE数据2018-11-22//processShowData.php查询数据库表信息学生一览表<?php echo $id ?><?php echo $name ?><?php echo $age ?><?php echo $sex ?><?php echo $address ?>结果&#xff1a;学号姓名年龄性别地址1Jane26female…

云服务器安装python_云服务器 搭建 python

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":6,"count":6}]},"card":[{"des":"云服务器 ECS(Elastic Compute Service)是一…

php获取当前系统配置文件,thinkphp5.1+配置文件结构及获取

tp5.1和5.0的差别还是不小的&#xff0c;取消了很多东西&#xff0c;例如基本配置项就做了很大的改变。5.1没有config.php配置文件&#xff0c;默认配置都在app.php配置文件&#xff0c;并且配置参数区分大小写&#xff0c;所有的配置文件在config目录下。和5.0最大的区别是&am…

sql 除以_使用SQL分析游戏运营情况

数据来源&#xff1a;http://www.dcjingsai.com/common/cmpt/%E6%B8%B8%E6%88%8F%E7%8E%A9%E5%AE%B6%E4%BB%98%E8%B4%B9%E9%87%91%E9%A2%9D%E9%A2%84%E6%B5%8B%E5%A4%A7%E8%B5%9B_%E7%AB%9E%E8%B5%9B%E4%BF%A1%E6%81%AF.html游戏介绍&#xff1a;《野蛮时代》是一款SLG游戏。在…

好看的php验证码,一漂亮的PHP图片验证码实例

一、显示效果二、代码如下代码如下:/** Author fy*/$imgwidth 100; //图片宽度$imgheight 40; //图片高度$codelen 4; //验证码长度$fontsize 20; //字体大小$charset abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789;$font Fonts/segoesc.ttf;$imimagecreatetruecolor…

检测到目标服务器启用了trace方法_深度学习检测小目标常用方法

引言在深度学习目标检测中&#xff0c;特别是人脸检测中&#xff0c;小目标、小人脸的检测由于分辨率低&#xff0c;图片模糊&#xff0c;信息少&#xff0c;噪音多&#xff0c;所以一直是一个实际且常见的困难问题。不过在这几年的发展中&#xff0c;也涌现了一些提高小目标检…

php正则大小写字母,php 常见email,url,英文大小写,字母数字组合等正则表达式详解...

操作符 描述\ 转义符(), (?:), (?), [] 圆括号和方括号*, , ?, {n}, {n,}, {n,m} 限定符^, $, \anymetacharacter 位置和顺序| “或”操作全部符号解释字符 描述\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如&#xff0c;’…

学python五大理由_学习Python的五大理由

Python已经是25岁的大叔级编程语言了&#xff0c;但近年来Python反而变得越来越流行&#xff0c;在TIOBE编程语言指数排行榜中&#xff0c;Python的排名从去年的第八名飙升到了第五名(下图)。无论是编程新手还是保持饥饿的编程老鸟&#xff0c;Python都有着不可阻挡的魅力&…

redis连不上java,java使用jedis连不上linux上redis服务

java用的jedis连接redis。reids是安装在虚拟机里面&#xff0c;ip是192.168.216.128&#xff0c;在本地能ping通虚拟机&#xff0c;并且xshell也能远程登录虚拟机。虚拟机内的redis服务正常&#xff0c;可以启动&#xff0c;并且执行命令没问题。问题&#xff1a;在虚拟机外tel…

python图片隐写_Lsb图片隐写

前言在刚刚过去的网鼎杯第一场比赛中&#xff0c;做到了一道杂项题是关于lsb隐写的。LSB全称为 least significant bit&#xff0c;是最低有效位的意思。Lsb图片隐写是基于lsb算法的一种图片隐写术&#xff0c;以下统称为lsb隐写&#xff0c;这是一种常见的信息隐藏方法。当然关…

php自定义能过滤器,过滤器与自定义过滤器的介绍

angularjs中的过滤器为了实现对于表达式结果的筛选、过滤、格式化&#xff0c;达到更好的表现效果。过滤器的语法&#xff1a;支持多重过滤和传参{{expression | 过滤器名称 : ‘参数’ | 过滤器名称2&#xff1a;‘参数’ }}方式&#xff1a;| -》 管道常用的过滤器&#xff1…

python二维元素向量_详解python Numpy中求向量和矩阵的范数

在python Numpy中求向量和矩阵的范数实例np.linalg.norm(求范数):linalglinear(线性)algebra(代数)&#xff0c;norm则表示范数。函数参数x_normnp.linalg.norm(x, ordNone, axisNone, keepdimsFalse)①x: 表示矩阵(也可以是一维)②ord&#xff1a;范数类型向量的范数&#xff…

find查找所有php,linux中的find命令—查找文件名

1.在某目录下查找名为“elm.cc”的文件find /home/lijiajia/ -name elm.cc2.查找文件名中包含某字符(如"elm")的文件find /home/lijiajia/ -name *elm*find /home/lijiajia/ -name elm*find /home/lijiajia/ -name *elm3.根据文件的特征进行查询find /home/lijiajia/…

mac定时执行python_Python脚本实现在Mac上DIY定时提醒功能

背景&#xff1a;这两天一直沉迷于在电脑上看书&#xff0c;每到12点该吃饭时就会忘了&#xff0c;同事还要到工位上叫我&#xff0c;于是就想搞出来一个每天能够定时提醒我该做什么事情的功能&#xff0c;这样能够有提前准备。今天下午花了半天的时间研究了一下&#xff0c;最…

php 制造异常,php 异常

PHP 5 添加了类似于其它语言的异常处理模块。在 PHP 代码中所产生的异常可被 throw 语句抛出并被 catch 语句捕获。需要进行异常处理的代码都必须放入 try 代码块内&#xff0c;以便捕获可能存在的异常。每一个 try 至少要有一个与之对应的 catch。使用多个 catch 可以捕获不同…

大数据项目开发案例_大数据分析技术——项目案例1(猫眼电影数据分析上)...

壹猫眼Top100电影数据分析概述从这一节开始&#xff0c;我们就综合利用已学到的一些分析技术来尝试做一些比较复杂的实际数据分析项目。在这些实际的项目案例中&#xff0c;我们将会看到一个完整的数据分析流程&#xff1a;数据清理——数据分析——数据可视化(即数据解释)。最…

php utf8格式显示中文,php截取中文字符(utf-8格式)的函数

/**UTF-8中文字符截断程序http://www.jquerycn.cn*/$str "321这是测试字符串";$str1 "()()";echo subUTF8str($str,0,3)."";echo subUTF8str($str,0,4)."";echo subUTF8str($str1,0,4)."";echo subUTF8str($str1,0,10).&q…

python计算一年有多少天_Python 案例 004 (计算当前时间是一年中的第几天)

# -*- coding:utf-8 -*-"""计算当前时间是一年中的第几天"""bissextile [31,60,91,121,152,182,213,244,274,305,335,366] #leap yearcommonYear [31,59,90,120,151,181,212,243,273,304,334,365]enterYear int(raw_input("enter the Yea…