public decimal PredictFrame(Ball b, int frame)
        {
            Image<Bgr, byte> frameImg = video.GetFrame(Camera.StartFrame + frame);

            ErodeDilateSimplifier s = new ErodeDilateSimplifier(Camera.Iterations);
            BgrThresholdsDetector d = new BgrThresholdsDetector(Camera.MinimumThresholds, Camera.MaximumThresholds);

            Image<Bgr, byte> simplifiedFrame = s.Simplify(frameImg);
            Blob prediction = d.Detect(simplifiedFrame);

            if (prediction != null)
            {
                int apparentWidth = (prediction.Contour.BoundingRectangle.Width + prediction.Contour.BoundingRectangle.Height) / 2;
                Distances[frame] = Camera.FocalLength / apparentWidth * b.Diameter;
            }
            else
            {
                Distances[frame] = -1; // Ball could not be located in the frame
            }

            return Distances[frame];
        }
        private void UpdatePreview(object sender = null, EventArgs e = null)
        {
            ErodeDilateSimplifier simplifier = new ErodeDilateSimplifier((int)configBall_iterations.Value);
            Image<Bgr, byte> simplifiedImage = simplifier.Simplify(video.GetFrame((int)configBall_previewFrame.Value));

            Bgr minimumThresholds = new Bgr((int)configBall_bMin.Value, (int)configBall_gMin.Value, (int)configBall_rMin.Value);
            Bgr maximumThresholds = new Bgr((int)configBall_bMax.Value, (int)configBall_gMax.Value, (int)configBall_rMax.Value);

            BgrThresholdsDetector detector = new BgrThresholdsDetector(minimumThresholds, maximumThresholds);
            Blob output = detector.Detect(simplifiedImage);

            if(output != null)
                simplifiedImage.Draw(output.Contour, new Bgr(Color.Azure), 0);

            configBall_preview.Image = simplifiedImage.ToBitmap();
        }