package sdk /* #include #define LANDMARKS_NUM 25 typedef struct { int id; float x; float y; } Key_Point; typedef struct { int count; int view; Key_Point pts[LANDMARKS_NUM]; } Face_Landmarks; void *resize(void **data, const float fx, const float fy){ Face_Landmarks* lms = (Face_Landmarks*)(*data); for(int i = 0; i < lms->count; i++){ Key_Point kp = lms->pts[i]; kp.x /= fx; kp.y /= fy; lms->pts[i] = kp; } return *data; } */ import "C" import ( "analysis/logo" "analysis/work" "context" "fmt" "time" "unsafe" "basic.com/libgowrapper/sdkstruct.git" "basic.com/pubsub/protomsg.git" "github.com/gogo/protobuf/proto" ) const ( cacheFrameNum = 3 trackChnTimeout = time.Duration(10) ) func (e *EFDetect) cleanChnStat() { e.chnLock.Lock() for i := 0; i < MaxFaceDetectThreadNum; i++ { e.ftrackChanStats[i] = false } e.chnLock.Unlock() } func (e *EFDetect) getAvailableChn() int { e.chnLock.Lock() defer e.chnLock.Unlock() for i := 0; i < MaxFaceDetectThreadNum; i++ { if e.ftrackChanStats[i] == false { e.ftrackChanStats[i] = true return i } } return -1 } func (e *EFDetect) releaseChn(chn int) { e.chnLock.Lock() e.ftrackChanStats[chn] = false e.chnLock.Unlock() } func (e *EFDetect) detectTrack(ctx context.Context, in <-chan work.MsgRS, out chan<- work.MsgRS, typ string) { for { select { case <-ctx.Done(): e.fnFree(e.handle) return case rMsg := <-in: if !validRemoteMessage(rMsg, typ) { logo.Errorln("face track validremotemessage invalid") ejectResult(nil, rMsg, out) continue } if _, ok := e.ftrackChans[rMsg.Msg.Cid]; ok { e.ftrackChans[rMsg.Msg.Cid] <- rMsg } else { e.ftrackChans[rMsg.Msg.Cid] = make(chan work.MsgRS, cacheFrameNum) chn := e.getAvailableChn() if chn < 0 { logo.Infof("TOO MUCH CHANNEL") ejectResult(nil, rMsg, out) continue } e.ftrackChannels[rMsg.Msg.Cid] = chn i := unpackImage(rMsg, typ) if i == nil { ejectResult(nil, rMsg, out) continue } // conv to bgr24 and resize imgW, imgH := int(i.Width), int(i.Height) ret := e.fnTrackerResize(e.handle, imgW, imgH, chn) logo.Infof("ResizeFaceTracker: cid:%s, chan:%d, wXh:%d x %d ,result:%t\n", rMsg.Msg.Cid, chn, imgW, imgH, ret) go e.detectTrackOneChn(ctx, e.ftrackChans[rMsg.Msg.Cid], out, typ, chn) e.ftrackChans[rMsg.Msg.Cid] <- rMsg } default: time.Sleep(time.Millisecond * 100) } } } func (e *EFDetect) detectTrackOneChn(ctx context.Context, in <-chan work.MsgRS, out chan<- work.MsgRS, typ string, dtchn int) { tm := time.Now() sc := 0 logo.Infof("detectTrackOneChn dtchn:%d\n", dtchn) var curCid string for { select { case <-ctx.Done(): return case rMsg := <-in: if !validRemoteMessage(rMsg, typ) { ejectResult(nil, rMsg, out) continue } i := unpackImage(rMsg, typ) if i == nil || i.Data == nil || i.Width <= 0 || i.Height <= 0 { ejectResult(nil, rMsg, out) continue } curCid = i.Cid // conv to bgr24 and resize imgW, imgH := int(i.Width), int(i.Height) fRes := e.fnRun(e.handle, i.Data, imgW, imgH, 3, dtchn) var faces []*protomsg.ResultFaceDetect //将sdk返回值转换成protomsg类型 for _, r := range fRes { d := r.Info /// filter rules sdkid := rMsg.Msg.Tasklab.Sdkinfos[rMsg.Msg.Tasklab.Index].Ipcid size := (d.RcFace.Right - d.RcFace.Left) * (d.RcFace.Bottom - d.RcFace.Top) angle := d.FAngle if !filter(rMsg.Msg.Tasklab.Taskid, sdkid, angle.Confidence, float32(angle.Yaw), int(size)) { continue } /// filter rules feat := r.Feat prop := (*protomsg.ThftResult)(unsafe.Pointer(&r.Prop)) fpos := tconvert2ProtoFacePos(d) //组成结果并序列化 res := &protomsg.ResultFaceDetect{Pos: fpos, Result: prop, Feats: feat} faces = append(faces, res) } var err error var data []byte if len(faces) > 0 { facePos := protomsg.ParamFacePos{Faces: faces} data, err = proto.Marshal(&facePos) if err != nil { fmt.Println("fdetect marshal proto face pos error", err) data = nil } } ejectResult(data, rMsg, out) var id, name string if rMsg.Msg.Tasklab != nil { id, name = rMsg.Msg.Tasklab.Taskid, rMsg.Msg.Tasklab.Taskname } logo.Infoln("CAMERAID: ", rMsg.Msg.Cid, " TASKID: ", id, " TASKNAME: ", name, " DETECT FACE COUNT: ", len(fRes)) sc++ if sc == 25 { logo.Infoln("CHAN:%d, FACE RUN 25 FRAME USE TIME: ", dtchn, time.Since(tm)) sc = 0 tm = time.Now() } if time.Since(tm) > time.Second { logo.Infof("CHAN:%d, FACE RUN %d FRAME USE TIME: %v", dtchn, sc, time.Since(tm)) sc = 0 tm = time.Now() } case <-time.After(trackChnTimeout * time.Second): logo.Errorln("Timeout to get image, curCid:", curCid) if curCid != "" { delete(e.ftrackChans, curCid) e.releaseChn(dtchn) } return } } } func tconvert2ProtoFacePos(dec sdkstruct.CFaceInfo) *protomsg.FacePos { crect := dec.RcFace rect := protomsg.Rect{Left: crect.Left, Top: crect.Top, Right: crect.Right, Bottom: crect.Bottom} leftEye := (*protomsg.Point)(unsafe.Pointer(&dec.PtLeftEye)) rightEye := (*protomsg.Point)(unsafe.Pointer(&dec.PtRightEye)) mouth := (*protomsg.Point)(unsafe.Pointer(&dec.PtMouth)) nose := (*protomsg.Point)(unsafe.Pointer(&dec.PtNose)) angle := (*protomsg.FaceAngle)(unsafe.Pointer(&dec.FAngle)) faceID := uint64(dec.NFaceID) facialData := dec.PFacialData[:512] // facialData := make([]byte, 512) // copy(facialData[:], dec.PFacialData[:512]) return &protomsg.FacePos{ RcFace: &rect, PtLeftEye: leftEye, PtRightEye: rightEye, PtMouth: mouth, PtNose: nose, FAngle: angle, Quality: dec.NQuality, FacialData: facialData, FaceID: faceID, } }