---
panlei
2019-12-13 6fd9af45e0cd30838b221f759ba59adc50653093
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
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
}