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/goconv" "analysis/logo" "analysis/work" "context" "time" "unsafe" "basic.com/pubsub/protomsg.git" "basic.com/valib/gosdk.git" "github.com/gogo/protobuf/proto" ) func tconvert2ProtoFacePos(dec gosdk.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, } } 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(): return default: 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 := gosdk.ResizeFaceTracker(e.ftrackChannels[rMsg.Msg.Cid], imgW, imgH) logo.Infof("ResizeFaceTracker: cid:%s, chan:%d, wXh:%d x %d ,result:%d\n", rMsg.Msg.Cid, e.ftrackChannels[rMsg.Msg.Cid], imgW, imgH, ret) go e.detectTrackOneChn(ctx, e.ftrackChans[rMsg.Msg.Cid], out, typ, e.ftrackChannels[rMsg.Msg.Cid]) e.ftrackChans[rMsg.Msg.Cid] <- rMsg } } } } 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(): goconv.Free() 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) bgrData := goconv.YUV2BGR(i.Data, imgW, imgH) if bgrData == nil { ejectResult(nil, rMsg, out) continue } img := gosdk.SDKImage{Data: bgrData, Width: imgW, Height: imgH} detect := gosdk.FaceTrackSimple(img, dtchn) var faces []*protomsg.ResultFaceDetect //将sdk返回值转换成protomsg类型 for _, d := range detect { /// 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 //运行sd dec := gosdk.FaceInfo2FacePos(d) prop := gosdk.FaceProperty(dec, img, dtchn) feat := gosdk.FaceExtract(dec, img, dtchn) resP := (*protomsg.ThftResult)(unsafe.Pointer(&prop)) result := tconvert2ProtoFacePos(d) //组成结果并序列化 res := &protomsg.ResultFaceDetect{Pos: result, Result: resP, Feats: feat} faces = append(faces, res) } var err error var data []byte if len(faces) > 0 { // logo.Infoln("CID: ", rMsg.Msg.Cid, " TASK: ", rMsg.Msg.Tasklab.Taskid, " FACE TRACK OBJS: ", len(faces)) facePos := protomsg.ParamFacePos{Faces: faces} data, err = proto.Marshal(&facePos) if err != nil { logo.Errorln("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(faces)) 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("cahn:%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 (e *EFDetect) detectTrack(ctx context.Context, in <-chan work.MsgRS, out chan<- work.MsgRS, typ string) { // tm := time.Now() // sc := 0 // // for { // select { // case <-ctx.Done(): // goconv.Free() // return // default: // rMsg := <-in // validMsg := validRemoteMessage(rMsg, typ) // // 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) // resizeW, resizeH := util.SFI.TrackPicWidth, util.SFI.TrackPicHeight // fx := (float64)(resizeW) / (float64)(imgW) // fy := (float64)(resizeH) / (float64)(imgH) // // origData, resizeData := goconv.YUV2BGRandResize(i.Data, goconv.PIX_FMT_NV12, imgW, imgH, fx, fy) // if origData == nil { // ejectResult(nil, rMsg, out) // continue // } // // resize to track // if imgW < resizeW && imgH < resizeH { // resizeData = origData // resizeW, resizeH = imgW, imgH // } // // resize to track // // img := gosdk.SDKImage{Data: origData, Width: imgW, Height: imgH} // imgTrack := gosdk.SDKImage{Data: resizeData, Width: resizeW, Height: resizeH} // if !validMsg { // ejectResult(nil, rMsg, out) // continue // } // //运行sdk // c, ok, _ := e.q.Get() // if !ok { // logo.Errorln("fdetect there is no idle thread") // ejectResult(nil, rMsg, out) // continue // } // detect := gosdk.FaceTrackSimple(imgTrack, c.(int)) // e.q.Put(c) // // // if len(detect) > 0 { // // logo.Infof("FACE DETECT FROM CAMERA %s IMAGE-ID %d, TASKID %s, %d FACES COUNT\n", rMsg.Msg.Cid, i.Id, rMsg.Msg.Tasklab.Taskid, len(detect)) // // } // // var faces []*protomsg.ResultFaceDetect // // //将sdk返回值转换成protomsg类型 // for _, d := range detect { // // /// 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 // // if fx < 1.0 || fy < 1.0 { // d.RcFace.Left = (int32)((float64)(d.RcFace.Left) / fx) // d.RcFace.Top = (int32)((float64)(d.RcFace.Top) / fy) // d.RcFace.Right = (int32)((float64)(d.RcFace.Right) / fx) // d.RcFace.Bottom = (int32)((float64)(d.RcFace.Bottom) / fy) // d.PtLeftEye.X = (int32)((float64)(d.PtLeftEye.X) / fx) // d.PtLeftEye.Y = (int32)((float64)(d.PtLeftEye.Y) / fy) // d.PtRightEye.X = (int32)((float64)(d.PtRightEye.X) / fx) // d.PtRightEye.Y = (int32)((float64)(d.PtRightEye.Y) / fy) // d.PtMouth.X = (int32)((float64)(d.PtMouth.X) / fx) // d.PtMouth.Y = (int32)((float64)(d.PtMouth.Y) / fy) // d.PtNose.X = (int32)((float64)(d.PtNose.X) / fx) // d.PtNose.Y = (int32)((float64)(d.PtNose.Y) / fy) // // faceData := d.PFacialData[:8192] // data := C.CBytes(faceData) // defer C.free(data) // resizeP := C.resize(&data, C.float(fx), C.float(fy)) // fd := C.GoBytes(resizeP, 8192) // d.PFacialData = *(*[8192]uint8)(unsafe.Pointer(&fd[0])) // // } // // //运行sd // dec := gosdk.FaceInfo2FacePos(d) // // c, ok, _ := e.qprop.Get() // if !ok { // logo.Errorln("fproperty there is no idle thread") // continue // } // prop := gosdk.FaceProperty(dec, imgTrack, c.(int)) // e.qprop.Put(c) // // c, ok, _ = e.qext.Get() // if !ok { // logo.Errorln("fextract there is no idle thread") // continue // } // feat := gosdk.FaceExtract(dec, imgTrack, c.(int)) // e.qext.Put(c) // // resP := (*protomsg.ThftResult)(unsafe.Pointer(&prop)) // // result := tconvert2ProtoFacePos(d) // // //组成结果并序列化 // res := &protomsg.ResultFaceDetect{Pos: result, Result: resP, Feats: feat} // faces = append(faces, res) // // } // // var err error // var data []byte // if len(faces) > 0 { // // // logo.Infoln("CID: ", rMsg.Msg.Cid, " TASK: ", rMsg.Msg.Tasklab.Taskid, " FACE TRACK OBJS: ", len(faces)) // // facePos := protomsg.ParamFacePos{Faces: faces} // data, err = proto.Marshal(&facePos) // if err != nil { // logo.Errorln("fdetect marshal proto face pos error", err) // data = nil // } // } // // // logo.Infoln("CURRENT INDEX: ",rMsg.Msg.Tasklab.Index) // rMsg.BGRImg = &img // ejectResult(data, rMsg, out) // // sc++ // if sc == 25 { // logo.Infoln("FACE RUN 25 FRAME USE TIME: ", time.Since(tm)) // sc = 0 // tm = time.Now() // } // // if time.Since(tm) > time.Second { // logo.Infof("FACE RUN %d FRAME USE TIME: %v", sc, time.Since(tm)) // sc = 0 // tm = time.Now() // } // // } // } //}