Beispiel #1
0
        private void NonMaximumSuppression(List <FaceInfo> input, List <FaceInfo> output, float nmsThreshold = 0.3f, NonMaximumSuppressionMode type = NonMaximumSuppressionMode.Minimum)
        {
            if (!input.Any())
            {
                return;
            }

            input.Sort((f1, f2) => f1.Score.CompareTo(f2.Score));

            var nPick    = 0;
            var vScores  = new List <Tuple <float, int> >();
            var numBoxes = input.Count;
            var vPick    = new int[numBoxes];

            for (var i = 0; i < numBoxes; ++i)
            {
                vScores.Add(new Tuple <float, int>(input[i].Score, i));
            }

            while (vScores.Count > 0)
            {
                var last = vScores.Last().Item2;
                vPick[nPick] = last;
                nPick       += 1;

                for (var index = 0; index < vScores.Count;)
                {
                    var it        = vScores[index];
                    var itemIndex = it.Item2;

                    var maxX = Math.Max(input[itemIndex].X1, input[last].X1);
                    var maxY = Math.Max(input[itemIndex].Y1, input[last].Y1);
                    var minX = Math.Min(input[itemIndex].X2, input[last].X2);
                    var minY = Math.Min(input[itemIndex].Y2, input[last].Y2);
                    //maxX1 and maxY1 reuse
                    maxX = ((minX - maxX + 1) > 0) ? (minX - maxX + 1) : 0;
                    maxY = ((minY - maxY + 1) > 0) ? (minY - maxY + 1) : 0;
                    //IOU reuse for the area of two bbox
                    var iou = maxX * maxY;
                    switch (type)
                    {
                    case NonMaximumSuppressionMode.Union:
                        iou = iou / (input[itemIndex].Area + input[last].Area - iou);
                        break;

                    case NonMaximumSuppressionMode.Minimum:
                        iou = iou / ((input[itemIndex].Area < input[last].Area) ? input[itemIndex].Area : input[last].Area);
                        break;
                    }

                    if (iou > nmsThreshold)
                    {
                        vScores.RemoveAt(index);
                    }
                    else
                    {
                        index++;
                    }
                }
            }

            Array.Resize(ref vPick, nPick);
            Resize(output, nPick);
            for (var i = 0; i < nPick; i++)
            {
                output[i] = input[vPick[i]];
            }
        }
        private void NonMaximumSuppression(List <FaceInfo> input, ICollection <FaceInfo> output, NonMaximumSuppressionMode type = NonMaximumSuppressionMode.Blending)
        {
            input.Sort((f1, f2) => f1.Score.CompareTo(f2.Score));

            var boxNum = input.Count;

            var merged = new int[boxNum];

            for (var i = 0; i < boxNum; i++)
            {
                if (merged[i] > 0)
                {
                    continue;
                }

                var buf = new List <FaceInfo>
                {
                    input[i]
                };

                merged[i] = 1;

                var h0 = input[i].Y2 - input[i].Y1 + 1;
                var w0 = input[i].X2 - input[i].X1 + 1;

                var area0 = h0 * w0;

                for (var j = i + 1; j < boxNum; j++)
                {
                    if (merged[j] > 0)
                    {
                        continue;
                    }

                    var innerX0 = input[i].X1 > input[j].X1 ? input[i].X1 : input[j].X1;
                    var innerY0 = input[i].Y1 > input[j].Y1 ? input[i].Y1 : input[j].Y1;

                    var innerX1 = input[i].X2 < input[j].X2 ? input[i].X2 : input[j].X2;
                    var innerY1 = input[i].Y2 < input[j].Y2 ? input[i].Y2 : input[j].Y2;

                    var innerH = innerY1 - innerY0 + 1;
                    var innerW = innerX1 - innerX0 + 1;

                    if (innerH <= 0 || innerW <= 0)
                    {
                        continue;
                    }

                    var innerArea = innerH * innerW;

                    var h1 = input[j].Y2 - input[j].Y1 + 1;
                    var w1 = input[j].X2 - input[j].X1 + 1;

                    var area1 = h1 * w1;

                    var score = innerArea / (area0 + area1 - innerArea);

                    if (score > this._IouThreshold)
                    {
                        merged[j] = 1;
                        buf.Add(input[j]);
                    }
                }

                switch (type)
                {
                case NonMaximumSuppressionMode.Hard:
                {
                    output.Add(buf[0]);
                    break;
                }

                case NonMaximumSuppressionMode.Blending:
                {
                    var total = 0d;
                    for (var j = 0; j < buf.Count; j++)
                    {
                        total += Math.Exp(buf[j].Score);
                    }

                    var rects = new FaceInfo();
                    for (var j = 0; j < buf.Count; j++)
                    {
                        var rate = Math.Exp(buf[j].Score) / total;
                        rects.X1    += (float)(buf[j].X1 * rate);
                        rects.Y1    += (float)(buf[j].Y1 * rate);
                        rects.X2    += (float)(buf[j].X2 * rate);
                        rects.Y2    += (float)(buf[j].Y2 * rate);
                        rects.Score += (float)(buf[j].Score * rate);
                    }

                    output.Add(rects);
                    break;
                }

                default:
                    //{
                    //    Console.WriteLine("wrong type of nms.");
                    //    exit(-1);
                    //}
                    break;
                }
            }

            #endregion

            #endregion
        }