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
|
logger.Info("请求张增飞比对数据参数:",trackArg)
|
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)
|
logger.Info("比完之后的数据追踪数据是:",arg)
|
//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
|
logger.Info("追踪请求通道建立")
|
if sock, err = req.NewSocket(); err != nil {
|
logger.Error("创建请求socket失败: %s", err.Error())
|
}
|
errSize := sock.SetOption(mangos.OptionMaxRecvSize,20*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+":4011"); 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
|
}
|