package personTrack import ( "encoding/json" "errors" uuid "github.com/satori/go.uuid" "net" "strconv" "time" "nanomsg.org/go-mangos" "nanomsg.org/go-mangos/protocol/req" "nanomsg.org/go-mangos/transport/tcp" "github.com/knetic/govaluate" "basic.com/valib/logger.git" "basic.com/pubsub/protomsg.git" "ruleprocess/structure" ) var sender chan []byte = make(chan []byte) var receiver chan string = make(chan string) var initFlag bool = false var sock mangos.Socket func Init() { go Push() } // 人体跟踪算法 func Entrance(rule *protomsg.Rule, am *structure.AreaMap, lable *structure.Others, args *structure.SdkDatas, message *protomsg.SdkMessage) structure.LittleRuleResult { if !initFlag { Init() } if rule.PolygonId == am.AreaId { // 首先这条规则得是这个算法的规则,其次规则所对应的区域id要跟区域数据的id对的上 //logger.Debug("---------走了人员异常算法", rule.Id, rule.SdkArgAlias, rule.Operator, rule.SdkArgValue, am.AreaId) if rule.SdkArgAlias == "score" || rule.SdkArgAlias == "proportion" || rule.SdkArgAlias == "size" || rule.SdkArgAlias == "" { // 判断的是相似值,占比,尺寸等过滤条件,如果再有,还可以再加 return filterRule(rule, am) } else if rule.SdkArgAlias == "cmpThreshold"{ return track(rule,am) } return structure.LittleRuleResult{} } else { return structure.LittleRuleResult{} } } // 过滤规则先筛选出符合条件的目标数量 func filterRule(rule *protomsg.Rule, am *structure.AreaMap) structure.LittleRuleResult { // 处理的都是yolo数据 if rule.SdkArgAlias == "score" || rule.SdkArgAlias == "proportion" || rule.SdkArgAlias == "size" { // 判断的是相似值,占比,尺寸等过滤条件,如果再有,还可以再加 var args []*structure.Arg if rule.RuleWithPre == "&&" { args = am.FilterData } else { args = am.Args } // 先清空过滤后的数据,再往里塞本次过滤后的数据 am.FilterData = am.FilterData[0:0] //logger.Debug("看看args:::::", args) for _, arg := range args { var formula string switch rule.SdkArgAlias { case "score": formula = strconv.FormatFloat(arg.Score, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue //logger.Info("相似度小公式:", formula) case "proportion": formula = strconv.FormatFloat(arg.Proportion, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue //logger.Info("占比公式:", formula) case "size": formula = strconv.FormatFloat(arg.Size, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue //logger.Info("尺寸小公式:", formula) } expression, _ := govaluate.NewEvaluableExpression(formula) // 得到数学公式 result, _ := expression.Evaluate(nil) // 得到数学公式的结果 if result.(bool) { am.FilterData = append(am.FilterData, arg) // 得到符合条件的过滤数据 } } am.TargetNum = len(am.FilterData) // 把符合条件的目标数量更新到targetNum字段 if am.TargetNum > 0 { return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "true", rule.Sort} } else { return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort} } } else if rule.SdkArgAlias == "" { if am.TargetNum > 0 { return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "true", rule.Sort} } else { return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort} } } return structure.LittleRuleResult{} } // 给目标填充liker func fillLiker(compareThreshold float32,arg *structure.Arg,am *structure.AreaMap) { trackArg := make(map[string]interface{}) esId := uuid.NewV4().String() trackArg["esId"] = esId trackArg["threshold"] = compareThreshold trackArg["cameraId"] = am.CameraId trackArg["bodyFeature"] = arg.Feature trackArg["faceFeature"] = arg.AttachArg.Feature b,err := json.Marshal(trackArg) if err != nil { logger.Error("json序列化错误", err) } dataId := getCompareMsg(b) if esId == dataId { // 说明没比到相似的人 logger.Info("没比到人") arg.Uuid = dataId } else { logger.Info("比对出来的dataId:",dataId) base := structure.BaseInfo{TargetId:dataId} arg.Liker = append(arg.Liker, &base) } } func track (rule *protomsg.Rule,am *structure.AreaMap) structure.LittleRuleResult{ var threshold float32 = 70 // 默认阈值为70 if th,err := strconv.ParseFloat(rule.SdkArgValue,32); err == nil { threshold = float32(th) } for _, arg := range am.FilterData { fillLiker(threshold,arg,am) //if len(arg.Liker) == 0 { // // 如果没有相似者则删除本目标数据 // am.FilterData = append(am.FilterData[:i],am.FilterData[i+1:]...) //} } //if len(am.FilterData) > 0 { // return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "true", rule.Sort} //} else { // return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort} //} // 无论有没有相似者都要返回true return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "true", rule.Sort} } func Push(){ var err error var msg []byte if sock, err = req.NewSocket(); err != nil { logger.Error("创建请求socket失败: %s", err.Error()) } errSize := sock.SetOption(mangos.OptionMaxRecvSize,5*1024*1024) if errSize != nil { logger.Error("Failed set MaxRecvSize: %v", err) } //sock.AddTransport(ipc.NewTransport()) sock.AddTransport(tcp.NewTransport()) serverIP, _ := GetLocalIP() if err = sock.Dial("tcp://"+serverIP+":4010"); err != nil { logger.Error("请求socket拨号失败: %s", err.Error()) } logger.Info("序列化数据") initFlag = true for { select { case data := <- sender: logger.Debug("推送数据:",len(data)) if err = sock.Send(data); err != nil { logger.Error("推送socket发送数据失败: %s", err.Error()) } if msg, err = sock.Recv(); err != nil { logger.Error("接收响应失败: %s", err.Error()) } logger.Debug("数据推送成功!收到响应,数据长度为:",len(msg)) receiver <- string(msg) default: time.Sleep(time.Millisecond * 10) } } } func getCompareMsg(data []byte) string{ sender <- data return <- receiver } // 获取本机ip func GetLocalIP() (ipv4 string, err error) { var ( addrs []net.Addr addr net.Addr ipNet *net.IPNet // IP地址 isIpNet bool ) // 获取所有网卡 if addrs, err = net.InterfaceAddrs(); err != nil { return } // 取第一个非lo的网卡IP for _, addr = range addrs { // 这个网络地址是IP地址: ipv4, ipv6 if ipNet, isIpNet = addr.(*net.IPNet); isIpNet && !ipNet.IP.IsLoopback() { // 跳过IPV6 if ipNet.IP.To4() != nil { ipv4 = ipNet.IP.String() // 192.168.1.1 return } } } err = errors.New("ipv4 not found") return }