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(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}
|
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,90)
|
if singleResult {
|
flag = "true"
|
tars = append(tars,arg)
|
logger.Info("静止的目标:",arg.Id,arg.Location,arg.Score)
|
}
|
}
|
|
// 把满足条件的目标放进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){
|
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(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 //
|
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"
|
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
|
}
|