New file |
| | |
| | | package ruleserver |
| | | |
| | | import ( |
| | | "math" |
| | | ) |
| | | |
| | | func min(num1 float64, num2 float64) float64 { |
| | | if num1 < num2 { |
| | | return num1 |
| | | } |
| | | return num2 |
| | | |
| | | } |
| | | |
| | | func max(num1 float64, num2 float64) float64 { |
| | | if num1 < num2 { |
| | | return num2 |
| | | } |
| | | return num1 |
| | | } |
| | | |
| | | //Point 坐标点 |
| | | type Point struct { |
| | | X float64 `json:"x"` |
| | | Y float64 `json:"y"` |
| | | } |
| | | |
| | | //Rect 检测目标 |
| | | type Rect struct { |
| | | X float64 |
| | | Y float64 |
| | | Width float64 |
| | | Height float64 |
| | | } |
| | | |
| | | //Pointfloat 坐标点 |
| | | type Pointfloat struct { |
| | | X float64 `json:"x"` |
| | | Y float64 `json:"y"` |
| | | } |
| | | |
| | | //PintIsInPolygon 判断点是否在多边形内部 |
| | | //point为要判断的坐标点 |
| | | //polygon是多边形各点数组 |
| | | func pintIsInPolygon(point Pointfloat, polygon []Point, widthScale float64, heightScale float64) bool { |
| | | var nCross int = 0 |
| | | for i := 0; i < len(polygon); i++ { |
| | | |
| | | p1 := polygon[i] |
| | | p2 := polygon[(i+1)%len(polygon)] |
| | | // 根据摄像机所拍图像与前端画布的比例将区域放大 |
| | | p1.X = p1.X * widthScale |
| | | p1.Y = p1.Y * heightScale |
| | | p2.X = p2.X * widthScale |
| | | p2.Y = p2.Y * heightScale |
| | | if p1.Y == p2.Y { |
| | | continue |
| | | } |
| | | if point.Y < min(p1.Y, p2.Y) { |
| | | continue |
| | | } |
| | | if point.Y > max(p1.Y, p2.Y) { |
| | | continue |
| | | } |
| | | X := (point.Y-p1.Y)*(p2.X-p1.X)/(p2.Y-p1.Y) + p1.X |
| | | |
| | | if X > point.X { |
| | | nCross++ |
| | | } |
| | | } |
| | | return nCross%2 != 0 |
| | | } |
| | | |
| | | //GetLocation 将一个给定起始坐标,宽度长度的矩形区域均分为n方份并返回中心坐标(n为单边平分数值)和面积 |
| | | func getLocation(rect Rect, n int) ([]Pointfloat, float64) { |
| | | xArr := make([]float64, n) // 用切片不用数组,数组不能用变量定义长度 |
| | | yArr := make([]float64, n) |
| | | pointArr := make([]Pointfloat, 0, n*n) |
| | | for i := 0; i < n; i++ { |
| | | xArr[i] = rect.X + (rect.Width/float64(2*n))*float64(2*i+1) |
| | | yArr[i] = rect.Y + (rect.Height/float64(2*n))*float64(2*i+1) |
| | | } |
| | | for i := 0; i < n; i++ { |
| | | for j := 0; j < n; j++ { |
| | | point := Pointfloat{X: xArr[i], Y: yArr[j]} |
| | | pointArr = append(pointArr, point) |
| | | } |
| | | } |
| | | s := rect.Width * rect.Height |
| | | return pointArr, s |
| | | } |
| | | |
| | | //ComputePolygonArea 计算任意多边形面积 |
| | | func computePolygonArea(polygon []Point) float64 { |
| | | pointNum := len(polygon) |
| | | var s float64 = 0 |
| | | if pointNum < 3 { |
| | | s = 0 |
| | | } |
| | | for i := 0; i < pointNum; i++ { |
| | | s += polygon[i].X*polygon[(i+1)%pointNum].Y - polygon[i].Y*polygon[(i+1)%pointNum].X |
| | | } |
| | | area := math.Abs(s / 2) |
| | | return area |
| | | } |
| | | |
| | | //PgsInterPercent calculate percent of two polygon intersection 计算两个多边形的重叠占比 |
| | | func PgsInterPercent(pgpts []Point, box Rect, widthScale float64, heightScale float64) (percent float64) { |
| | | |
| | | areapts, areaBox := getLocation(box, 10) |
| | | var count = 0 |
| | | for _, pts := range areapts { |
| | | if pintIsInPolygon(pts, pgpts, widthScale, heightScale) { |
| | | count++ |
| | | } |
| | | } |
| | | perInterBox := float64(count) / float64(len(areapts)) // 重合面积占矩形的比例 |
| | | areaInter := perInterBox * areaBox |
| | | areaPg := computePolygonArea(pgpts) |
| | | perInterPg := areaInter / areaPg // 重合面积占多边形区域的比例 |
| | | // 哪个占的比例大按哪个计算 |
| | | if perInterBox > perInterPg { |
| | | return (perInterBox*100) |
| | | } |
| | | return (perInterPg*100) |
| | | } |