Exemplo n.º 1
0
        /// <summary>
        /// Checks if two contours intersects
        /// </summary>
        /// <param name="contour1">Contour 1</param>
        /// <param name="contour2">Contour 2</param>
        /// <returns></returns>
        public static bool ContoursIntersect(VectorOfVectorOfPoint contour1, VectorOfVectorOfPoint contour2)
        {
            var contour1Rect = CvInvoke.BoundingRectangle(contour1[0]);
            var contour2Rect = CvInvoke.BoundingRectangle(contour2[0]);

            /* early exit if the bounding rectangles don't intersect */
            if (!contour1Rect.IntersectsWith(contour2Rect))
            {
                return(false);
            }

            var minX = contour1Rect.X < contour2Rect.X ? contour1Rect.X : contour2Rect.X;
            var minY = contour1Rect.Y < contour2Rect.Y ? contour1Rect.Y : contour2Rect.Y;

            var maxX = (contour1Rect.X + contour1Rect.Width) < (contour2Rect.X + contour2Rect.Width) ? (contour2Rect.X + contour2Rect.Width) : (contour1Rect.X + contour1Rect.Width);
            var maxY = (contour1Rect.Y + contour1Rect.Height) < (contour2Rect.Y + contour2Rect.Height) ? (contour2Rect.Y + contour2Rect.Height) : (contour1Rect.Y + contour1Rect.Height);

            var totalRect = new Rectangle(minX, minY, maxX - minX, maxY - minY);

            using var contour1Mat = EmguExtensions.InitMat(totalRect.Size);
            using var contour2Mat = EmguExtensions.InitMat(totalRect.Size);

            var inverseOffset = new Point(minX * -1, minY * -1);

            CvInvoke.DrawContours(contour1Mat, contour1, -1, EmguExtensions.WhiteColor, -1, Emgu.CV.CvEnum.LineType.EightConnected, null, int.MaxValue, inverseOffset);
            CvInvoke.DrawContours(contour2Mat, contour2, -1, EmguExtensions.WhiteColor, -1, Emgu.CV.CvEnum.LineType.EightConnected, null, int.MaxValue, inverseOffset);

            CvInvoke.BitwiseAnd(contour1Mat, contour2Mat, contour1Mat);

            return(!contour1Mat.IsZeroed());
        }
Exemplo n.º 2
0
            public unsafe Mat Decode(bool consumeRle = true)
            {
                var mat         = EmguExtensions.InitMat(Parent.Resolution);
                var matSpan     = mat.GetBytePointer();
                var imageLength = mat.GetLength();

                byte last  = 0;
                int  span  = 0;
                int  index = 0;

                foreach (var b in EncodedRle)
                {
                    byte color = (byte)((b & 0xf0) | (b >> 4));

                    if (color == last)
                    {
                        span = (span << 4) | (b & 0xf);
                    }
                    else
                    {
                        for (; span > 0; span--)
                        {
                            if (index >= imageLength)
                            {
                                throw new FileLoadException($"'{span}' bytes to many");
                            }

                            matSpan[index++] = last;
                        }

                        span = b & 0xf;
                    }

                    last = color;
                }

                for (; span > 0; span--)
                {
                    if (index >= imageLength)
                    {
                        throw new FileLoadException($"'{span}' bytes to many");
                    }

                    matSpan[index++] = last;
                }

                if (index != imageLength)
                {
                    throw new FileLoadException($"Incomplete buffer, expected: {imageLength}, got: {index}");
                }


                if (consumeRle)
                {
                    EncodedRle = null;
                }

                return(mat);
            }
Exemplo n.º 3
0
            public void Encode(Mat mat)
            {
                mat ??= EmguExtensions.InitMat(new Size(ResolutionX, ResolutionY), 3);

                if (mat.Width != ResolutionX || mat.Height != ResolutionY)
                {
                    using var resizeMat = new Mat();
                    CvInvoke.Resize(mat, resizeMat, new Size(ResolutionX, ResolutionY));
                    PngBytes = resizeMat.GetPngByes();
                }
                else
                {
                    PngBytes = mat.GetPngByes();
                }
            }
Exemplo n.º 4
0
            public unsafe Mat Decode(bool consumeRle = true)
            {
                var mat         = EmguExtensions.InitMat(new Size((int)ResolutionX, (int)ResolutionY));
                var matSpan     = mat.GetBytePointer();
                var imageLength = mat.GetLength();

                int pixel = 0;

                foreach (var run in EncodedRle)
                {
                    byte col = (byte)((run & 0x01) * 255);

                    var numPixelsInRun =
                        (((run & 128) > 0 ? 1 : 0) |
                         ((run & 64) > 0 ? 2 : 0) |
                         ((run & 32) > 0 ? 4 : 0) |
                         ((run & 16) > 0 ? 8 : 0) |
                         ((run & 8) > 0 ? 16 : 0) |
                         ((run & 4) > 0 ? 32 : 0) |
                         ((run & 2) > 0 ? 64 : 0)) + 1;

                    for (; numPixelsInRun > 0; numPixelsInRun--)
                    {
                        if (pixel > imageLength)
                        {
                            mat.Dispose();
                            throw new FileLoadException($"Error image ran off the end, expecting {imageLength} pixels");
                        }
                        matSpan[pixel++] = col;
                    }
                }

                // Not required as mat is all black by default
                //for (;pixel < imageLength; pixel++) matSpan[pixel] = 0;

                if (consumeRle)
                {
                    EncodedRle = null;
                }

                return(mat);
            }
Exemplo n.º 5
0
        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);
        }