/// <summary> /// Removes overlaped duplicates (nms). /// </summary> private List <YoloPrediction> Supress(List <YoloPrediction> items) { var result = new List <YoloPrediction>(items); foreach (var item in items) // iterate every prediction { foreach (var current in result.ToList()) // make a copy for each iteration { if (current == item) { continue; } var(rect1, rect2) = (item.Rectangle, current.Rectangle); RectangleF intersection = RectangleF.Intersect(rect1, rect2); float intArea = intersection.Area(); // intersection area float unionArea = rect1.Area() + rect2.Area() - intArea; // union area float overlap = intArea / unionArea; // overlap ratio if (overlap >= _model.Overlap) { if (item.Score >= current.Score) { result.Remove(current); } } } } return(result); }
/// <summary> /// Changes rectangle scale by a minimum amount in term of area change to match the scale of the user-specified size scale. /// </summary> /// <param name="rect">Rectangle.</param> /// <param name="widthHeightRatio">Width / height ratio that must be satisfied.</param> /// <param name="correctLocation">Moves rectangle to minimize the impact of scaling regarding original location.</param> /// <returns>Rectangle that has the same scale as </returns> public static RectangleF ScaleTo(this RectangleF rect, float widthHeightRatio, bool correctLocation = true) { var sizeScale = widthHeightRatio; var newWidthCandidate = rect.Height * sizeScale; var newHeightCandidate = rect.Width * (1 / sizeScale); //if we choose newWidth... var newWidthAreaChangeFactor = rect.Area() / (newWidthCandidate * rect.Height); newWidthAreaChangeFactor = newWidthAreaChangeFactor - 1; //for how much the area will change (+/- X percent) //if we choose newHeight... var newHeightAreaChangeFactor = rect.Area() / (newHeightCandidate * rect.Width); newHeightAreaChangeFactor = newHeightAreaChangeFactor - 1; //for how much the area will change (+/- X percent) if (System.Math.Abs(newWidthAreaChangeFactor) < System.Math.Abs(newHeightAreaChangeFactor)) { var xOffset = 0f; if (correctLocation) { xOffset = -(newWidthCandidate - rect.Width) / 2; } return(new RectangleF(rect.X + xOffset, rect.Y, newWidthCandidate, rect.Height)); } else { var yOffset = 0f; if (correctLocation) { yOffset = -(newHeightCandidate - rect.Height) / 2; } return(new RectangleF(rect.X, rect.Y + yOffset, rect.Width, newHeightCandidate)); } }