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" { lr := CompareAndSave(rule,am,lable,args,message) logger.Info("个体静止规则结果:",lr) return lr } 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 { 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 _, 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 }