├── .gitignore ├── AFRTest.py ├── README.md ├── arcsoft ├── AFD_FSDKLibrary.py ├── AFR_FSDKLibrary.py ├── ASVL_COLOR_FORMAT.py ├── CLibrary.py ├── __init__.py ├── lib │ ├── linux_x64 │ │ ├── README.md │ │ └── ReadME.md │ ├── win32 │ │ ├── README.md │ │ └── ReadME.md │ └── win64 │ │ ├── README.md │ │ └── ReadME.md └── utils │ ├── ImageLoader.py │ ├── __init__.py │ ├── imageJudge.py │ └── lib_path.py ├── lena.bmp ├── lena_I420_fromBMP.yuv ├── requirements.txt └── screenshot └── lib.png /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | __pycache__ 3 | *.dll 4 | *.so 5 | *.dat 6 | *.zip 7 | -------------------------------------------------------------------------------- /AFRTest.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from arcsoft import CLibrary, ASVL_COLOR_FORMAT, ASVLOFFSCREEN, c_ubyte_p, FaceInfo 4 | from arcsoft.utils import BufferInfo, ImageLoader 5 | from arcsoft.AFD_FSDKLibrary import * 6 | from arcsoft.AFR_FSDKLibrary import * 7 | from ctypes import * 8 | import traceback 9 | 10 | APPID = c_char_p(b'APPID') 11 | FD_SDKKEY = c_char_p(b'FD_SDKKEY') 12 | FR_SDKKEY = c_char_p(b'FR_SDKKEY') 13 | 14 | FD_WORKBUF_SIZE = 20 * 1024 * 1024 15 | FR_WORKBUF_SIZE = 40 * 1024 * 1024 16 | MAX_FACE_NUM = 50 17 | 18 | bUseYUVFile = 0 19 | 20 | 21 | def doFaceDetection(hFDEngine, inputImg): 22 | faceInfo = [] 23 | 24 | pFaceRes = POINTER(AFD_FSDK_FACERES)() 25 | ret = AFD_FSDK_StillImageFaceDetection(hFDEngine, byref(inputImg), 26 | byref(pFaceRes)) 27 | if ret != 0: 28 | print(u'AFD_FSDK_StillImageFaceDetection 0x{0:x}'.format(ret)) 29 | return faceInfo 30 | 31 | faceRes = pFaceRes.contents 32 | if faceRes.nFace > 0: 33 | for i in range(0, faceRes.nFace): 34 | rect = faceRes.rcFace[i] 35 | orient = faceRes.lfaceOrient[i] 36 | faceInfo.append( 37 | FaceInfo(rect.left, rect.top, rect.right, rect.bottom, orient)) 38 | 39 | return faceInfo 40 | 41 | 42 | def extractFRFeature(hFREngine, inputImg, faceInfo): 43 | """ 44 | 获取人脸特征值 45 | """ 46 | faceinput = AFR_FSDK_FACEINPUT() 47 | faceinput.lOrient = faceInfo.orient 48 | faceinput.rcFace.left = faceInfo.left 49 | faceinput.rcFace.top = faceInfo.top 50 | faceinput.rcFace.right = faceInfo.right 51 | faceinput.rcFace.bottom = faceInfo.bottom 52 | 53 | faceFeature = AFR_FSDK_FACEMODEL() 54 | ret = AFR_FSDK_ExtractFRFeature(hFREngine, inputImg, faceinput, 55 | faceFeature) 56 | if ret != 0: 57 | print(u'AFR_FSDK_ExtractFRFeature ret 0x{0:x}'.format(ret)) 58 | return None 59 | 60 | try: 61 | return faceFeature.deepCopy() 62 | except Exception as e: 63 | traceback.print_exc() 64 | print(e.message) 65 | return None 66 | 67 | 68 | def compareFaceSimilarity(hFDEngine, hFREngine, inputImgA, inputImgB): 69 | """ 70 | 人脸相似度对比 71 | """ 72 | # Do Face Detect 73 | faceInfosA = doFaceDetection(hFDEngine, inputImgA) 74 | if len(faceInfosA) < 1: 75 | print(u'no face in Image A ') 76 | return 0.0 77 | faceInfosB = doFaceDetection(hFDEngine, inputImgB) 78 | if len(faceInfosB) < 1: 79 | print(u'no face in Image B ') 80 | return 0.0 81 | 82 | # Extract Face Feature 83 | faceFeatureA = extractFRFeature(hFREngine, inputImgA, faceInfosA[0]) 84 | if faceFeatureA == None: 85 | print(u'extract face feature in Image A faile') 86 | return 0.0 87 | faceFeatureB = extractFRFeature(hFREngine, inputImgB, faceInfosB[0]) 88 | if faceFeatureB == None: 89 | print(u'extract face feature in Image B failed') 90 | faceFeatureA.freeUnmanaged() 91 | return 0.0 92 | 93 | # calc similarity between faceA and faceB 94 | fSimilScore = c_float(0.0) 95 | ret = AFR_FSDK_FacePairMatching(hFREngine, faceFeatureA, faceFeatureB, 96 | byref(fSimilScore)) 97 | faceFeatureA.freeUnmanaged() 98 | faceFeatureB.freeUnmanaged() 99 | if ret != 0: 100 | print(u'AFR_FSDK_FacePairMatching failed:ret 0x{0:x}'.format(ret)) 101 | return 0.0 102 | 103 | return fSimilScore 104 | 105 | 106 | def loadYUVImage(yuv_filePath, yuv_width, yuv_height, yuv_format): 107 | """ 108 | 加载YUV图片 109 | """ 110 | yuv_rawdata_size = 0 111 | 112 | inputImg = ASVLOFFSCREEN() 113 | inputImg.u32PixelArrayFormat = yuv_format 114 | inputImg.i32Width = yuv_width 115 | inputImg.i32Height = yuv_height 116 | if ASVL_COLOR_FORMAT.ASVL_PAF_I420 == inputImg.u32PixelArrayFormat: 117 | inputImg.pi32Pitch[0] = inputImg.i32Width 118 | inputImg.pi32Pitch[1] = inputImg.i32Width // 2 119 | inputImg.pi32Pitch[2] = inputImg.i32Width // 2 120 | yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 3 // 2 121 | elif ASVL_COLOR_FORMAT.ASVL_PAF_NV12 == inputImg.u32PixelArrayFormat: 122 | inputImg.pi32Pitch[0] = inputImg.i32Width 123 | inputImg.pi32Pitch[1] = inputImg.i32Width 124 | yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 3 // 2 125 | elif ASVL_COLOR_FORMAT.ASVL_PAF_NV21 == inputImg.u32PixelArrayFormat: 126 | inputImg.pi32Pitch[0] = inputImg.i32Width 127 | inputImg.pi32Pitch[1] = inputImg.i32Width 128 | yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 3 // 2 129 | elif ASVL_COLOR_FORMAT.ASVL_PAF_YUYV == inputImg.u32PixelArrayFormat: 130 | inputImg.pi32Pitch[0] = inputImg.i32Width * 2 131 | yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 2 132 | else: 133 | print(u'unsupported yuv format') 134 | exit(0) 135 | 136 | # load YUV Image Data from File 137 | f = None 138 | try: 139 | f = open(yuv_filePath, u'rb') 140 | imagedata = f.read(yuv_rawdata_size) 141 | except Exception as e: 142 | traceback.print_exc() 143 | print(e.message) 144 | exit(0) 145 | finally: 146 | if f is not None: 147 | f.close() 148 | 149 | if ASVL_COLOR_FORMAT.ASVL_PAF_I420 == inputImg.u32PixelArrayFormat: 150 | inputImg.ppu8Plane[0] = cast(imagedata, c_ubyte_p) 151 | inputImg.ppu8Plane[1] = cast( 152 | addressof(inputImg.ppu8Plane[0].contents) + 153 | (inputImg.pi32Pitch[0] * inputImg.i32Height), c_ubyte_p) 154 | inputImg.ppu8Plane[2] = cast( 155 | addressof(inputImg.ppu8Plane[1].contents) + 156 | (inputImg.pi32Pitch[1] * inputImg.i32Height // 2), c_ubyte_p) 157 | inputImg.ppu8Plane[3] = cast(0, c_ubyte_p) 158 | elif ASVL_COLOR_FORMAT.ASVL_PAF_NV12 == inputImg.u32PixelArrayFormat: 159 | inputImg.ppu8Plane[0] = cast(imagedata, c_ubyte_p) 160 | inputImg.ppu8Plane[1] = cast( 161 | addressof(inputImg.ppu8Plane[0].contents) + 162 | (inputImg.pi32Pitch[0] * inputImg.i32Height), c_ubyte_p) 163 | inputImg.ppu8Plane[2] = cast(0, c_ubyte_p) 164 | inputImg.ppu8Plane[3] = cast(0, c_ubyte_p) 165 | elif ASVL_COLOR_FORMAT.ASVL_PAF_NV21 == inputImg.u32PixelArrayFormat: 166 | inputImg.ppu8Plane[0] = cast(imagedata, c_ubyte_p) 167 | inputImg.ppu8Plane[1] = cast( 168 | addressof(inputImg.ppu8Plane[0].contents) + 169 | (inputImg.pi32Pitch[0] * inputImg.i32Height), c_ubyte_p) 170 | inputImg.ppu8Plane[2] = cast(0, c_ubyte_p) 171 | inputImg.ppu8Plane[3] = cast(0, c_ubyte_p) 172 | elif ASVL_COLOR_FORMAT.ASVL_PAF_YUYV == inputImg.u32PixelArrayFormat: 173 | inputImg.ppu8Plane[0] = cast(imagedata, c_ubyte_p) 174 | inputImg.ppu8Plane[1] = cast(0, c_ubyte_p) 175 | inputImg.ppu8Plane[2] = cast(0, c_ubyte_p) 176 | inputImg.ppu8Plane[3] = cast(0, c_ubyte_p) 177 | else: 178 | print(u'unsupported yuv format') 179 | exit(0) 180 | 181 | inputImg.gc_ppu8Plane0 = imagedata 182 | return inputImg 183 | 184 | 185 | def loadImage(filePath): 186 | """ 187 | 加载图片 188 | """ 189 | bufferInfo = ImageLoader.getI420FromFile(filePath) 190 | inputImg = ASVLOFFSCREEN() 191 | inputImg.u32PixelArrayFormat = ASVL_COLOR_FORMAT.ASVL_PAF_I420 192 | inputImg.i32Width = bufferInfo.width 193 | inputImg.i32Height = bufferInfo.height 194 | inputImg.pi32Pitch[0] = inputImg.i32Width 195 | inputImg.pi32Pitch[1] = inputImg.i32Width // 2 196 | inputImg.pi32Pitch[2] = inputImg.i32Width // 2 197 | inputImg.ppu8Plane[0] = cast(bufferInfo.buffer, c_ubyte_p) 198 | inputImg.ppu8Plane[1] = cast( 199 | addressof(inputImg.ppu8Plane[0].contents) + 200 | (inputImg.pi32Pitch[0] * inputImg.i32Height), c_ubyte_p) 201 | inputImg.ppu8Plane[2] = cast( 202 | addressof(inputImg.ppu8Plane[1].contents) + 203 | (inputImg.pi32Pitch[1] * inputImg.i32Height // 2), c_ubyte_p) 204 | inputImg.ppu8Plane[3] = cast(0, c_ubyte_p) 205 | 206 | inputImg.gc_ppu8Plane0 = bufferInfo.buffer 207 | 208 | return inputImg 209 | 210 | 211 | def get_feature_test(hFDEngine, hFREngine, imgFile): 212 | """ 213 | 获取图片特征值测试 214 | """ 215 | faceInfos = doFaceDetection(hFDEngine, inputImgA) 216 | if len(faceInfos) < 1: 217 | print(u'no face in Image ') 218 | return 0.0 219 | 220 | # Extract Face Feature 221 | faceFeature = extractFRFeature(hFREngine, imgFile, faceInfos[0]) 222 | if faceFeature == None: 223 | print(u'extract face feature in Image faile') 224 | return 0.0 225 | 226 | feature = faceFeature.toByteArray() 227 | filename = "feature.dat" 228 | 229 | with open(filename, "wb") as f: 230 | f.write(feature) 231 | print("save face feature in feature.dat") 232 | print("feature length:", len(feature), "Byte") 233 | 234 | faceFeature.freeUnmanaged() 235 | 236 | 237 | if __name__ == u'__main__': 238 | 239 | print(u'#####################################################') 240 | 241 | # init Engine 242 | pFDWorkMem = CLibrary.malloc(c_size_t(FD_WORKBUF_SIZE)) 243 | pFRWorkMem = CLibrary.malloc(c_size_t(FR_WORKBUF_SIZE)) 244 | 245 | hFDEngine = c_void_p() 246 | ret = AFD_FSDK_InitialFaceEngine( 247 | APPID, FD_SDKKEY, pFDWorkMem, c_int32(FD_WORKBUF_SIZE), 248 | byref(hFDEngine), AFD_FSDK_OPF_0_HIGHER_EXT, 16, MAX_FACE_NUM) 249 | if ret != 0: 250 | CLibrary.free(pFDWorkMem) 251 | print(u'AFD_FSDK_InitialFaceEngine ret 0x{:x}'.format(ret)) 252 | exit(0) 253 | 254 | # print FDEngine version 255 | versionFD = AFD_FSDK_GetVersion(hFDEngine) 256 | print(u'AFD Version: {} {} {} {}'.format( 257 | versionFD.contents.lCodebase, versionFD.contents.lMajor, 258 | versionFD.contents.lMinor, versionFD.contents.lBuild)) 259 | print("Version:", 260 | c_char_p(versionFD.contents.Version).value.decode(u'utf-8')) 261 | print("BuildDate:", 262 | c_char_p(versionFD.contents.BuildDate).value.decode(u'utf-8')) 263 | print("CopyRight:", 264 | c_char_p(versionFD.contents.CopyRight).value.decode(u'utf-8')) 265 | 266 | hFREngine = c_void_p() 267 | ret = AFR_FSDK_InitialEngine(APPID, FR_SDKKEY, pFRWorkMem, 268 | c_int32(FR_WORKBUF_SIZE), byref(hFREngine)) 269 | if ret != 0: 270 | AFD_FSDKLibrary.AFD_FSDK_UninitialFaceEngine(hFDEngine) 271 | CLibrary.free(pFDWorkMem) 272 | CLibrary.free(pFRWorkMem) 273 | print(u'AFR_FSDK_InitialEngine ret 0x{:x}'.format(ret)) 274 | System.exit(0) 275 | 276 | print("\r\n") 277 | # print FREngine version 278 | versionFR = AFR_FSDK_GetVersion(hFREngine) 279 | print(u'AFR Version: {} {} {} {}'.format( 280 | versionFR.contents.lCodebase, versionFR.contents.lMajor, 281 | versionFR.contents.lMinor, versionFR.contents.lBuild)) 282 | print("Version:", 283 | c_char_p(versionFR.contents.Version).value.decode(u'utf-8')) 284 | print("BuildDate:", 285 | c_char_p(versionFR.contents.BuildDate).value.decode(u'utf-8')) 286 | print("CopyRight:", 287 | c_char_p(versionFR.contents.CopyRight).value.decode(u'utf-8')) 288 | 289 | # load Image Data 290 | if bUseYUVFile: 291 | filePathA = u'lena_I420_fromBMP.yuv' 292 | yuv_widthA = 512 293 | yuv_heightA = 512 294 | yuv_formatA = ASVL_COLOR_FORMAT.ASVL_PAF_I420 295 | 296 | filePathB = u'lena_I420_fromBMP.yuv' 297 | yuv_widthB = 512 298 | yuv_heightB = 512 299 | yuv_formatB = ASVL_COLOR_FORMAT.ASVL_PAF_I420 300 | 301 | inputImgA = loadYUVImage(filePathA, yuv_widthA, yuv_heightA, 302 | yuv_formatA) 303 | inputImgB = loadYUVImage(filePathB, yuv_widthB, yuv_heightB, 304 | yuv_formatB) 305 | else: 306 | filePathA = u'lena.bmp' 307 | filePathB = u'lena.bmp' 308 | 309 | inputImgA = loadImage(filePathA) 310 | inputImgB = loadImage(filePathB) 311 | 312 | print(u'\r\nsimilarity between faceA and faceB is {0}'.format( 313 | compareFaceSimilarity(hFDEngine, hFREngine, inputImgA, inputImgB))) 314 | 315 | print("\r\n") 316 | # 特征值获取 317 | get_feature_test(hFDEngine, hFREngine, inputImgA) 318 | 319 | # release Engine 320 | AFD_FSDK_UninitialFaceEngine(hFDEngine) 321 | AFR_FSDK_UninitialEngine(hFREngine) 322 | 323 | CLibrary.free(pFDWorkMem) 324 | CLibrary.free(pFRWorkMem) 325 | 326 | print(u'#####################################################') 327 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python调用虹软人脸认知引擎库示例 2 | 3 | forked from [asdfqwrasdf/ArcSoft_FreeSDK_Demo/FR/python/](https://github.com/asdfqwrasdf/ArcSoft_FreeSDK_Demo/tree/master/FR/python) 4 | 5 | 基于上面代码进行修改。 6 | 7 | ## 已测试过的环境 8 | 9 | - CentOS 7.2 x64 + Python 3.5 10 | - Windows 10 x64 + Python 3.5(32bit) 11 | - Windows 10 x64 + Python 3.5(64bit) 12 | 13 | 注意事项:在Windows环境下,如果使用32位的DLL,Python也必须也要32位。 14 | 15 | ## 第一步:安装依赖包 16 | 17 | 首先需要安装依赖包(也就一个Pillow) 18 | 19 | ```sh 20 | pip install -r requirements.txt 21 | # OR 22 | pip install Pillow 23 | ``` 24 | 25 | ## 第二步:导入库文件 26 | 27 | 然后将虹软SDK中的DLL拷贝到`arcsoft\lib\`相关目录下,确保相关系统有detection和recognition两个库文件: 28 | 29 | ![lib](screenshot/lib.png) 30 | 31 | ## 第三步:填写信息 32 | 33 | 填写`APPID`、`FD_SDKKEY`和`FR_SDKKEY`。 34 | 35 | ```Python 36 | APPID = c_char_p(b'APPID') 37 | FD_SDKKEY = c_char_p(b'FD_SDKKEY') 38 | FR_SDKKEY = c_char_p(b'FR_SDKKEY') 39 | ``` 40 | 41 | ## 第三步:完成,运行测试 42 | 43 | 执行`python3 AFRTest.py`,成功的话会输出下面信息: 44 | 45 | ```PowerShell 46 | > python3 AFRTest.py 47 | ##################################################### 48 | AFD Version: 1 1 0 81 49 | Version: ArcSoft_FreeSDK_FaceDetection_1.1.0.81 50 | BuildDate: Jan 22 2018 51 | CopyRight: Copyright 2017 ArcSoft, Inc. All rights reserved. 52 | 53 | 54 | AFR Version: 1 1 0 81 55 | Version: ArcSoft_FreeSDK_FaceRecognition_1.1.0.81 56 | BuildDate: Jan 22 2018 57 | CopyRight: Copyright 2017 ArcSoft, Inc. All rights reserved. 58 | 59 | similarity between faceA and faceB is c_float(1.0) 60 | 61 | 62 | save face feature in feature.dat 63 | feature length: 22020 Byte 64 | ##################################################### 65 | ``` 66 | 67 | 同时在当前目录下会生成`feature.dat`文件,里面保存了人脸特征值,大小为22020 Byte。 68 | 69 | 70 | ## 修改输入图片 71 | 72 | 可以在`AFRTest.py`290行修改要输入的图片: 73 | 74 | BMP文件格式: 75 | 76 | ```Python 77 | # AFRTest.py 290行 78 | filePathA = u'lena.bmp' 79 | filePathB = u'lena.bmp' 80 | 81 | inputImgA = loadImage(filePathA) 82 | inputImgB = loadImage(filePathB) 83 | ``` 84 | 85 | yuv格式: 86 | 87 | ```Python 88 | filePathA = u'lena_I420_fromBMP.yuv' 89 | yuv_widthA = 512 90 | yuv_heightA = 512 91 | yuv_formatA = ASVL_COLOR_FORMAT.ASVL_PAF_I420 92 | 93 | filePathB = u'lena_I420_fromBMP.yuv' 94 | yuv_widthB = 512 95 | yuv_heightB = 512 96 | yuv_formatB = ASVL_COLOR_FORMAT.ASVL_PAF_I420 97 | 98 | inputImgA = loadYUVImage(filePathA, yuv_widthA, yuv_heightA, 99 | yuv_formatA) 100 | inputImgB = loadYUVImage(filePathB, yuv_widthB, yuv_heightB, 101 | yuv_formatB) 102 | ``` 103 | 104 | 使用`ffmpeg -i lena.bmp -pix_fmt yuv420p lena_I420_fromBMP.yuv`命令转换 105 | 106 | ## 其他信息 107 | 108 | 虹软官方SDK下载地址:http://www.arcsoft.com.cn/ai/arcface.html 109 | 110 | -------------------------------------------------------------------------------- /arcsoft/AFD_FSDKLibrary.py: -------------------------------------------------------------------------------- 1 | #-*- encoding=utf-8 -*- 2 | 3 | import os 4 | import sys 5 | import platform 6 | from ctypes import * 7 | from . import MRECT,ASVLOFFSCREEN 8 | from .utils.lib_path import LINUX_X64_DIR, WIN64_DIR, WIN32_DIR 9 | 10 | class AFD_FSDK_FACERES(Structure): 11 | _fields_ = [(u'nFace',c_int32),(u'rcFace',POINTER(MRECT)),(u'lfaceOrient',POINTER(c_int32))] 12 | 13 | class AFD_FSDK_Version(Structure): 14 | _fields_ = [(u'lCodebase',c_int32),(u'lMajor',c_int32),(u'lMinor',c_int32),(u'lBuild',c_int32), 15 | (u'Version',c_char_p),(u'BuildDate',c_char_p),(u'CopyRight',c_char_p)] 16 | 17 | AFD_FSDK_OPF_0_ONLY = 0x1; # 0; 0; ... 18 | AFD_FSDK_OPF_90_ONLY = 0x2; # 90; 90; ... 19 | AFD_FSDK_OPF_270_ONLY = 0x3; # 270; 270; ... 20 | AFD_FSDK_OPF_180_ONLY = 0x4; # 180; 180; ... 21 | AFD_FSDK_OPF_0_HIGHER_EXT = 0x5; # 0; 90; 270; 180; 0; 90; 270; 180; ... 22 | 23 | AFD_FSDK_FOC_0 = 0x1;# 0 degree 24 | AFD_FSDK_FOC_90 = 0x2; # 90 degree 25 | AFD_FSDK_FOC_270 = 0x3; # 270 degree 26 | AFD_FSDK_FOC_180 = 0x4; # 180 degree 27 | AFD_FSDK_FOC_30 = 0x5; # 30 degree 28 | AFD_FSDK_FOC_60 = 0x6; # 60 degree 29 | AFD_FSDK_FOC_120 = 0x7; # 120 degree 30 | AFD_FSDK_FOC_150 = 0x8; # 150 degree 31 | AFD_FSDK_FOC_210 = 0x9; # 210 degree 32 | AFD_FSDK_FOC_240 = 0xa; # 240 degree 33 | AFD_FSDK_FOC_300 = 0xb; # 300 degree 34 | AFD_FSDK_FOC_330 = 0xc; # 330 degree 35 | 36 | 37 | if platform.system() == u'Windows': 38 | if "32 bit" in sys.version: 39 | lib_file = os.path.join(WIN32_DIR, u"libarcsoft_fsdk_face_detection.dll") 40 | else: 41 | lib_file = os.path.join(WIN64_DIR, u"libarcsoft_fsdk_face_detection.dll") 42 | else: 43 | lib_file = os.path.join(LINUX_X64_DIR, u"libarcsoft_fsdk_face_detection.so") 44 | 45 | internalLibrary = CDLL(lib_file) 46 | 47 | AFD_FSDK_InitialFaceEngine = internalLibrary.AFD_FSDK_InitialFaceEngine 48 | AFD_FSDK_UninitialFaceEngine = internalLibrary.AFD_FSDK_UninitialFaceEngine 49 | AFD_FSDK_StillImageFaceDetection = internalLibrary.AFD_FSDK_StillImageFaceDetection 50 | AFD_FSDK_GetVersion = internalLibrary.AFD_FSDK_GetVersion 51 | 52 | AFD_FSDK_InitialFaceEngine.restype = c_long 53 | AFD_FSDK_InitialFaceEngine.argtypes = (c_char_p,c_char_p,c_void_p,c_int32,POINTER(c_void_p),c_int32,c_int32,c_int32) 54 | AFD_FSDK_UninitialFaceEngine.restype = c_long 55 | AFD_FSDK_UninitialFaceEngine.argtypes = (c_void_p,) 56 | AFD_FSDK_StillImageFaceDetection.restype = c_long 57 | AFD_FSDK_StillImageFaceDetection.argtypes = (c_void_p,POINTER(ASVLOFFSCREEN),POINTER(POINTER(AFD_FSDK_FACERES))) 58 | AFD_FSDK_GetVersion.restype = POINTER(AFD_FSDK_Version) 59 | AFD_FSDK_GetVersion.argtypes =(c_void_p,) 60 | -------------------------------------------------------------------------------- /arcsoft/AFR_FSDKLibrary.py: -------------------------------------------------------------------------------- 1 | #-*- encoding=utf-8 -*- 2 | 3 | import os 4 | import sys 5 | import platform 6 | from ctypes import * 7 | from . import MRECT,ASVLOFFSCREEN 8 | from . import CLibrary 9 | from .utils.lib_path import LINUX_X64_DIR, WIN64_DIR, WIN32_DIR 10 | 11 | class AFR_FSDK_Version(Structure): 12 | _fields_ = [(u'lCodebase',c_int32),(u'lMajor',c_int32),(u'lMinor',c_int32),(u'lBuild',c_int32),(u'lFeatureLevel',c_int32), 13 | (u'Version',c_char_p),(u'BuildDate',c_char_p),(u'CopyRight',c_char_p)] 14 | 15 | class AFR_FSDK_FACEINPUT(Structure): 16 | _fields_ = [(u'rcFace',MRECT),(u'lOrient',c_int32)] 17 | 18 | class AFR_FSDK_FACEMODEL(Structure): 19 | _fields_ = [(u'pbFeature',c_void_p),(u'lFeatureSize',c_int32)] 20 | def __init__(self): 21 | self.bAllocByMalloc = False 22 | Structure.__init__(self) 23 | def deepCopy(self): 24 | if(self.pbFeature == 0): 25 | raise Exception(u'invalid feature') 26 | feature = AFR_FSDK_FACEMODEL() 27 | feature.bAllocByMalloc = True 28 | feature.lFeatureSize = self.lFeatureSize 29 | feature.pbFeature = CLibrary.malloc(feature.lFeatureSize) 30 | CLibrary.memcpy(feature.pbFeature,self.pbFeature,feature.lFeatureSize) 31 | return feature 32 | def freeUnmanaged(self): 33 | if self.bAllocByMalloc and (self.pbFeature != 0): 34 | CLibrary.free(self.pbFeature) 35 | self.pbFeature = 0 36 | def __del__(self): 37 | self.freeUnmanaged() 38 | #print(u'gc feature freeUnmanaged') 39 | @staticmethod 40 | def fromByteArray(byteArrayFeature): 41 | if byteArrayFeature == None: 42 | raise Exception(u'invalid byteArray') 43 | feature = AFR_FSDK_FACEMODEL() 44 | feature.lFeatureSize = len(byteArrayFeature) 45 | feature.bAllocByMalloc = True 46 | featureData = create_string_buffer(byteArrayFeature) 47 | feature.pbFeature = CLibrary.malloc(feature.lFeatureSize) 48 | CLibrary.memcpy(feature.pbFeature,cast(featureData,c_void_p),feature.lFeatureSize) 49 | return feature 50 | 51 | def toByteArray(self): 52 | if(self.pbFeature == 0): 53 | raise Exception(u'invalid feature') 54 | featureData = create_string_buffer(self.lFeatureSize) 55 | CLibrary.memcpy(cast(featureData,c_void_p),self.pbFeature,self.lFeatureSize) 56 | return bytes(bytearray(featureData)) 57 | 58 | 59 | if platform.system() == u'Windows': 60 | if "32 bit" in sys.version: 61 | lib_file = os.path.join(WIN32_DIR, u'libarcsoft_fsdk_face_recognition.dll') 62 | else: 63 | lib_file = os.path.join(WIN64_DIR, u'libarcsoft_fsdk_face_recognition.dll') 64 | else: 65 | lib_file = os.path.join(LINUX_X64_DIR, u"libarcsoft_fsdk_face_recognition.so") 66 | 67 | internalLibrary = CDLL(lib_file) 68 | 69 | AFR_FSDK_InitialEngine = internalLibrary.AFR_FSDK_InitialEngine 70 | AFR_FSDK_UninitialEngine = internalLibrary.AFR_FSDK_UninitialEngine 71 | AFR_FSDK_ExtractFRFeature = internalLibrary.AFR_FSDK_ExtractFRFeature 72 | AFR_FSDK_FacePairMatching = internalLibrary.AFR_FSDK_FacePairMatching 73 | AFR_FSDK_GetVersion = internalLibrary.AFR_FSDK_GetVersion 74 | 75 | AFR_FSDK_InitialEngine.restype = c_long 76 | AFR_FSDK_InitialEngine.argtypes = (c_char_p,c_char_p,c_void_p,c_int32,POINTER(c_void_p)) 77 | AFR_FSDK_UninitialEngine.restype = c_long 78 | AFR_FSDK_UninitialEngine.argtypes = (c_void_p,) 79 | AFR_FSDK_ExtractFRFeature.restype = c_long 80 | AFR_FSDK_ExtractFRFeature.argtypes = (c_void_p,POINTER(ASVLOFFSCREEN),POINTER(AFR_FSDK_FACEINPUT),POINTER(AFR_FSDK_FACEMODEL)) 81 | AFR_FSDK_FacePairMatching.restype = c_long 82 | AFR_FSDK_FacePairMatching.argtypes = (c_void_p,POINTER(AFR_FSDK_FACEMODEL),POINTER(AFR_FSDK_FACEMODEL),POINTER(c_float)) 83 | AFR_FSDK_GetVersion.restype = POINTER(AFR_FSDK_Version) 84 | AFR_FSDK_GetVersion.argtypes =(c_void_p,) 85 | -------------------------------------------------------------------------------- /arcsoft/ASVL_COLOR_FORMAT.py: -------------------------------------------------------------------------------- 1 | #-*- encoding=utf-8 -*- 2 | """ 3 | 颜色格式及其对齐规则 4 | """ 5 | 6 | # R R R R R G G G G G G B B B B B 7 | ASVL_PAF_RGB16_B5G6R5 = 0x101 8 | # X R R R R R G G G G G B B B B B 9 | ASVL_PAF_RGB16_B5G5R5 = 0x102 10 | # X X X X R R R R G G G G B B B B 11 | ASVL_PAF_RGB16_B4G4R4 = 0x103 12 | # T R R R R R G G G G G B B B B B 13 | ASVL_PAF_RGB16_B5G5R5T = 0x104 14 | # B B B B B G G G G G G R R R R R 15 | ASVL_PAF_RGB16_R5G6B5 = 0x105 16 | # X B B B B B G G G G G R R R R R 17 | ASVL_PAF_RGB16_R5G5B5 = 0x106 18 | # X X X X B B B B G G G G R R R R 19 | ASVL_PAF_RGB16_R4G4B4 = 0x107 20 | 21 | # R R R R R R R R G G G G G G G G B B B B B B B B 22 | ASVL_PAF_RGB24_B8G8R8 = 0x201 23 | # X X X X X X R R R R R R G G G G G G B B B B B B 24 | ASVL_PAF_RGB24_B6G6R6 = 0x202 25 | # X X X X X T R R R R R R G G G G G G B B B B B B 26 | ASVL_PAF_RGB24_B6G6R6T = 0x203 27 | # B B B B B B B B G G G G G G G G R R R R R R R R 28 | ASVL_PAF_RGB24_R8G8B8 = 0x204 29 | # X X X X X X B B B B B B G G G G G G R R R R R R 30 | ASVL_PAF_RGB24_R6G6B6 = 0x205 31 | 32 | # X X X X X X X X R R R R R R R R G G G G G G G G B B B B B B B B 33 | ASVL_PAF_RGB32_B8G8R8 = 0x301 34 | # A A A A A A A A R R R R R R R R G G G G G G G G B B B B B B B B 35 | ASVL_PAF_RGB32_B8G8R8A8 = 0x302 36 | # X X X X X X X X B B B B B B B B G G G G G G G G R R R R R R R R 37 | ASVL_PAF_RGB32_R8G8B8 = 0x303 38 | # B B B B B B B B G G G G G G G G R R R R R R R R A A A A A A A A 39 | ASVL_PAF_RGB32_A8R8G8B8 = 0x304 40 | # A A A A A A A A B B B B B B B B G G G G G G G G R R R R R R R R 41 | ASVL_PAF_RGB32_R8G8B8A8 = 0x305 42 | 43 | # Y0, U0, V0 44 | ASVL_PAF_YUV = 0x401 45 | # Y0, V0, U0 46 | ASVL_PAF_YVU0 = 0x402 47 | # U0, V0, Y0 48 | ASVL_PAF_UVY = 0x403 49 | # V0, U0, Y0 50 | ASVL_PAF_VUY = 0x404 51 | 52 | # Y0, U0, Y1, V0 53 | ASVL_PAF_YUYV = 0x501 54 | # Y0, V0, Y1, U0 55 | ASVL_PAF_YVYU = 0x502 56 | # U0, Y0, V0, Y1 57 | ASVL_PAF_UYVY = 0x503 58 | # V0, Y0, U0, Y1 59 | ASVL_PAF_VYUY = 0x504 60 | # Y1, U0, Y0, V0 61 | ASVL_PAF_YUYV2 = 0x505 62 | # Y1, V0, Y0, U0 63 | ASVL_PAF_YVYU2 = 0x506 64 | # U0, Y1, V0, Y0 65 | ASVL_PAF_UYVY2 = 0x507 66 | # V0, Y1, U0, Y0 67 | ASVL_PAF_VYUY2 = 0x508 68 | # Y0, Y1, U0, V0 69 | ASVL_PAF_YYUV = 0x509 70 | 71 | # I420(IYUV) 72 | # 8-bit Y层,之后是8-bit的2x2 采样的U层和V层 73 | ASVL_PAF_I420 = 0x601 74 | # 8 bit Y plane followed by 8 bit 1x2 subsampled U and V planes 75 | ASVL_PAF_I422V = 0x602 76 | # 8 bit Y plane followed by 8 bit 2x1 subsampled U and V planes 77 | ASVL_PAF_I422H = 0x603 78 | # 8 bit Y plane followed by 8 bit U and V planes 79 | ASVL_PAF_I444 = 0x604 80 | # 8 bit Y plane followed by 8 bit 2x2 subsampled V and U planes 81 | ASVL_PAF_YV12 = 0x605 82 | # 8 bit Y plane followed by 8 bit 1x2 subsampled V and U planes 83 | ASVL_PAF_YV16V = 0x606 84 | # 8 bit Y plane followed by 8 bit 2x1 subsampled V and U planes 85 | ASVL_PAF_YV16H = 0x607 86 | # 8 bit Y plane followed by 8 bit V and U planes 87 | ASVL_PAF_YV24 = 0x608 88 | 89 | # 8 bit Y plane only 90 | ASVL_PAF_GRAY = 0x701 91 | 92 | # 8 bit Y plane followed by 8 bit 2x2 subsampled UV planes 93 | ASVL_PAF_NV12 = 0x801 94 | # 8 bit Y plane followed by 8 bit 2x2 subsampled VU planes 95 | ASVL_PAF_NV21 = 0x802 96 | # 8 bit Y plane followed by 8 bit 2x1 subsampled UV planes 97 | ASVL_PAF_LPI422H = 0x803 98 | # 8 bit Y plane followed by 8 bit 2x1 subsampled VU planes 99 | ASVL_PAF_LPI422H2 = 0x804 100 | # 8 bit Y plane followed by 8 bit 4x4 subsampled VU planes 101 | ASVL_PAF_NV41 = 0x805 102 | 103 | ASVL_PAF_RAW10_RGGB_10B = 0xd01 104 | ASVL_PAF_RAW10_GRBG_10B = 0xd02 105 | ASVL_PAF_RAW10_GBRG_10B = 0xd03 106 | ASVL_PAF_RAW10_BGGR_10B = 0xd04 107 | 108 | ASVL_PAF_RAW12_RGGB_12B = 0xd05 109 | ASVL_PAF_RAW12_GRBG_12B = 0xd06 110 | ASVL_PAF_RAW12_GBRG_12B = 0xd07 111 | ASVL_PAF_RAW12_BGGR_12B = 0xd08 112 | 113 | ASVL_PAF_RAW10_RGGB_16B = 0xd09 114 | ASVL_PAF_RAW10_GRBG_16B = 0xd0A 115 | ASVL_PAF_RAW10_GBRG_16B = 0xd0B 116 | ASVL_PAF_RAW10_BGGR_16B = 0xd0C 117 | 118 | # 10 bits gray raw data 119 | ASVL_PAF_RAW10_GRAY_10B = 0xe01 120 | 121 | # 10 bits gray raw data, each data has 2 bytes 122 | ASVL_PAF_RAW10_GRAY_16B = 0xe81 123 | -------------------------------------------------------------------------------- /arcsoft/CLibrary.py: -------------------------------------------------------------------------------- 1 | #-*- encoding=utf-8 -*- 2 | 3 | from ctypes import * 4 | import platform 5 | 6 | if platform.system() == u'Windows': 7 | internalLibrary = cdll.msvcrt 8 | else: 9 | internalLibrary = CDLL(u'libc.so.6') 10 | 11 | malloc = internalLibrary.malloc 12 | free = internalLibrary.free 13 | memcpy = internalLibrary.memcpy 14 | 15 | malloc.restype = c_void_p 16 | malloc.argtypes = (c_size_t, ) 17 | free.restype = None 18 | free.argtypes = (c_void_p, ) 19 | memcpy.restype = c_void_p 20 | memcpy.argtypes = (c_void_p, c_void_p, c_size_t) 21 | -------------------------------------------------------------------------------- /arcsoft/__init__.py: -------------------------------------------------------------------------------- 1 | #-*- encoding=utf-8 -*- 2 | 3 | from ctypes import * 4 | 5 | c_ubyte_p = POINTER(c_ubyte) 6 | 7 | class MRECT(Structure): 8 | _fields_ = [(u'left',c_int32),(u'top',c_int32),(u'right',c_int32),(u'bottom',c_int32)] 9 | 10 | class ASVLOFFSCREEN(Structure): 11 | _fields_ = [(u'u32PixelArrayFormat',c_uint32),(u'i32Width',c_int32),(u'i32Height',c_int32), 12 | (u'ppu8Plane',c_ubyte_p*4),(u'pi32Pitch',c_int32*4)] 13 | def __init__(self): 14 | Structure.__init__(self) 15 | self.gc_ppu8Plane0 = None 16 | self.gc_ppu8Plane1 = None 17 | self.gc_ppu8Plane2 = None 18 | self.gc_ppu8Plane3 = None 19 | 20 | class FaceInfo: 21 | def __init__(self,l,t,r,b,o): 22 | self.left = l; 23 | self.top = t; 24 | self.right = r; 25 | self.bottom = b; 26 | self.orient = o; 27 | 28 | 29 | -------------------------------------------------------------------------------- /arcsoft/lib/linux_x64/README.md: -------------------------------------------------------------------------------- 1 | 把Linux_x64的`.so`文件放在这里。 2 | -------------------------------------------------------------------------------- /arcsoft/lib/linux_x64/ReadME.md: -------------------------------------------------------------------------------- 1 | 把Linux_x64的`.so`文件放在这里。 2 | -------------------------------------------------------------------------------- /arcsoft/lib/win32/README.md: -------------------------------------------------------------------------------- 1 | 把Win32的`.dll`文件放在这里。 2 | -------------------------------------------------------------------------------- /arcsoft/lib/win32/ReadME.md: -------------------------------------------------------------------------------- 1 | 把Win32的`.dll`文件放在这里。 2 | -------------------------------------------------------------------------------- /arcsoft/lib/win64/README.md: -------------------------------------------------------------------------------- 1 | 把64位的`.dll`文件放在这里 -------------------------------------------------------------------------------- /arcsoft/lib/win64/ReadME.md: -------------------------------------------------------------------------------- 1 | 把64位的`.dll`文件放在这里 -------------------------------------------------------------------------------- /arcsoft/utils/ImageLoader.py: -------------------------------------------------------------------------------- 1 | #-*- encoding=utf-8 -*- 2 | 3 | from PIL import Image 4 | from . import BufferInfo 5 | 6 | 7 | def BGRA2I420(img, width, height): 8 | """ 9 | BGRA转换为I420 10 | """ 11 | yuv = bytearray(width * height * 3 // 2) 12 | u_offset = width * height 13 | y_offset = width * height * 5 // 4 14 | 15 | for i in range(0, height): 16 | for j in range(0, width): 17 | rgb = img.getpixel((j, i)) 18 | r = rgb[0] 19 | g = rgb[1] 20 | b = rgb[2] 21 | 22 | y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16 23 | u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128 24 | v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128 25 | 26 | y = 0 if y < 0 else (255 if y > 255 else (y & 0xFF)) 27 | u = 0 if u < 0 else (255 if u > 255 else (u & 0xFF)) 28 | v = 0 if v < 0 else (255 if v > 255 else (v & 0xFF)) 29 | 30 | yuv[i * width + j] = y 31 | yuv[u_offset + (i >> 1) * (width >> 1) + (j >> 1)] = u 32 | yuv[y_offset + (i >> 1) * (width >> 1) + (j >> 1)] = v 33 | 34 | return bytes(yuv) 35 | 36 | 37 | def getI420FromFile(filePath): 38 | """ 39 | 从文件中获取I420数据 40 | """ 41 | img = Image.open(filePath).convert('RGB') 42 | w = img.width & 0xFFFFFFFE 43 | h = img.height & 0xFFFFFFFE 44 | yuv = BGRA2I420(img, w, h) 45 | 46 | return BufferInfo(w, h, yuv) 47 | -------------------------------------------------------------------------------- /arcsoft/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #-*- encoding=utf-8 -*- 2 | 3 | class BufferInfo: 4 | def __init__(self,w, h, buf): 5 | self.width = w; 6 | self.height = h; 7 | self.buffer = buf; -------------------------------------------------------------------------------- /arcsoft/utils/imageJudge.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | from pymediainfo import MediaInfo 4 | 5 | media_info = MediaInfo.parse('../../lena.bmp') 6 | 7 | print(media_info.tracks) 8 | -------------------------------------------------------------------------------- /arcsoft/utils/lib_path.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | import os 4 | 5 | # 获取上级目录的绝对路径 6 | last_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) 7 | # 获取lib 8 | LIB_DIR = os.path.join(last_dir, u"lib") 9 | 10 | LINUX_X64_DIR = os.path.join(LIB_DIR, u"linux_x64") 11 | WINDOWS_DIR = os.path.join(LIB_DIR, u"windows") 12 | WIN32_DIR = os.path.join(LIB_DIR, u"win32") 13 | WIN64_DIR = os.path.join(LIB_DIR, u"win64") 14 | 15 | def test(): 16 | print(LIB_DIR) 17 | print(LINUX_X64_DIR) 18 | print(WIN32_DIR) 19 | 20 | if __name__ == '__main__': 21 | test() 22 | -------------------------------------------------------------------------------- /lena.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/arcsoft_fdfr_python_demo/78891307b0ed331f335a4b78b374b7ab2c09b3b5/lena.bmp -------------------------------------------------------------------------------- /lena_I420_fromBMP.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/arcsoft_fdfr_python_demo/78891307b0ed331f335a4b78b374b7ab2c09b3b5/lena_I420_fromBMP.yuv -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/arcsoft_fdfr_python_demo/78891307b0ed331f335a4b78b374b7ab2c09b3b5/requirements.txt -------------------------------------------------------------------------------- /screenshot/lib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngelLiang/arcsoft_fdfr_python_demo/78891307b0ed331f335a4b78b374b7ab2c09b3b5/screenshot/lib.png --------------------------------------------------------------------------------