| | |
| | | "ruleprocess/ruleserver" |
| | | "ruleprocess/structure" |
| | | "strconv" |
| | | "sync" |
| | | ) |
| | | |
| | | //个体静止算法 |
| | | var StaticMap = make(map[string]CameraArea) |
| | | 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" { |
| | | |
| | | type CameraArea struct { |
| | | targets []Obj |
| | | duration int |
| | | cache structure.ResultMsg |
| | | } |
| | | type Obj struct { |
| | | id string |
| | | location []structure.Rect |
| | | staticStatus int |
| | | } |
| | | |
| | | func Entrance(rule *protomsg.Rule, am *structure.AreaMap) structure.LittleRuleResult { |
| | | for _, obj := range am.FilterData { |
| | | var flag bool = true |
| | | for k, _ := range ruleserver.TimeEleList { |
| | | if k == rule.Id+""+strconv.Itoa(int(obj.Id)) { |
| | | flag = false // 有就置为false |
| | | logger.Info("有这个定时器,不再创建了:") |
| | | } |
| | | lr := CompareAndSave(rule,am,lable,args,message) |
| | | logger.Info("个体静止规则结果:",lr) |
| | | return lr |
| | | } else { |
| | | return structure.LittleRuleResult{} |
| | | } |
| | | if flag { |
| | | timeEle := ruleserver.TimeElement{N: 10, InitN: 10, AlarmFlag: false, BufferFlag: 5} // 扔进去一个定时器元素 |
| | | ruleserver.TimeEleList[rule.Id+""+strconv.Itoa(int(obj.Id))] = &timeEle // 定时器元素以小规则id和目标id为键 |
| | | } |
| | | } else { |
| | | return structure.LittleRuleResult{} |
| | | } |
| | | return structure.LittleRuleResult{} |
| | | } |
| | | |
| | | // 过滤规则先筛选出符合条件的目标数量 |
| | | func filterRule(rule *protomsg.Rule, am *structure.AreaMap) structure.LittleRuleResult { |
| | | // 处理的都是yolo数据 |
| | | 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) |
| | | if rule.SdkArgAlias == "score" || rule.SdkArgAlias == "proportion" || rule.SdkArgAlias == "size" { // 判断的是相似值,占比,尺寸等过滤条件,如果再有,还可以再加 |
| | | var args []*structure.Arg |
| | | if rule.RuleWithPre == "&&" { |
| | | args = am.FilterData |
| | | } else { |
| | | formula = strconv.FormatFloat(arg.Size, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式 |
| | | logger.Info("当前尺寸小公式:", formula) |
| | | args = am.Args |
| | | } |
| | | expression, _ := govaluate.NewEvaluableExpression(formula) // 得到数学公式 |
| | | result, _ := expression.Evaluate(nil) // 得到数学公式的结果 |
| | | if result.(bool) { |
| | | am.FilterData = append(am.FilterData, arg) // 得到符合条件的过滤数据 |
| | | // 先清空过滤后的数据,再往里塞本次过滤后的数据 |
| | | 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} |
| | | } |
| | | } |
| | | 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} |
| | | } |
| | | return structure.LittleRuleResult{} |
| | | } |
| | | |
| | | // 判断两个矩形的重合度,把面积更大的做分母 |
| | | // 判断两个矩形的重合度,把面积更大的做分母,即取小值 |
| | | func PgsInterPercent(pgpts []structure.Point, box structure.Rect, widthScale float64, heightScale float64) (percent float64) { |
| | | |
| | | areapts, areaBox := ruleserver.GetLocation(box, 10) |
| | |
| | | } |
| | | return (perInterPg * 100) |
| | | } |
| | | // 判断一个区域内有没有静止的目标 |
| | | func CompareAndSave(rule *protomsg.Rule, am *structure.AreaMap,lable *structure.Others,args *structure.SdkDatas,message *protomsg.SdkMessage) structure.LittleRuleResult { |
| | | defer func() { |
| | | if err := recover(); err != nil { |
| | | logger.Error("个体静止规则有误", err) |
| | | } |
| | | }() |
| | | logger.Info("走了个体静止核心算法") |
| | | initN := 5 |
| | | if rule.SdkId == "812b674b-2375-4589-919a-5c1c3278a977" && rule.SdkArgAlias == "duration" { |
| | | if init,err := strconv.Atoi(rule.SdkArgValue); err != nil { |
| | | logger.Debug("个体静止算法读取持续时间失败",err) |
| | | } else { |
| | | initN = init |
| | | } |
| | | } |
| | | if len(am.FilterData) < 0 { |
| | | logger.Info("本帧区域内无数据,返回") |
| | | // 清空缓存的目标 |
| | | |
| | | return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort} |
| | | } |
| | | m := make(map[string]interface{}) |
| | | m["target"] = []structure.Result{} |
| | | m["target"] = append(m["target"].([]structure.Result), structure.Result{args.TaskId, "", "", true, 0, "", am.FilterData, am.AreaJson, false,*lable}) |
| | | |
| | | if structure.StaticMap[am.AreaId] == nil || len(structure.StaticMap[am.AreaId].Targets) == 0 { |
| | | logger.Info("之前无缓存并且此次区域内有人") |
| | | |
| | | objs := []*structure.Obj{} |
| | | for _, tar := range am.FilterData { |
| | | obj := &structure.Obj{Id: tar.Id, Location: tar.Location, N: initN, InitN:initN, AlarmFlag: false, BufferFlag: 10, CacheSdkData:structure.ResultMsg{message, m}} |
| | | objs = append(objs, obj) |
| | | } |
| | | structure.StaticMap[am.AreaId] = &structure.CameraArea{objs} |
| | | return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort} |
| | | } else { |
| | | logger.Info("之前有缓存") |
| | | flag := "false" |
| | | // 以之前静止的对象为主判断是否静止 |
| | | tars := []*structure.Arg{} |
| | | //logger.Info("看一下静止区域内的目标:",am.AreaId) |
| | | //for _, tar := range structure.StaticMap[am.AreaId].Targets { |
| | | // logger.Info("具体目标:",tar.Location) |
| | | //} |
| | | for _, tar := range structure.StaticMap[am.AreaId].Targets { |
| | | singleResult,arg := SingleStatic(tar,am,lable,95) |
| | | if singleResult { |
| | | flag = "true" |
| | | tars = append(tars,arg) |
| | | logger.Info("静止的目标:",arg.Id,arg.Location,arg.Score) |
| | | } |
| | | } |
| | | |
| | | // 把满足条件的目标放进areaMap中 |
| | | am.AlarmObj = tars |
| | | // 更新数据,把新来的数据写入缓存 |
| | | 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, m}} |
| | | structure.StaticMap[am.AreaId].Targets = append(structure.StaticMap[am.AreaId].Targets, obj) |
| | | } |
| | | } |
| | | 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){ |
| | | logger.Info("单个目标的判断:") |
| | | 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) |
| | | logger.Info("判断目标的重合度",coincidenceDegree) |
| | | o = obj |
| | | if coincidenceDegree >= argValue { |
| | | flag = true |
| | | } |
| | | } |
| | | } |
| | | if flag { // 当前检测对象保持静止(id相等并且重合度高于阈值) |
| | | flagTime := TimerAlarm(o,person,flag,am.AreaId) |
| | | if flagTime == "10" || flagTime == "11" { |
| | | return flag,o |
| | | } else { |
| | | return false,o |
| | | } |
| | | } else { |
| | | TimerAlarm(o,person,flag,am.AreaId) |
| | | return flag,o |
| | | } |
| | | } |
| | | var rw sync.RWMutex |
| | | // 判断是否符合定时器条件 |
| | | func TimerAlarm(o *structure.Arg,person *structure.Obj, result bool,areaId string) (string) { |
| | | var flagTime string // |
| | | logger.Info("目标的定时器:") |
| | | 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" |
| | | o.TimeLable = flagTime |
| | | o.CacheData = tar.CacheSdkData |
| | | } |
| | | if tar.N == 0 && !tar.AlarmFlag { // 这组规则的定时器要全部等于0 暂且认为一组规则只有一个定时器 |
| | | logger.Debug("———————————-------------首次符合持续时间规则并报警") |
| | | flagTime = "10" |
| | | tar.AlarmFlag = true |
| | | o.TimeLable = flagTime |
| | | o.CacheData = tar.CacheSdkData |
| | | } |
| | | 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" |
| | | 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 |
| | | } |
| | | |
| | | |