做服务外包项目需要是用虹软的人脸对比SDK,项目使用Python进行开发,但是网上以及官方社区没有基于Python的3.0版本项目,所以自己根据社区里大佬1.1和2.0的Demo修改套了一下
face_class
from ctypes import *
# 人脸框
class MRECT(Structure):
_fields_ = [(u'left1', c_int32), (u'top1', c_int32),
(u'right1', c_int32), (u'bottom1', c_int32)]
# 版本信息 版本号,构建日期,版权说明
class ASF_VERSION(Structure):
_fields_ = [('Version', c_char_p), ('BuildDate',
c_char_p), ('CopyRight', c_char_p)]
# 单人人脸信息 人脸狂,人脸角度
class ASF_SingleFaceInfo(Structure):
_fields_ = [('faceRect', MRECT), ('faceOrient', c_int32)]
# 多人人脸信息 人脸框数组,人脸角度数组,人脸数
class ASF_MultiFaceInfo(Structure):
# _fields_=[('faceRect',POINTER(MRECT)),('faceOrient',POINTER( c_int32)),('faceNum',c_int32)]
_fields_ = [(u'faceRect', POINTER(MRECT)), (u'faceOrient',
POINTER(c_int32)), (u'faceNum', c_int32)]
# _fields_=[(u'faceRect',MRECT*50),(u'faceOrient',c_int32*50),(u'faceNum',c_int32)]
# 人脸特征 人脸特征,人脸特征长度
class ASF_FaceFeature(Structure):
_fields_ = [('feature', c_void_p), ('featureSize', c_int32)]
# 自定义图片类face_dll
class IM:
def __init__(self):
self.filepath = None
self.date = None
self.width = 0
self.height = 0
face_dll
wuyongdll = CDLL('/media/psf/Home/code/fwwb/face/so/libarcsoft_face.so')
dll = CDLL('/media/psf/Home/code/fwwb/face/so/libarcsoft_face_engine.so')
libc = CDLL('libc.so.6')
#这里不同操作系统使用的动态库链接文件是不同的,我使用的是linux用了libc.so
ASF_DETECT_MODE_VIDEO = 0x00000000
ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF
c_ubyte_p = POINTER(c_ubyte)
# 激活
jihuo = dll.ASFActivation
jihuo.restype = c_int32
jihuo.argtypes = (c_char_p, c_char_p)
# 初始化
chushihua = dll.ASFInitEngine
chushihua.restype = c_int32
chushihua.argtypes = (
c_long,
c_int32,
c_int32,
c_int32,
c_int32,
POINTER(c_void_p))
# 人脸识别
shibie = dll.ASFDetectFaces
shibie.restype = c_int32
shibie.argtypes = (
c_void_p,
c_int32,
c_int32,
c_int32,
POINTER(c_ubyte),
POINTER(ASF_MultiFaceInfo))
# 特征提取
tezheng = dll.ASFFaceFeatureExtract
tezheng.restype = c_int32
tezheng.argtypes = (
c_void_p,
c_int32,
c_int32,
c_int32,
POINTER(c_ubyte),
POINTER(ASF_SingleFaceInfo),
POINTER(ASF_FaceFeature))
# 特征比对
bidui = dll.ASFFaceFeatureCompare
bidui.restype = c_int32
bidui.argtypes = (
c_void_p,
POINTER(ASF_FaceFeature),
POINTER(ASF_FaceFeature),
POINTER(c_float))
# 内存控制
malloc = libc.malloc
free = libc.free
memcpy = libc.memcpy
malloc.restype = c_void_p
malloc.argtypes = (c_size_t, )
free.restype = None
free.argtypes = (c_void_p, )
memcpy.restype = c_void_p
memcpy.argtypes = (c_void_p, c_void_p, c_size_t)
face_function
from . import face_dll
from . import face_class
from ctypes import *
import cv2
from io import BytesIO
Handle = c_void_p()
c_ubyte_p = POINTER(c_ubyte)
# 激活函数
def JH(appkey, sdkey):
ret = face_dll.jihuo(appkey, sdkey)
return ret
# 初始化函数
def CSH(): # 1:视频或图片模式,2角度,3最小人脸尺寸推荐16,4最多人脸数最大50,5功能,6返回激活句柄
ret = face_dll.chushihua(0xFFFFFFFF, 0x1, 16, 50, 5, byref(Handle))
# Main.Handle=Handle
return ret, Handle
# cv2记载图片并处理
def LoadImg(im):
img = cv2.imread(im.filepath)
sp = img.shape
img = cv2.resize(img, (sp[1] // 4 * 4, sp[0] // 4 * 4))
sp = img.shape
im.data = img
im.width = sp[1]
im.height = sp[0]
return im
def LoadWebImg(img):
print(img)
sp = img.shape
im = cv2.resize(img, (sp[1] // 4 * 4, sp[0] // 4 * 4))
sp = im.shape
img.data = im
img.width = sp[1]
img.height = sp[0]
return img
def RLSB(im):
faces = face_class.ASF_MultiFaceInfo()
img = im.data
imgby = bytes(im.data)
imgcuby = cast(imgby, c_ubyte_p)
ret = face_dll.shibie(
Handle,
im.width,
im.height,
0x201,
imgcuby,
byref(faces))
return ret, faces
# 显示人脸识别图片**unfinish
def showimg(im, faces):
print('facenum is:', faces.faceNum)
for i in range(0, faces.faceNum):
ra = faces.faceRect[i]
cv2.rectangle(im.data, (ra.left1, ra.top1),
(ra.right1, ra.bottom1), (255, 0, 0,), 2)
cv2.imshow('faces', im.data)
cv2.waitKey(0)
# 提取人脸特征
def RLTZ(im, ft):
detectedFaces = face_class.ASF_FaceFeature()
img = im.data
imgby = bytes(im.data)
imgcuby = cast(imgby, c_ubyte_p)
ret = face_dll.tezheng(
Handle,
im.width,
im.height,
0x201,
imgcuby,
ft,
byref(detectedFaces))
if ret == 0:
retz = face_class.ASF_FaceFeature()
retz.featureSize = detectedFaces.featureSize
# 必须操作内存来保留特征值,因为c++会在过程结束后自动释放内存
retz.feature = face_dll.malloc(detectedFaces.featureSize)
face_dll.memcpy(
retz.feature,
detectedFaces.feature,
detectedFaces.featureSize)
#print('提取特征成功:', detectedFaces.featureSize, mem)
return ret, retz
else:
return ret
# 特征值比对,返回比对结果
def BD(tz1, tz2):
jg = c_float()
ret = face_dll.bidui(Handle, tz1, tz2, byref(jg))
return ret, jg.value
# 单人特征写入文件
def writeFTFile(feature, filepath):
f = BytesIO(string_at(feature.feature, feature.featureSize))
a = open(filepath, 'wb')
a.write(f.getvalue())
a.close()
# 从多人中提取单人数据
def getsingleface(singleface, index):
ft = face_class.ASF_SingleFaceInfo()
ra = singleface.faceRect[index]
ft.faceRect.left1 = ra.left1
ft.faceRect.right1 = ra.right1
ft.faceRect.top1 = ra.top1
ft.faceRect.bottom1 = ra.bottom1
ft.faceOrient = singleface.faceOrient[index]
return ft
# 从文件获取特征值
def ftfromfile(filepath):
fas = face_class.ASF_FaceFeature()
f = open('./1.dat', 'rb')
b = f.read()
f.close()
fas.featureSize = b.__len__()
fas.feature = face_dll.malloc(fas.featureSize)
face_dll.memcpy(fas.feature, b, fas.featureSize)
return fas
关于ctypes类型转换
C类型 | Python类型 | ctypes 类型 |
---|---|---|
char | 1-character/string | c_char |
wchar_t | 1-character/Unicode、string | c_wchar |
char | int/long | c_byte |
char | int/long | c_ubyte |
short | int/long | c_short |
unsigned short | int/long | c_ushort |
int | int/long | c_int |
unsigned int | int/long | c_uint |
long | int/long | c_long |
unsigned long | int/long | c_ulong |
long long | int/long | c_longlong |
unsigned long long | int/long | c_ulonglong |
float | float | c_float |
double | float | c_double |
char *(NULL terminated) | string or none | c_char_p |
wchar_t *(NULL terminated) | unicode or none | c_wchar_p |
void * | int/long or none | c_void_p |
当一个函数期望一个指针作为参数时,可以像这样调用
function_main(byref(parameter))
struct例子
下面的例子是定义一个结构
C语言例子
struct beer_recipe
{
int amt_barley;
int amt_water;
};
Python例子
class beer_recipe(Structure):
_fields_ = [
("amt_barley", c_int),
("amt_water", c_int),
]
写在后面
ArcFaceSDK3.0还加入了很多新功能 比如说1:N的识别等 如果后期继续做相关应该会继续补到function里面