Comments (9)
@chaniqure ArcFace并不支持多线程,如果要在协程下调用SDK,请为每一个goroutine使用NewFaceEngine方法创建一个单独的FaceEngine实例(线上环境应该优先考虑使用池化)。如果不符合上述情况,请贴出代码以供分析。
from face-engine.
嗯,我就是池化了引擎,引用的 github.com/jolestar/go-commons-pool/v2 来缓存,引擎对象做了部分修改,关键部分代码代码如下:
type Proxy struct {
c FeatureClient
*pool.ObjectPool
context.Context
}
type FeatureClient struct {
engine *FaceEngine
valid bool
Name string
}
// 为了解决循环依赖而单独放到face包里面
var (
Client *Proxy
)
func InitProxy() *Proxy {
ctx := context.Background()
p := &Proxy{}
p.Context = ctx
//p.ObjectPool = pool.NewObjectPoolWithDefaultConfig(ctx, &ClientFactory{})
p.ObjectPool = pool.NewObjectPool(ctx, &ClientFactory{created: atomic.NewInt64(0)}, &pool.ObjectPoolConfig{
LIFO: pool.DefaultLIFO, // 池是否具有关于空闲对象的 LIFO(后进先出)行为 - 始终从池中返回最近使用的对象,或者作为 FIFO(先进先出)队列,其中池始终返回最旧的对象空闲对象池中的对象。
MaxIdle: 15,
MaxTotal: 15, // 在给定池可以分配的对象数量上限。使用负值表示没有限制
MinIdle: 0, // 要在池中维护的最少空闲对象数。此设置仅在 TimeBetweenEvictionRuns 大于零时才有效。如果是这种情况,则会尝试确保池在空闲对象驱逐运行期间具有所需的最少实例数。如果 MinIdle 的配置值大于 MaxIdle 的配置值,则将使用 MaxIdle 的值。
MinEvictableIdleTime: 10 * time.Minute, // 对象在被回收之前可以在池中闲置的最短时间(如果有的话 - 请参阅 TimeBetweenEvictionRuns。当非正数时,仅由于空闲时间,不会从池中驱逐任何对象
EvictionPolicyName: pool.DefaultEvictionPolicyName,
EvitionContext: context.Background(),
TimeBetweenEvictionRuns: time.Minute,
NumTestsPerEvictionRun: 15,
BlockWhenExhausted: pool.DefaultBlockWhenExhausted}, //是否在池耗尽时调用 ObjectPool.BorrowObject() 方法时阻塞(已达到“活动”对象的最大数量)。
)
p.ObjectPool.StartEvictor()
return p
}
type ClientFactory struct {
created *atomic.Int64
mu sync.Mutex
}
func (f *ClientFactory) MakeObject(ctx context.Context) (*pool.PooledObject, error) {
f.mu.Lock()
defer f.mu.Unlock()
global.Log.Infof("初始化虹软引擎开始,目前已经初始化引擎数量:%d", f.created.Load())
profile := global.Conf.ArcSoft.Linux
if runtime.GOOS == "windows" {
profile = global.Conf.ArcSoft.Windows
}
if err := OnlineActivation(profile.AppId, profile.SdkKey, profile.ActiveKey); err != nil {
global.Log.Errorf("虹软引擎激活失败,堆栈信息: %s", string(debug.Stack()))
return nil, err
}
// 初始化引擎
engine, err := NewFaceEngine(DetectModeImage,
OrientPriority0,
10, // 4.0最大支持10个人脸
EnableFaceDetect|EnableFaceRecognition|EnableFace3DAngle|EnableLiveness|EnableIRLiveness|EnableAge|EnableGender|EnableMaskDetect|EnableFaceLandMark)
if err != nil {
global.Log.Errorf("虹软引擎初始化失败,堆栈信息: %s", string(debug.Stack()))
return nil, err
}
f.created.Inc()
global.Log.Infof("初始化虹软引擎结束,目前已经初始化虹软引擎数量:%d", f.created.Load())
return pool.NewPooledObject(
&FeatureClient{
engine: engine,
Name: fmt.Sprintf("虹软引擎客户端%d号", f.created.Load()),
}), nil
}
func (f *ClientFactory) DestroyObject(ctx context.Context, object *pool.PooledObject) error {
// do destroy
global.Log.Infof("销毁虹软引擎开始,目前已经初始化虹软引擎数量:%d", f.created.Load())
if c, ok := object.Object.(*FeatureClient); ok {
err := c.engine.Destroy()
if err != nil {
return err
}
f.created.Dec()
global.Log.Infof("销毁虹软引擎结束,目前已经初始化虹软引擎数量:%d", f.created.Load())
}
return nil
}
func (f *ClientFactory) ValidateObject(ctx context.Context, object *pool.PooledObject) bool {
// do validate
if c, ok := object.Object.(*FeatureClient); ok {
return c.valid
}
return true
}
func (f *ClientFactory) ActivateObject(ctx context.Context, object *pool.PooledObject) error {
// do activate
if c, ok := object.Object.(*FeatureClient); ok {
c.valid = true
}
return nil
}
func (f *ClientFactory) PassivateObject(ctx context.Context, object *pool.PooledObject) error {
// do passivate
if c, ok := object.Object.(*FeatureClient); ok {
c.valid = false
}
return nil
}
func (p *Proxy) do(f func(c *FeatureClient) (interface{}, error)) (interface{}, error) {
obj1, err := p.BorrowObject(p.Context)
if err != nil {
panic(fmt.Sprintf("租借虹软引擎错误:%s", err))
}
o := obj1.(*FeatureClient)
global.Log.Debugf("%s开始执行", o.Name)
result, err := f(o)
defer func() {
e := p.ReturnObject(p.Context, obj1)
if e != nil {
panic(fmt.Sprintf("归还虹软引擎错误:%s", e))
}
if e := recover(); e != nil {
// 将异常写入日志
global.Log.Error(fmt.Sprintf("[Exception]虹软引擎执行异常: %v\n堆栈信息: %v", err, string(debug.Stack())))
// 服务器异常
return
}
}()
return result, err
}
func (p *Proxy) ExtractFaceFeatureByBase64(saveFace bool, faceBase64 string) (*FaceFeature, error) {
result, err := p.do(func(c *FeatureClient) (interface{}, error) {
return c.ExtractFaceFeatureByBase64(saveFace, faceBase64)
})
return result.(*FaceFeature), err
}
func (p *Proxy) ExtractFaceFeatureByFile(saveFace bool, filePath string) (*FaceFeature, error) {
result, err := p.do(func(c *FeatureClient) (interface{}, error) {
return c.ExtractFaceFeatureByFile(saveFace, filePath)
})
return result.(*FaceFeature), err
}
func (c *FeatureClient) ExtractFaceFeatureByFile(save bool, path string) (*FaceFeature, error) {
imageInfo, err := util.GetResizedImageInfo(path)
if err != nil {
return nil, err
}
info, err := c.engine.DetectFaces(imageInfo.Width, imageInfo.Height, ColorFormatBGR24, imageInfo.DataUInt8)
if err != nil {
return nil, errors.New("未检测到人脸信息")
}
registerOrNot := RecognitionPhoto
if save {
// 注册模式
registerOrNot = RegisterPhoto
}
// 获取单人脸信息
singleFaceInfoArr := GetSingleFaceInfo(info)
if len(singleFaceInfoArr) <= 0 {
return nil, errors.New("未检测到人脸信息")
}
// 图像转为特征
feature, err := c.engine.FaceFeatureExtract(imageInfo.Width, imageInfo.Height, ColorFormatBGR24, imageInfo.DataUInt8, singleFaceInfoArr[0], registerOrNot, 0)
feature.Release()
return &feature, err
}
from face-engine.
补充一下,批量抽取特征的图片数量大约2000张,有些时候能全部成功,有些时候只能抽取几十张到几百张,然后报错
from face-engine.
@chaniqure 你可以先试试竞态检查。我看了一下你发的日志调用堆栈信息,能确定是多线程调用触发SDK的内存保护导致的。我有空了在看看你发的代码。
from face-engine.
刚刚试了下,竞态检查没问题。辛苦大大帮忙看一下 ,谢谢!!
from face-engine.
@chaniqure client.go第100行处,没有对error进行判断就调用了释放方法
from face-engine.
还是不行
错误.txt
from face-engine.
from face-engine.
是批量获取图片的人像信息报错了,之前保存图片相关信息时候,除了要提取人像特征,同时也会获取图片人像的年龄,性别等信息,现在单独
Uploading 错误.txt…
批量抽特征没问题了。刚刚测试了一下,并发获取图片人像信息会报错,而且是100%的会报错
func (c *FeatureClient) GetLiveInfoByFile(path string) (LiveInfo, error) {
imageInfo, err := util.GetResizedImageInfo(path)
if err != nil {
return LiveInfo{}, err
}
info, err := c.engine.DetectFaces(imageInfo.Width, imageInfo.Height, ColorFormatBGR24, imageInfo.DataUInt8)
if err != nil {
return LiveInfo{}, errors.New("未检测到人脸信息")
}
// 获取单人脸信息
err = c.engine.Process(imageInfo.Width, imageInfo.Height, ColorFormatBGR24, imageInfo.DataUInt8, info, EnableAge|EnableGender|EnableMaskDetect)
if err != nil {
return LiveInfo{}, err
}
liveInfo := LiveInfo{}
age, err := c.engine.GetAge()
if err != nil {
return liveInfo, err
}
fmt.Println(age)
mask, err := c.engine.GetMask()
if err != nil {
return liveInfo, err
}
fmt.Println(mask)
gender, err := c.engine.GetGender()
if err != nil {
return liveInfo, err
}
fmt.Println(gender)
return liveInfo, nil
}
from face-engine.
Related Issues (20)
- 能支持linux不?是不是有什么问题? HOT 5
- 如何根据人脸特征码,反向组成Featrue结构体 HOT 2
- 无法编译通过 HOT 1
- Mac 上运行报错 ld: library not found for -larcsoft_face_engine
- 目前报这个错误,该怎么解决呢,求回答 HOT 1
- 你好 HOT 1
- V4版本SDK在哪? HOT 1
- 麻烦作者什么时候抽空封装下4.1版本呢,据说效果有提升
- 运行例子报了几个未定义的错,请问怎么解决 HOT 2
- 请问支持视频流识别么? HOT 4
- 示例运行错误 HOT 2
- 小建议 HOT 1
- cgo 动态编译库文件问题 HOT 3
- 请问支持年龄识别吗?
- 请问有改造3.0的想法么 HOT 4
- go get wrong HOT 1
- 提取人脸特征的时候,咋感觉arr没有赋值呢? HOT 1
- 提取人脸特征的时候,咋感觉arr没有赋值呢? HOT 1
- 一个因为人脸特征提取失败导致panic的bug HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from face-engine.