---
panlei
2019-11-13 dd633efd5fcb1d18517f1203b74f6fe71661b3c5
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
package main
 
import (
    "basic.com/pubsub/protomsg.git"
    "basic.com/valib/logger.git"
    "github.com/knetic/govaluate"
    "ruleprocess/ruleserver"
    "ruleprocess/structure"
    "strconv"
    "sync"
)
 
func Entrance(rule *protomsg.Rule, am *structure.AreaMap,lable *structure.Others,args *structure.SdkDatas,message *protomsg.SdkMessage) structure.LittleRuleResult {
    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 == "duration" {
            return CompareAndSave(rule,am,lable,args,message)
        } else {
            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
            if rule.SdkArgAlias == "score" {
                formula = strconv.FormatFloat(arg.Score, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
                logger.Info("当前相似度小公式:", formula)
            } else if rule.SdkArgAlias == "proportion" {
                formula = strconv.FormatFloat(arg.Proportion, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
                logger.Info("当前占比小公式:", formula)
            } else {
                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{}
}
 
// 判断两个矩形的重合度,把面积更大的做分母,即取小值
func PgsInterPercent(pgpts []structure.Point, box structure.Rect, widthScale float64, heightScale float64) (percent float64) {
 
    areapts, areaBox := ruleserver.GetLocation(box, 10)
    var count = 0
    for _, pts := range areapts {
        if ruleserver.PintIsInPolygon(pts, pgpts, widthScale, heightScale) {
            count++
        }
    }
    perInterBox := float64(count) / float64(len(areapts)) // 重合面积占矩形的比例
    areaInter := perInterBox * areaBox
    areaPg := ruleserver.ComputePolygonArea(pgpts)
    perInterPg := areaInter / areaPg // 重合面积占多边形区域的比例
    // 哪个占的比例小按哪个计算,比如人站起来了,大框套住了小框
    if perInterBox < perInterPg {
        return (perInterBox * 100)
    }
    return (perInterPg * 100)
}
// 判断一个区域内有没有静止的目标
func CompareAndSave(rule *protomsg.Rule, am *structure.AreaMap,lable *structure.Others,args *structure.SdkDatas,message *protomsg.SdkMessage) structure.LittleRuleResult {
    initN := 60
    if rule.SdkId == "个体静止" && rule.SdkArgAlias == "duration" {
        if init,err := strconv.Atoi(rule.SdkArgValue); err != nil {
            logger.Debug("个体静止算法读取持续时间失败",err)
        } else {
            initN = init
        }
    }
    if len(structure.StaticMap[am.AreaId].Targets) == 0 { // 即第一帧数据(也不一定),还没有缓存
        objs := []*structure.Obj{}
        for _, tar := range am.FilterData {
            obj := &structure.Obj{Id: tar.Id, Location: tar.Location, N: initN,InitN:initN}
            objs = append(objs, obj)
        }
        structure.StaticMap[am.AreaId] = &structure.CameraArea{objs}
        return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort}
    } else {
        flag := "false"
        // 以之前静止的对象为主判断是否静止
        tars := []*structure.Arg{}
        for _, tar := range structure.StaticMap[am.AreaId].Targets {
            singleResult,arg := SingleStatic(tar,am,lable,90)
            if singleResult {
                flag = "true"
                tars = append(tars,arg)
            }
        }
        // 把满足条件的目标放进areaMap中
        am.AlarmObj = tars
        // 更新数据,把新来的数据写入缓存
        objs := []*structure.Obj{}
        for _, tar := range am.FilterData {
            flag1 := false
            for _, OBJ := range structure.StaticMap[am.AreaId].Targets {
                if tar.Id == OBJ.Id {
                    flag1 = true
                }
            }
            if !flag1 { // 集合中没有的才插入
                obj := &structure.Obj{Id: tar.Id, Location: tar.Location, N: initN,InitN:initN,AlarmFlag: false, BufferFlag: 10, CacheSdkData: structure.ResultMsg{message, nil}}
                objs = append(objs, obj)
            }
        }
        structure.StaticMap[am.AreaId] = &structure.CameraArea{objs}
        return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + flag, rule.Sort}
    }
}
 
// rec变为[t]point 逆时针一圈的坐标
func Rect2Point(rect structure.Rect) []structure.Point {
    points := []structure.Point{}
    point1 := structure.Point{rect.X, rect.Y}
    points = append(points, point1)
    point2 := structure.Point{rect.X, rect.Y + rect.Height}
    points = append(points, point2)
    point3 := structure.Point{rect.X + rect.Width, rect.Y + rect.Height}
    points = append(points, point3)
    point4 := structure.Point{rect.X + rect.Width, rect.Y}
    points = append(points, point4)
    return points
}
 
// 判断一个目标是否静止了指定时间
func SingleStatic(person *structure.Obj, am *structure.AreaMap,lable *structure.Others, argValue float64) (bool,*structure.Arg){
    flag := false
    var o *structure.Arg = nil
    for _, obj := range am.FilterData {
        if person.Id == obj.Id {
            coincidenceDegree := PgsInterPercent(Rect2Point(person.Location), obj.Location, 1, 1)
            o = obj
            if coincidenceDegree >= argValue {
                flag = true
            }
        }
    }
    if flag { // 有一个对象保持静止(id相等并且重合度高于阈值)
        flagTime := TimerAlarm(lable,person,flag,am.AreaId)
        if flagTime == "10" || flagTime == "11" {
            return flag,o
        } else {
            return false,o
        }
    } else {
        TimerAlarm(lable,person,flag,am.AreaId)
        return flag,o
    }
}
var rw sync.RWMutex
// 判断是否符合定时器条件
func TimerAlarm(oth *structure.Others,person *structure.Obj, result bool,areaId string) (string) {
    var flagTime string //
 
    rw.Lock()
 
        if result { // 结果为真
            for k, tar := range structure.StaticMap[areaId].Targets {
                if tar.Id == person.Id {
                    if tar.N == 0 && tar.AlarmFlag {
                        logger.Debug("-------------------------符合持续时间规则但并不是首次,不报警")
                        flagTime = "11"
                        oth.TimeLabel = flagTime
                    }
                    if tar.N == 0 && !tar.AlarmFlag { // 这组规则的定时器要全部等于0   暂且认为一组规则只有一个定时器
                        logger.Debug("———————————-------------首次符合持续时间规则并报警")
                        flagTime = "10"
                        tar.AlarmFlag = true
                        oth.CacheData = []structure.ResultMsg{}
                        oth.CacheData = append(oth.CacheData,tar.CacheSdkData)
                        oth.TimeLabel = flagTime
                    }
                    if tar.N != 0 {
                        flagTime = "00"
                        // 有定时器但不为0把已打的标签删除
                        // args.RuleResult = nil
                        logger.Debug("------------------------结果为真但计数器不到0,不报警,此时的计数器", k, "的值为:", tar.N)
                    }
                }
            }
        } else { // 结果为假 干掉这个计数器
            for index, tar := range structure.StaticMap[areaId].Targets {
                if tar.Id == person.Id {
                    if tar.AlarmFlag {
                        if tar.BufferFlag == 0 {
                            logger.Debug("------------------------------杀死计数器,报警此帧状态改变的数据,此时的计数器的值为", tar.N)
                            flagTime = "12"
                            oth.TimeLabel = flagTime
                            structure.StaticMap[areaId].Targets = append(structure.StaticMap[areaId].Targets[:index],structure.StaticMap[areaId].Targets[index+1:]...)
                        } else {
                            if tar.BufferFlag > 0 {
                                logger.Debug("缓冲区减减")
                                tar.BufferFlag--
                            }
                        }
                    } else {
                        logger.Debug("-----------结果为假且不到0,杀死定时器")
                        structure.StaticMap[areaId].Targets = append(structure.StaticMap[areaId].Targets[:index],structure.StaticMap[areaId].Targets[index+1:]...)
                    }
                }
            }
        }
 
    rw.Unlock()
    return flagTime
}