private EnclosingRectangle FindEnclosingRectangle(ref Image <Gray, byte> grayscaleImage, Point center, ref Image <Rgb, byte> debugImage, Rectangle roi)
        {
            var binaryThreshold      = BinaryThreshold;
            var binaryThresholdImage = grayscaleImage.ThresholdBinary(new Gray(binaryThreshold), Grays.White);

            #region Debug Binary Image

            // Binary Threshold Image
            var binaryThresholdImageCopy = binaryThresholdImage.Copy();
            Task.Factory.StartNew(() =>
            {
                var bitmapSource = binaryThresholdImageCopy.ToBitmapSource(true);
                binaryThresholdImageCopy.Dispose();
                return(bitmapSource);
            }).ContinueWith(t => BinaryThresholdImageBitmapSource = t.Result);

            #endregion

            var floodFillImage = binaryThresholdImage.Copy();
            binaryThresholdImage.Dispose();

            var imageWidth  = floodFillImage.Width;
            var imageHeight = floodFillImage.Height;

            MCvConnectedComp comp;

            // mask needs to be 2 pixels wider and 2 pixels taller
            var mask = new Image <Gray, byte>(imageWidth + 2, imageHeight + 2);
            CvInvoke.cvFloodFill(floodFillImage, center, new MCvScalar(255), new MCvScalar(FloodFillDifference), new MCvScalar(FloodFillDifference), out comp, CONNECTIVITY.FOUR_CONNECTED, FLOODFILL_FLAG.DEFAULT, mask);

            #region Debug Flood Fill Image

            //// Flood fill image
            //var maskCopy = floodFillImage.Copy();
            //Task.Factory.StartNew(() =>
            //{
            //    var bitmapSource = maskCopy.ToBitmapSource(true);
            //    maskCopy.Dispose();
            //    return bitmapSource;
            //}).ContinueWith(t => BinaryThresholdImageBitmapSource = t.Result);

            #endregion

            // shrink mask back to original grayscale image size
            mask.ROI = new Rectangle(1, 1, imageWidth, imageHeight);
            var contourBinaryImage = mask.Mul(255);

            #region Debug Output Binary Image

            //var maskCopy = contourBinaryImage.Copy();
            //Task.Factory.StartNew(() =>
            //{
            //    var bitmapSource = maskCopy.ToBitmapSource(true);
            //    maskCopy.Dispose();
            //    return bitmapSource;
            //}).ContinueWith(t => BinaryThresholdImageBitmapSource = t.Result);

            #endregion

            mask.Dispose();
            floodFillImage.Dispose();

            EnclosingRectangle enclosingRectangle = null;
            using (var storage = new MemStorage())
            {
                for (
                    var contours = contourBinaryImage.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                                                                   RETR_TYPE.CV_RETR_EXTERNAL, storage);
                    contours != null;
                    contours = contours.HNext)
                {
                    var contour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);

                    var contourBounds = contour.BoundingRectangle;
                    if (contourBounds.Width + 5 >= roi.Width || contourBounds.Height + 5 >= roi.Height)
                    {
                        continue;
                    }

                    if (!EmguExtensions.IsRectangle(contour, 10.0))
                    {
                        continue;
                    }

                    var edges = GetRightAngleEdges(contour);

                    if (IsRenderContent)
                    {
                        var debugImageRoi = debugImage.ROI;
                        debugImage.ROI = roi;
                        debugImage.Draw(contour.GetConvexHull(ORIENTATION.CV_CLOCKWISE), Rgbs.Cyan, 2);
                        debugImage.Draw(contour.GetMinAreaRect(storage), Rgbs.Cyan, 2);

                        DrawEdge(ref debugImage, edges[0], Rgbs.Red);
                        DrawEdge(ref debugImage, edges[1], Rgbs.Green);

                        debugImage.ROI = debugImageRoi;
                    }

                    enclosingRectangle = new EnclosingRectangle
                    {
                        Contour   = contour,
                        LongEdge  = edges[0],
                        ShortEdge = edges[1]
                    };
                }
            }

            contourBinaryImage.Dispose();

            return(enclosingRectangle);
        }
 internal void Sample(EnclosingRectangle rectangle)
 {
     DisplaySamples[SampleCounter] = rectangle;
     SampleCounter++;
 }
 internal void Sample(EnclosingRectangle rectangle)
 {
     DisplaySamples[SampleCounter] = rectangle;
     SampleCounter++;
 }
        private EnclosingRectangle FindEnclosingRectangle(ref Image<Gray, byte> grayscaleImage, Point center, ref Image<Rgb, byte> debugImage, Rectangle roi)
        {
            var binaryThreshold = BinaryThreshold;
            var binaryThresholdImage = grayscaleImage.ThresholdBinary(new Gray(binaryThreshold), Grays.White);

            #region Debug Binary Image

            // Binary Threshold Image
            var binaryThresholdImageCopy = binaryThresholdImage.Copy();
            Task.Factory.StartNew(() =>
            {
                var bitmapSource = binaryThresholdImageCopy.ToBitmapSource(true);
                binaryThresholdImageCopy.Dispose();
                return bitmapSource;
            }).ContinueWith(t => BinaryThresholdImageBitmapSource = t.Result);

            #endregion

            var floodFillImage = binaryThresholdImage.Copy();
            binaryThresholdImage.Dispose();

            var imageWidth = floodFillImage.Width;
            var imageHeight = floodFillImage.Height;

            MCvConnectedComp comp;

            // mask needs to be 2 pixels wider and 2 pixels taller
            var mask = new Image<Gray, byte>(imageWidth + 2, imageHeight + 2);
            CvInvoke.cvFloodFill(floodFillImage, center, new MCvScalar(255), new MCvScalar(FloodFillDifference), new MCvScalar(FloodFillDifference), out comp, CONNECTIVITY.FOUR_CONNECTED, FLOODFILL_FLAG.DEFAULT, mask);

            #region Debug Flood Fill Image

            //// Flood fill image
            //var maskCopy = floodFillImage.Copy();
            //Task.Factory.StartNew(() =>
            //{
            //    var bitmapSource = maskCopy.ToBitmapSource(true);
            //    maskCopy.Dispose();
            //    return bitmapSource;
            //}).ContinueWith(t => BinaryThresholdImageBitmapSource = t.Result);

            #endregion

            // shrink mask back to original grayscale image size
            mask.ROI = new Rectangle(1, 1, imageWidth, imageHeight);
            var contourBinaryImage = mask.Mul(255);

            #region Debug Output Binary Image

            //var maskCopy = contourBinaryImage.Copy();
            //Task.Factory.StartNew(() =>
            //{
            //    var bitmapSource = maskCopy.ToBitmapSource(true);
            //    maskCopy.Dispose();
            //    return bitmapSource;
            //}).ContinueWith(t => BinaryThresholdImageBitmapSource = t.Result);

            #endregion

            mask.Dispose();
            floodFillImage.Dispose();

            EnclosingRectangle enclosingRectangle = null;
            using (var storage = new MemStorage())
            {
                for (
                    var contours = contourBinaryImage.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                        RETR_TYPE.CV_RETR_EXTERNAL, storage);
                    contours != null;
                    contours = contours.HNext)
                {
                    var contour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);

                    var contourBounds = contour.BoundingRectangle;
                    if (contourBounds.Width + 5 >= roi.Width || contourBounds.Height + 5 >= roi.Height)
                        continue;

                    if (!EmguExtensions.IsRectangle(contour, 10.0)) continue;

                    var edges = GetRightAngleEdges(contour);

                    if (IsRenderContent)
                    {
                        var debugImageRoi = debugImage.ROI;
                        debugImage.ROI = roi;
                        debugImage.Draw(contour.GetConvexHull(ORIENTATION.CV_CLOCKWISE), Rgbs.Cyan, 2);
                        debugImage.Draw(contour.GetMinAreaRect(storage), Rgbs.Cyan, 2);

                        DrawEdge(ref debugImage, edges[0], Rgbs.Red);
                        DrawEdge(ref debugImage, edges[1], Rgbs.Green);

                        debugImage.ROI = debugImageRoi;
                    }

                    enclosingRectangle = new EnclosingRectangle
                    {
                        Contour = contour,
                        LongEdge = edges[0],
                        ShortEdge = edges[1]
                    };
                }
            }

            contourBinaryImage.Dispose();

            return enclosingRectangle;
        }