| | |
| | | */ |
| | | import "C" |
| | | import ( |
| | | "analysis/goconv" |
| | | "analysis/logo" |
| | | "analysis/work" |
| | | "context" |
| | | "fmt" |
| | | "time" |
| | | "unsafe" |
| | | |
| | | "basic.com/libgowrapper/sdkstruct.git" |
| | | "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) |
| | | cacheFrameNum = 3 |
| | | trackChnTimeout = time.Duration(10) |
| | | ) |
| | | |
| | | func (e *EFDetect) cleanChnStat() { |
| | |
| | | for { |
| | | select { |
| | | case <-ctx.Done(): |
| | | e.fnFree(e.handle) |
| | | return |
| | | default: |
| | | rMsg := <-in |
| | |
| | | e.ftrackChans[rMsg.Msg.Cid] <- rMsg |
| | | } else { |
| | | |
| | | e.ftrackChans[rMsg.Msg.Cid] = make(chan work.MsgRS, CacheFrameNum) |
| | | e.ftrackChans[rMsg.Msg.Cid] = make(chan work.MsgRS, cacheFrameNum) |
| | | chn := e.getAvailableChn() |
| | | if chn < 0 { |
| | | logo.Infof("TOO MUCH CHANNEL") |
| | |
| | | } |
| | | // conv to bgr24 and resize |
| | | imgW, imgH := int(i.Width), int(i.Height) |
| | | ret := gosdk.ResizeFaceTracker(e.ftrackChannels[rMsg.Msg.Cid], imgW, imgH) |
| | | ret := e.fnTrackerResize(e.handle, 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]) |
| | |
| | | for { |
| | | select { |
| | | case <-ctx.Done(): |
| | | goconv.Free() |
| | | return |
| | | |
| | | case rMsg := <-in: |
| | | |
| | | if !validRemoteMessage(rMsg, typ) { |
| | |
| | | |
| | | // 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) |
| | | fRes := e.fnRun(e.handle, i.Data, imgW, imgH, 3, dtchn) |
| | | |
| | | var faces []*protomsg.ResultFaceDetect |
| | | |
| | | //将sdk返回值转换成protomsg类型 |
| | | for _, d := range detect { |
| | | 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) |
| | |
| | | } |
| | | /// 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) |
| | | feat := r.Feat |
| | | prop := (*protomsg.ThftResult)(unsafe.Pointer(&r.Prop)) |
| | | fpos := tconvert2ProtoFacePos(d) |
| | | |
| | | //组成结果并序列化 |
| | | res := &protomsg.ResultFaceDetect{Pos: result, Result: resP, Feats: feat} |
| | | res := &protomsg.ResultFaceDetect{Pos: fpos, Result: prop, 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) |
| | | fmt.Println("fdetect marshal proto face pos error", err) |
| | | data = nil |
| | | } |
| | | } |
| | |
| | | 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)) |
| | | 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)) |
| | | 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)) |
| | | 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): |
| | | case <-time.After(trackChnTimeout * time.Second): |
| | | logo.Errorln("Timeout to get image, curCid:", curCid) |
| | | if curCid != "" { |
| | | delete(e.ftrackChans, curCid) |
| | |
| | | } |
| | | } |
| | | |
| | | //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() |
| | | // } |
| | | // |
| | | // } |
| | | // } |
| | | //} |
| | | 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, |
| | | } |
| | | } |