1 Star 0 Fork 0

wingyun/face-engine

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
engine.go 8.84 KB
一键复制 编辑 原始数据 按行查看 历史
wingyun 提交于 2024-05-24 14:57 . 增加非ex函数
package faceengine
/*
#cgo CFLAGS : -I./include
#cgo LDFLAGS : -larcsoft_face_engine
#include <stdlib.h>
#include "merror.h"
#include "asvloffscreen.h"
#include "arcsoft_face_sdk.h"
*/
import "C"
import (
"unsafe"
)
// FaceEngine 引擎结构体
type FaceEngine struct {
handle C.MHandle
}
// 人脸信息结构体
type FaceInfo struct {
FaceNum int32 // 检测到的人脸个数
//下面都是第一个人信息
FaceRect Rect // 人脸框信息
WearGlasses int32 // 戴眼镜状态, 0 未戴眼镜;1 戴眼镜;2 墨镜
LeftEyeOpen int32 // 左眼状态 0 闭眼;1 睁眼
RightEyeOpen int32 // 右眼状态 0 闭眼;1 睁眼
MouthClose int32 // 张嘴状态 0 张嘴;1 合嘴
FaceIsWithinBoundary int32 // 人脸是否在边界内 0 人脸溢出;1 人脸在图像边界内
Roll float32
Yaw float32
Pitch float32
IsLive int32 // 0:非真人 1:真人 -1:不确定 -2:传入人脸数>1
IsMask int32 // 0代表没有带口罩 1代表带口罩 -1表示不确定
}
// Rect 人脸坐标结构体
type Rect struct {
Left int32
Top int32
Right int32
Bottom int32
}
// ImageData 对应ASVLOFFSCREEN结构体
type ImageData struct {
PixelArrayFormat C.MUInt32
Width int
Height int
ImageData [4][]uint8
WidthStep [4]int
}
// EngineError SDK错误码
type EngineError struct {
Code int
Text string
}
const (
// DetectModeVideo 视频模式
DetectModeVideo = C.ASF_DETECT_MODE_VIDEO
// DetectModeImage 图片模式
DetectModeImage = C.ASF_DETECT_MODE_IMAGE
// OrientPriority0 不旋转
OrientPriority0 = C.ASF_OP_0_ONLY
// OrientPriority90 旋转90度
OrientPriority90 = C.ASF_OP_90_ONLY
// OrientPriority270 旋转270度
OrientPriority270 = C.ASF_OP_270_ONLY
// OrientPriority180 旋转180度
OrientPriority180 = C.ASF_OP_180_ONLY
// OrientPriorityAllOut 角度不限
OrientPriorityAllOut = C.ASF_OP_ALL_OUT
// EnableFaceDetect 开启人脸检测
EnableFaceDetect = C.ASF_FACE_DETECT
// EnableFaceRecognition 开启人脸识别
EnableFaceRecognition = C.ASF_FACERECOGNITION
// EnableLiveness 开启活体检测
EnableLiveness = C.ASF_LIVENESS
// EnableImageQuality 开启单人脸图片质量检测
EnableImageQuality = C.ASF_IMAGEQUALITY
// EnableMaskDetect 开启口罩检测
EnableMaskDetect = C.ASF_MASKDETECT
// EnableUpdateFaceData 开启人脸数据更新
EnableUpdateFaceData = C.ASF_UPDATE_FACEDATA
ColorFormatBGR24 = C.ASVL_PAF_RGB24_B8G8R8
)
// OnlineActivation 在线激活接口
func OnlineActivation(appID, sdkKey, activeKey string) (err error) {
id := C.CString(appID)
sk := C.CString(sdkKey)
ak := C.CString(activeKey)
defer func() {
C.free(unsafe.Pointer(id))
C.free(unsafe.Pointer(sk))
C.free(unsafe.Pointer(ak))
}()
r := C.ASFOnlineActivation(id, sk, ak)
if r != C.MOK && r != C.MERR_ASF_ALREADY_ACTIVATED {
err = newError(int(r), "激活SDK失败")
}
return
}
// NewFaceEngine 创建一个新的引擎实例
// 如果调用初始化函数失败则返回一个错误
func NewFaceEngine() (*FaceEngine, error) {
engine, err := &FaceEngine{}, error(nil)
r := C.ASFInitEngine(DetectModeImage, OrientPriority0,
10, EnableFaceDetect|EnableFaceRecognition|
EnableLiveness|EnableImageQuality|EnableMaskDetect|
EnableUpdateFaceData, &engine.handle)
if r != C.MOK {
err = newError(int(r), "初始化引擎失败")
}
return engine, err
}
// DetectFaces 人脸检测,目前不支持IR图像数据检测
func (engine *FaceEngine) DetectFaces(
width int, // 宽度
height int, // 高度
format C.MInt32, // 图像格式
imgData []byte, // 图片数据
) (faceInfo FaceInfo, err error) {
asfFaceInfo := &C.ASF_MultiFaceInfo{}
r := C.ASFDetectFaces(engine.handle,
C.MInt32(width),
C.MInt32(height),
format,
(*C.MUInt8)(unsafe.Pointer(&imgData[0])),
asfFaceInfo,
C.ASF_DETECT_MODEL_RGB,
)
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFDetectFacesEx失败")
}
faceNum := int32(asfFaceInfo.faceNum)
faceInfo.FaceNum = faceNum
if faceInfo.FaceNum < 1 {
return faceInfo, nil
}
faceInfo.FaceRect = (*[10]Rect)(unsafe.Pointer(asfFaceInfo.faceRect))[0]
faceInfo.FaceIsWithinBoundary = *(*int32)(unsafe.Pointer(asfFaceInfo.faceIsWithinBoundary))
faceInfo.WearGlasses = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.wearGlasses))
faceInfo.LeftEyeOpen = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.leftEyeOpen))
faceInfo.RightEyeOpen = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.rightEyeOpen))
faceInfo.MouthClose = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.mouthClose))
faceInfo.Roll = *(*float32)(unsafe.Pointer(asfFaceInfo.face3DAngleInfo.roll))
faceInfo.Yaw = *(*float32)(unsafe.Pointer(asfFaceInfo.face3DAngleInfo.yaw))
faceInfo.Pitch = *(*float32)(unsafe.Pointer(asfFaceInfo.face3DAngleInfo.pitch))
//获取活人和口罩前必须调用该函数
r = C.ASFProcess(engine.handle,
C.MInt32(width),
C.MInt32(height),
format,
(*C.MUInt8)(unsafe.Pointer(&imgData[0])),
asfFaceInfo,
EnableMaskDetect|EnableLiveness)
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFProcessEx失败")
}
//获取活人
asfLivenessInfo := &C.ASF_LivenessInfo{}
r = C.ASFGetLivenessScore((C.MHandle)(engine.handle), asfLivenessInfo)
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFGetLivenessScore失败")
}
faceInfo.IsLive = (*[10]int32)(unsafe.Pointer(asfLivenessInfo.isLive))[0]
//获取口罩
asfMaskInfo := &C.ASF_MaskInfo{}
r = C.ASFGetMask(engine.handle, (*C.ASF_MaskInfo)(unsafe.Pointer(asfMaskInfo)))
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFGetMask失败")
}
faceInfo.IsMask = (*[10]int32)(unsafe.Pointer(asfMaskInfo.maskArray))[0]
return
}
// DetectFacesEx 检测人脸信息
// 该接口与 DetectFaces 功能一致,但采用结构体的形式传入图像数据,对更高精度的图像兼容性更好。
func (engine *FaceEngine) DetectFacesEx(imageData ImageData) (faceInfo FaceInfo, err error) {
asfFaceInfo := &C.ASF_MultiFaceInfo{}
offscreen := imageDataToASVLOFFSCREEN(imageData)
r := C.ASFDetectFacesEx(engine.handle, offscreen, asfFaceInfo, C.ASF_DETECT_MODEL_RGB)
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFDetectFacesEx失败")
}
faceNum := int32(asfFaceInfo.faceNum)
faceInfo.FaceNum = faceNum
if faceInfo.FaceNum < 1 {
return faceInfo, nil
}
faceInfo.FaceRect = (*[10]Rect)(unsafe.Pointer(asfFaceInfo.faceRect))[0]
faceInfo.FaceIsWithinBoundary = *(*int32)(unsafe.Pointer(asfFaceInfo.faceIsWithinBoundary))
faceInfo.WearGlasses = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.wearGlasses))
faceInfo.LeftEyeOpen = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.leftEyeOpen))
faceInfo.RightEyeOpen = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.rightEyeOpen))
faceInfo.MouthClose = *(*int32)(unsafe.Pointer(asfFaceInfo.faceAttributeInfo.mouthClose))
faceInfo.Roll = *(*float32)(unsafe.Pointer(asfFaceInfo.face3DAngleInfo.roll))
faceInfo.Yaw = *(*float32)(unsafe.Pointer(asfFaceInfo.face3DAngleInfo.yaw))
faceInfo.Pitch = *(*float32)(unsafe.Pointer(asfFaceInfo.face3DAngleInfo.pitch))
//获取活人和口罩前必须调用该函数
r = C.ASFProcessEx(engine.handle, offscreen, asfFaceInfo,
EnableMaskDetect|EnableLiveness)
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFProcessEx失败")
}
//获取活人
asfLivenessInfo := &C.ASF_LivenessInfo{}
r = C.ASFGetLivenessScore((C.MHandle)(engine.handle), asfLivenessInfo)
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFGetLivenessScore失败")
}
faceInfo.IsLive = (*[10]int32)(unsafe.Pointer(asfLivenessInfo.isLive))[0]
//获取口罩
asfMaskInfo := &C.ASF_MaskInfo{}
r = C.ASFGetMask(engine.handle, (*C.ASF_MaskInfo)(unsafe.Pointer(asfMaskInfo)))
if r != C.MOK {
return faceInfo, newError(int(r), "人脸检测:ASFGetMask失败")
}
faceInfo.IsMask = (*[10]int32)(unsafe.Pointer(asfMaskInfo.maskArray))[0]
return
}
// Destroy 销毁引擎
func (engine *FaceEngine) Destroy() (err error) {
r := C.ASFUninitEngine(engine.handle)
if r != C.MOK {
err = newError(int(r), "销毁引擎失败")
}
return
}
// 实现Error接口
func (err EngineError) Error() string {
return err.Text
}
func newError(code int, text string) EngineError {
return EngineError{
Code: code,
Text: text,
}
}
func imageDataToASVLOFFSCREEN(imageData ImageData) C.LPASVLOFFSCREEN {
var pi32Pitch [4](C.MInt32)
for i := 0; i < 4; i++ {
pi32Pitch[i] = C.MInt32(imageData.WidthStep[0])
}
var ppu8Plane [4](*C.MUInt8)
for i := 0; i < 4; i++ {
if len(imageData.ImageData[i]) > 0 {
ppu8Plane[i] = (*C.MUInt8)(unsafe.Pointer(&imageData.ImageData[i][0]))
}
}
return &C.ASVLOFFSCREEN{
imageData.PixelArrayFormat,
C.MInt32(imageData.Width),
C.MInt32(imageData.Height),
ppu8Plane,
pi32Pitch}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/wingyun/face-engine.git
git@gitee.com:wingyun/face-engine.git
wingyun
face-engine
face-engine
master

搜索帮助