public Rectangle GetDetectionWindow(float upScale)
            {
                var r = _DetectionT0.HasValue
                    ?
                        DetectedFrame.GetNextDetectionWindow(_DetectionT0.Value, _DetectionT1.Value, upScale)
                    :
                        DetectedFrame.GetNextDetectionWindow(_DetectionT1.Value, upScale);

                return(Rectangle.Round(r));
            }
            public DetectedFrame?_DetectionT1;  // frame t-1

            public void AddDetection(DetectedFrame d)
            {
                if (_DetectionT1.HasValue)
                {
                    if (_DetectionT1.Value.Time >= d.Time)
                    {
                        _DetectionT1 = d;
                        return;
                    }
                }

                _DetectionT0 = _DetectionT1;
                _DetectionT1 = d;
            }
 public _TrackedObject(DetectedFrame detection)
 {
     AddDetection(detection);
 }
        public void Inference(DetectedObject.Collection result, InferenceInput <PointerBitmap> input, Rectangle?inputWindow = null)
        {
            // if we don't have any tracked face
            // or the tracked faces have a very low confidence,
            // try find new ones:

            // result.Clear();

            _Stats_AddNarrowScore(input.CaptureTime, Score.Zero);
            _Stats_AddBroadScore(input.CaptureTime, Score.Zero);

            if (_BroadTracked.Count == 0)
            {
                var seeds = new DetectedObject.Collection(new SizeF(input.Content.Width, input.Content.Height));
                _BroadDetector.Inference(seeds, input, inputWindow);

                var tracked = seeds.Objects
                              .Where(item => item.Name == _ObjectFilter)
                              .Where(item => item.Score.IsValid)
                              .Select(item => new DetectedFrame(item.Rect, _BroadOutputScale, input.CaptureTime, item.Score))
                              .ToList();

                DetectedFrame.RemoveOverlapping(tracked);

                _BroadTracked.Clear();
                _BroadTracked.AddRange(tracked.Select(item => new _TrackedObject(item)));

                foreach (var o in _BroadTracked.ToList())
                {
                    var r = o.GetDetectionWindow(1);
                    result.AddObject(r, o._DetectionT1.Value.Score, "Detected");

                    _Stats_AddBroadScore(input.CaptureTime, o._DetectionT1.Value.Score);
                }
            }

            foreach (var o in _BroadTracked.ToList())
            {
                var broadRect = Rectangle.Round(_NarrowDetector.GetNextDetectionWindow(o._DetectionT1.Value, o._DetectionT0));

                _NarrowTracked.Clear();
                _NarrowTracked.SetFrameSize(input);
                _NarrowDetector.Inference(_NarrowTracked, input, broadRect);

                var item = _NarrowTracked
                           .Objects
                           .Where(ttt => ttt.Name == _ObjectFilter)
                           .Where(ttt => ttt.Score.IsValid)
                           .FirstOrDefault();

                if (item.Name == null || item.Area < 16) // tracking lost
                {
                    _BroadTracked.Remove(o);
                }
                else
                {
                    result.Add(_NarrowTracked, result.AddObject(broadRect, item.Score, "Window"));

                    // update the broad tracking window for this face
                    o.AddDetection(new DetectedFrame(item.Rect, input.CaptureTime, item.Score));
                }

                _Stats_AddNarrowScore(input.CaptureTime, item.Score);
            }
        }