private void GenerateBBox(ICollection <FaceInfo> boundingBoxCollection, Mat scores, Mat boxes, float scoreThreshold, int numAnchors)
        {
            for (var i = 0; i < numAnchors; i++)
            {
                if (scores.Channel(0)[i * 2 + 1] > scoreThreshold)
                {
                    var rects   = new FaceInfo();
                    var xCenter = boxes.Channel(0)[i * 4] * CenterVariance * this._Priors[i][2] + this._Priors[i][0];
                    var yCenter = boxes.Channel(0)[i * 4 + 1] * CenterVariance * this._Priors[i][3] + this._Priors[i][1];
                    var w       = Math.Exp(boxes.Channel(0)[i * 4 + 2] * SizeVariance) * this._Priors[i][2];
                    var h       = Math.Exp(boxes.Channel(0)[i * 4 + 3] * SizeVariance) * this._Priors[i][3];

                    rects.X1    = Clip(xCenter - w / 2.0, 1) * this._ImageW;
                    rects.Y1    = Clip(yCenter - h / 2.0, 1) * this._ImageH;
                    rects.X2    = Clip(xCenter + w / 2.0, 1) * this._ImageW;
                    rects.Y2    = Clip(yCenter + h / 2.0, 1) * this._ImageH;
                    rects.Score = Clip(scores.Channel(0)[i * 2 + 1], 1);

                    boundingBoxCollection.Add(rects);
                }
            }
        }
        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
        }