예제 #1
0
 /// <summary>
 /// Calculates mean color of a blob in an image.
 /// </summary>
 /// <param name="blobs">Blob list</param>
 /// <param name="targetBlob">The target blob</param>
 /// <param name="originalImage">Original image.</param>
 /// <returns>Average color.</returns>
 public static CvScalar BlobMeanColor(CvBlobs blobs, CvBlob targetBlob, IplImage originalImage)
 {
     if (blobs == null)
     {
         throw new ArgumentNullException("blobs");
     }
     return(blobs.BlobMeanColor(targetBlob, originalImage));
 }
예제 #2
0
 /// <summary>
 /// Calculates angle orientation of a blob.
 /// This function uses central moments so cvCentralMoments should have been called before for this blob. (cvAngle)
 /// </summary>
 /// <param name="blob">Blob.</param>
 /// <returns>Angle orientation in radians.</returns>
 public static double CalcAngle(CvBlob blob)
 {
     if (blob == null)
     {
         throw new ArgumentNullException("blob");
     }
     return(blob.Angle());
 }
예제 #3
0
 /// <summary>
 /// Calculates centroid.
 /// Centroid will be returned and stored in the blob structure. (cvCentroid)
 /// </summary>
 /// <param name="blob">Blob whose centroid will be calculated.</param>
 /// <returns>Centroid.</returns>
 public static CvPoint2D64f CalcCentroid(CvBlob blob)
 {
     if (blob == null)
     {
         throw new ArgumentNullException("blob");
     }
     return(blob.CalcCentroid());
 }
예제 #4
0
 /// <summary>
 /// Calculates mean color of a blob in an image.
 /// </summary>
 /// <param name="blobs">Blob list</param>
 /// <param name="targetBlob">The target blob</param>
 /// <param name="originalImage">Original image.</param>
 /// <returns>Average color.</returns>
 public static Scalar BlobMeanColor(CvBlobs blobs, CvBlob targetBlob, Mat originalImage)
 {
     if (blobs == null)
     {
         throw new ArgumentNullException(nameof(blobs));
     }
     return(blobs.BlobMeanColor(targetBlob, originalImage));
 }
예제 #5
0
 /// <summary>
 /// Set the ROI of an image to the bounding box of a blob.
 /// </summary>
 /// <param name="img">Image.</param>
 /// <param name="blob">Blob.</param>
 public static void SetImageRoItoBlob(IplImage img, CvBlob blob)
 {
     if (blob == null)
     {
         throw new ArgumentNullException("blob");
     }
     blob.SetImageRoiToBlob(img);
 }
예제 #6
0
 /// <summary>
 /// Calculates centroid.
 /// Centroid will be returned and stored in the blob structure. (cvCentroid)
 /// </summary>
 /// <param name="blob">Blob whose centroid will be calculated.</param>
 /// <returns>Centroid.</returns>
 public static Point2d CalcCentroid(CvBlob blob)
 {
     if (blob == null)
     {
         throw new ArgumentNullException(nameof(blob));
     }
     return(blob.CalcCentroid());
 }
예제 #7
0
 /// <summary>
 /// Save the image of a blob to a file.
 /// The function uses an image (that can be the original pre-processed image or a processed one, or even the result of cvRenderBlobs, for example) and a blob structure.
 /// Then the function saves a copy of the part of the image where the blob is.
 /// </summary>
 /// <param name="fileName">Name of the file.</param>
 /// <param name="img">Image.</param>
 /// <param name="blob">Blob.</param>
 public static void SaveImageBlob(string fileName, Mat img, CvBlob blob)
 {
     if (string.IsNullOrEmpty(fileName))
     {
         throw new ArgumentNullException(nameof(fileName));
     }
     if (blob == null)
     {
         throw new ArgumentNullException(nameof(blob));
     }
     blob.SaveImage(fileName, img);
 }
예제 #8
0
 /// <summary>
 /// Save the image of a blob to a file.
 /// The function uses an image (that can be the original pre-processed image or a processed one, or even the result of cvRenderBlobs, for example) and a blob structure.
 /// Then the function saves a copy of the part of the image where the blob is.
 /// </summary>
 /// <param name="fileName">Name of the file.</param>
 /// <param name="img">Image.</param>
 /// <param name="blob">Blob.</param>
 public static void SaveImageBlob(string fileName, IplImage img, CvBlob blob)
 {
     if (String.IsNullOrEmpty(fileName))
     {
         throw new ArgumentNullException("fileName");
     }
     if (blob == null)
     {
         throw new ArgumentNullException("blob");
     }
     blob.SaveImage(fileName, img);
 }
예제 #9
0
        /// <summary>
        /// Draws or prints information about a blob.
        /// </summary>
        /// <param name="labels">Label data.</param>
        /// <param name="blob">Blob.</param>
        /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
        /// <param name="color">Color to render (if CV_BLOB_RENDER_COLOR is used).</param>
        /// <param name="alpha">If mode CV_BLOB_RENDER_COLOR is used. 1.0 indicates opaque and 0.0 translucent (1.0 by default).</param>
        public static void RenderBlob(LabelData labels, CvBlob blob, IplImage imgSource, IplImage imgDest, RenderBlobsMode mode, CvScalar color, double alpha)
        {
            if (labels == null)
            {
                throw new ArgumentNullException("labels");
            }
            if (blob == null)
            {
                throw new ArgumentNullException("blob");
            }
            if (imgSource == null)
            {
                throw new ArgumentNullException("imgSource");
            }
            if (imgDest == null)
            {
                throw new ArgumentNullException("imgDest");
            }

            BlobRenderer.PerformOne(labels, blob, imgSource, imgDest, mode, color, alpha);
        }
예제 #10
0
        /// <summary>
        /// Draws or prints information about a blob.
        /// </summary>
        /// <param name="labels">Label data.</param>
        /// <param name="blob">Blob.</param>
        /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
        /// <param name="color">Color to render (if CV_BLOB_RENDER_COLOR is used).</param>
        /// <param name="alpha">If mode CV_BLOB_RENDER_COLOR is used. 1.0 indicates opaque and 0.0 translucent (1.0 by default).</param>
        public static void RenderBlob(LabelData labels, CvBlob blob, Mat imgSource, Mat imgDest,
                                      RenderBlobsMode mode, Scalar color, double alpha = 1.0)
        {
            if (labels == null)
            {
                throw new ArgumentNullException(nameof(labels));
            }
            if (blob == null)
            {
                throw new ArgumentNullException(nameof(blob));
            }
            if (imgSource == null)
            {
                throw new ArgumentNullException(nameof(imgSource));
            }
            if (imgDest == null)
            {
                throw new ArgumentNullException(nameof(imgDest));
            }

            BlobRenderer.PerformOne(labels, blob, imgSource, imgDest, mode, color, alpha);
        }
예제 #11
0
 /// <summary>
 /// Draws or prints information about a blob.
 /// </summary>
 /// <param name="labels">Label data.</param>
 /// <param name="blob">Blob.</param>
 /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
 /// <param name="color">Color to render (if CV_BLOB_RENDER_COLOR is used).</param>
 public static void RenderBlob(LabelData labels, CvBlob blob, IplImage imgSource, IplImage imgDest, RenderBlobsMode mode, CvScalar color)
 {
     RenderBlob(labels, blob, imgSource, imgDest, mode, color, 1.0);
 }
예제 #12
0
 /// <summary>
 /// Draws or prints information about a blob.
 /// </summary>
 /// <param name="labels">Label data.</param>
 /// <param name="blob">Blob.</param>
 /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
 /// <param name="color">Color to render (if CV_BLOB_RENDER_COLOR is used).</param>
 public static void RenderBlob(LabelData labels, CvBlob blob, IplImage imgSource, IplImage imgDest, RenderBlobsMode mode, CvScalar color)
 {
     RenderBlob(labels, blob, imgSource, imgDest, mode, color, 1.0);
 }
예제 #13
0
 /// <summary>
 /// Draws or prints information about a blob.
 /// </summary>
 /// <param name="labels">Label data.</param>
 /// <param name="blob">Blob.</param>
 /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
 public static void RenderBlob(LabelData labels, CvBlob blob, IplImage imgSource, IplImage imgDest, RenderBlobsMode mode)
 {
     RenderBlob(labels, blob, imgSource, imgDest, mode, CvColor.White, 1.0);
 }
예제 #14
0
 /// <summary>
 /// Calculates mean color of a blob in an image.
 /// </summary>
 /// <param name="blobs">Blob list</param>
 /// <param name="targetBlob">The target blob</param>
 /// <param name="originalImage">Original image.</param>
 /// <returns>Average color.</returns>
 public static CvScalar BlobMeanColor(CvBlobs blobs, CvBlob targetBlob, IplImage originalImage)
 {
     if (blobs == null)
         throw new ArgumentNullException("blobs");
     return blobs.BlobMeanColor(targetBlob, originalImage);
 }
예제 #15
0
 /// <summary>
 /// Set the ROI of an image to the bounding box of a blob.
 /// </summary>
 /// <param name="img">Image.</param>
 /// <param name="blob">Blob.</param>
 public static void SetImageRoItoBlob(IplImage img, CvBlob blob)
 {
     if (blob == null)
         throw new ArgumentNullException("blob");
     blob.SetImageRoiToBlob(img);
 }
예제 #16
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="img"></param>
        /// <param name="blobs"></param>
        /// <returns></returns>
        public static int Perform(IplImage img, CvBlobs blobs)
        {
            if (img == null)
                throw new ArgumentNullException("img");
            if (blobs == null)
                throw new ArgumentNullException("blobs");
            if (img.Depth != BitDepth.U8 || img.NChannels != 1)
                throw new ArgumentException("'img' must be a 1-channel U8 image.");

            LabelData labels = blobs.Labels;
            if (labels == null)
                throw new ArgumentException("");
            //if(labels.GetLength(0) != h || labels.GetLength(1) != w)
            if (labels.Rows != img.Height || labels.Cols != img.Width)
                throw new ArgumentException("img.Size != labels' size");

            int numPixels = 0;
            blobs.Clear();

            int step = img.WidthStep;
            CvRect roi = img.ROI;
            int w = roi.Width;
            int h = roi.Height;
            int offset = 0;
            if (img.ROIPointer != IntPtr.Zero)
            {
                IplROI r = img.ROIValue;
                w = r.width;
                h = r.height;
                offset = r.xOffset + (r.yOffset * step);
            }
            byte[] imgIn;
            unsafe
            {
                byte* imgInPtr = img.ImageDataPtr + offset;
                imgIn = new byte[h * step];
                Marshal.Copy(new IntPtr(imgInPtr), imgIn, 0, imgIn.Length);
            }
            int label = 0;
            int lastLabel = 0;
            CvBlob lastBlob = null;


            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (imgIn[x + y * step] == 0)
                        continue;

                    bool labeled = labels[y, x] != 0;
                    if (!labeled && ((y == 0) || (imgIn[x + (y - 1) * step] == 0)))
                    {
                        labeled = true;

                        // Label contour.
                        label++;
                        if (label == MarkerValue)
                            throw new Exception();

                        labels[y, x] = label;
                        numPixels++;

                        // XXX This is not necessary at all. I only do this for consistency.
                        if (y > 0)
                            labels[y - 1, x] = MarkerValue;

                        CvBlob blob = new CvBlob(label, x, y);
                        blobs.Add(label, blob);
                        lastLabel = label;
                        lastBlob = blob;

                        blob.Contour.StartingPoint = new CvPoint(x, y);
                        int direction = 1;
                        int xx = x;
                        int yy = y;
                        bool contourEnd = false;

                        do
                        {
                            for (int numAttempts = 0; numAttempts < 3; numAttempts++)
                            {
                                bool found = false;
                                for (int i = 0; i < 3; i++)
                                {
                                    int nx = xx + MovesE[direction, i, 0];
                                    int ny = yy + MovesE[direction, i, 1];
                                    if ((nx < w) && (nx >= 0) && (ny < h) && (ny >= 0))
                                    {
                                        if (imgIn[nx + ny * step] != 0)
                                        {
                                            found = true;
                                            blob.Contour.ChainCode.Add((CvChainCode)MovesE[direction, i, 3]);
                                            xx = nx;
                                            yy = ny;
                                            direction = MovesE[direction, i, 2];
                                            break;
                                        }
                                        labels[ny, nx] = MarkerValue;
                                    }
                                }

                                if (!found)
                                    direction = (direction + 1) % 4;
                                else
                                {
                                    if (labels[yy, xx] != label)
                                    {
                                        labels[yy, xx] = label;
                                        numPixels++;

                                        if (xx < blob.MinX)
                                            blob.MinX = xx;
                                        else if (xx > blob.MaxX)
                                            blob.MaxX = xx;
                                        if (yy < blob.MinY)
                                            blob.MinY = yy;
                                        else if (yy > blob.MaxY)
                                            blob.MaxY = yy;

                                        blob.Area++;
                                        blob.M10 += xx;
                                        blob.M01 += yy;
                                        blob.M11 += xx * yy;
                                        blob.M20 += xx * xx;
                                        blob.M02 += yy * yy;
                                    }
                                    break;
                                }

                                contourEnd = ((xx == x) && (yy == y) && (direction == 1));
                                if (contourEnd)
                                    break;
                            }
                        } while (!contourEnd);

                    }

                    if ((y + 1 < h) && (imgIn[x + (y + 1) * step] == 0) && (labels[y + 1, x] == 0))
                    {
                        labeled = true;

                        // Label internal contour
                        int l;
                        CvBlob blob;

                        if (labels[y, x] == 0)
                        {
                            l = labels[y, x - 1];
                            labels[y, x] = l;
                            numPixels++;

                            if (l == lastLabel)
                                blob = lastBlob;
                            else
                            {
                                blob = blobs[l];
                                lastLabel = l;
                                lastBlob = blob;
                            }
                            if (blob == null)
                                throw new Exception();
                            blob.Area++;
                            blob.M10 += x;
                            blob.M01 += y;
                            blob.M11 += x * y;
                            blob.M20 += x * x;
                            blob.M02 += y * y;
                        }
                        else
                        {
                            l = labels[y, x];
                            if (l == lastLabel)
                                blob = lastBlob;
                            else
                            {
                                blob = blobs[l];
                                lastLabel = l;
                                lastBlob = blob;
                            }
                        }

                        if (blob == null)
                            throw new Exception();

                        // XXX This is not necessary (I believe). I only do this for consistency.
                        labels[y + 1, x] = MarkerValue;
                        var contour = new CvContourChainCode
                        {
                            StartingPoint = new CvPoint(x, y)
                        };

                        int direction = 3;
                        int xx = x;
                        int yy = y;

                        do
                        {
                            for (int numAttempts = 0; numAttempts < 3; numAttempts++)
                            {
                                bool found = false;

                                for (int i = 0; i < 3; i++)
                                {
                                    int nx = xx + MovesI[direction, i, 0];
                                    int ny = yy + MovesI[direction, i, 1];
                                    if (imgIn[nx + ny * step] != 0)
                                    {
                                        found = true;
                                        contour.ChainCode.Add((CvChainCode)MovesI[direction, i, 3]);
                                        xx = nx;
                                        yy = ny;
                                        direction = MovesI[direction, i, 2];
                                        break;
                                    }
                                    labels[ny, nx] = MarkerValue;
                                }

                                if (!found)
                                    direction = (direction + 1) % 4;
                                else
                                {
                                    if (labels[yy, xx] == 0)
                                    {
                                        labels[yy, xx] = l;
                                        numPixels++;

                                        blob.Area++;
                                        blob.M10 += xx;
                                        blob.M01 += yy;
                                        blob.M11 += xx * yy;
                                        blob.M20 += xx * xx;
                                        blob.M02 += yy * yy;
                                    }
                                    break;
                                }
                            }
                        } while (!(xx == x && yy == y));

                        blob.InternalContours.Add(contour);
                    }

                    //else if (!imageOut(x, y))
                    if (!labeled)
                    {
                        // Internal pixel
                        int l = labels[y, x - 1];
                        labels[y, x] = l;
                        numPixels++;

                        CvBlob blob;
                        if (l == lastLabel)
                            blob = lastBlob;
                        else
                        {
                            blob = blobs[l];
                            lastLabel = l;
                            lastBlob = blob;
                        }
                        if (blob == null)
                            throw new Exception();
                        blob.Area++;
                        blob.M10 += x;
                        blob.M01 += y;
                        blob.M11 += x * y;
                        blob.M20 += x * x;
                        blob.M02 += y * y;
                    }
                }
            }


            foreach (var kv in blobs)
            {
                kv.Value.SetMoments();
            }

            return numPixels;

        }
예제 #17
0
 /// <summary>
 /// Calculates mean color of a blob in an image.
 /// </summary>
 /// <param name="blobs">Blob list</param>
 /// <param name="targetBlob">The target blob</param>
 /// <param name="originalImage">Original image.</param>
 /// <returns>Average color.</returns>
 public static Scalar BlobMeanColor(CvBlobs blobs, CvBlob targetBlob, Mat originalImage)
 {
     if (blobs == null)
         throw new ArgumentNullException(nameof(blobs));
     return blobs.BlobMeanColor(targetBlob, originalImage);
 }
예제 #18
0
 /// <summary>
 /// Draws or prints information about a blob.
 /// </summary>
 /// <param name="labels">Label data.</param>
 /// <param name="blob">Blob.</param>
 /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
 public static void RenderBlob(LabelData labels, CvBlob blob, Mat imgSource, Mat imgDest,
                               RenderBlobsMode mode)
 {
     RenderBlob(labels, blob, imgSource, imgDest, mode, Scalar.White, 1.0);
 }
예제 #19
0
        /// <summary>
        /// Draws or prints information about a blob.
        /// </summary>
        /// <param name="labels">Label data.</param>
        /// <param name="blob">Blob.</param>
        /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
        /// <param name="color">Color to render (if CV_BLOB_RENDER_COLOR is used).</param>
        /// <param name="alpha">If mode CV_BLOB_RENDER_COLOR is used. 1.0 indicates opaque and 0.0 translucent (1.0 by default).</param>
        public static void RenderBlob(LabelData labels, CvBlob blob, IplImage imgSource, IplImage imgDest, RenderBlobsMode mode, CvScalar color, double alpha)
        {
            if (labels == null)
                throw new ArgumentNullException("labels");
            if (blob == null)
                throw new ArgumentNullException("blob");
            if (imgSource == null)
                throw new ArgumentNullException("imgSource");
            if (imgDest == null)
                throw new ArgumentNullException("imgDest");

            BlobRenderer.PerformOne(labels, blob, imgSource, imgDest, mode, color, alpha);
        }
예제 #20
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="labels"></param>
        /// <param name="blob"></param>
        /// <param name="imgSrc"></param>
        /// <param name="imgDst"></param>
        /// <param name="mode"></param>
        /// <param name="color"></param>
        /// <param name="alpha"></param>
        public static unsafe void PerformOne(LabelData labels, CvBlob blob, Mat imgSrc, Mat imgDst,
            RenderBlobsMode mode, Scalar color, double alpha)
        {
            if (labels == null)
                throw new ArgumentNullException("labels");
            if (blob == null)
                throw new ArgumentNullException("blob");
            if (imgSrc == null)
                throw new ArgumentNullException("imgSrc");
            if (imgDst == null)
                throw new ArgumentNullException("imgDst");
            if (imgDst.Type() != MatType.CV_8UC3)
                throw new ArgumentException("'img' must be a 3-channel U8 image.");

            if ((mode & RenderBlobsMode.Color) == RenderBlobsMode.Color)
            {
                var pSrc = imgSrc.GetGenericIndexer<Vec3b>();
                var pDst = imgDst.GetGenericIndexer<Vec3b>();

                for (int r = blob.MinY; r < blob.MaxY; r++)
                {
                    for (int c = blob.MinX; c < blob.MaxX; c++)
                    {
                        if (labels[r, c] == blob.Label)
                        {
                            byte v0 = (byte) ((1.0 - alpha)*pSrc[r, c].Item0 + alpha*color.Val0);
                            byte v1 = (byte) ((1.0 - alpha)*pSrc[r, c].Item1 + alpha*color.Val1);
                            byte v2 = (byte) ((1.0 - alpha)*pSrc[r, c].Item2 + alpha*color.Val2);
                            pDst[r, c] = new Vec3b(v0, v1, v2);
                        }
                    }
                }
            }

            if (mode != RenderBlobsMode.None)
            {
                if ((mode & RenderBlobsMode.BoundingBox) == RenderBlobsMode.BoundingBox)
                {
                    Cv2.Rectangle(
                        imgDst,
                        new Point(blob.MinX, blob.MinY),
                        new Point(blob.MaxX - 1, blob.MaxY - 1),
                        new Scalar(255, 0, 0));
                }
                if ((mode & RenderBlobsMode.Angle) == RenderBlobsMode.Angle)
                {
                    double angle = blob.Angle();
                    double lengthLine = Math.Max(blob.MaxX - blob.MinX, blob.MaxY - blob.MinY) / 2.0;
                    double x1 = blob.Centroid.X - lengthLine * Math.Cos(angle);
                    double y1 = blob.Centroid.Y - lengthLine * Math.Sin(angle);
                    double x2 = blob.Centroid.X + lengthLine * Math.Cos(angle);
                    double y2 = blob.Centroid.Y + lengthLine * Math.Sin(angle);
                    Cv2.Line(imgDst, new Point((int)x1, (int)y1), new Point((int)x2, (int)y2),
                        new Scalar(0, 255, 0));
                }
                if ((mode & RenderBlobsMode.Centroid) == RenderBlobsMode.Centroid)
                {
                    Cv2.Line(imgDst,
                        new Point((int)blob.Centroid.X - 3, (int)blob.Centroid.Y),
                        new Point((int)blob.Centroid.X + 3, (int)blob.Centroid.Y),
                        new Scalar(255, 0, 0));
                    Cv2.Line(imgDst,
                        new Point((int)blob.Centroid.X, (int)blob.Centroid.Y - 3),
                        new Point((int)blob.Centroid.X, (int)blob.Centroid.Y + 3),
                        new Scalar(255, 0, 0));
                }
            }
        }
예제 #21
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="labels"></param>
        /// <param name="blob"></param>
        /// <param name="imgSrc"></param>
        /// <param name="imgDst"></param>
        /// <param name="mode"></param>
        /// <param name="color"></param>
        /// <param name="alpha"></param>
        public static unsafe void PerformOne(LabelData labels, CvBlob blob, IplImage imgSrc, IplImage imgDst,
            RenderBlobsMode mode, CvScalar color, double alpha)
        {
            if (labels == null)
                throw new ArgumentNullException("labels");
            if (blob == null)
                throw new ArgumentNullException("blob");
            if (imgSrc == null)
                throw new ArgumentNullException("imgSrc");
            if (imgDst == null)
                throw new ArgumentNullException("imgDst");
            if (imgDst.Depth != BitDepth.U8 || imgDst.NChannels != 3)
                throw new ArgumentException("'img' must be a 3-channel U8 image.");

            if ((mode & RenderBlobsMode.Color) == RenderBlobsMode.Color)
            {
                int stepSrc = imgSrc.WidthStep;
                int stepDst = imgDst.WidthStep;
                int offsetSrc = 0;
                int offsetDst = 0;
                CvRect roiSrc = imgSrc.ROI;
                CvRect roiDst = imgDst.ROI;
                if (roiSrc.Size != imgSrc.Size)
                    offsetSrc = roiSrc.Y * stepSrc + roiSrc.X;
                if (roiDst.Size != imgDst.Size)
                    offsetDst = roiDst.Y * stepDst + roiDst.X;
                byte* pSrc = (byte*)imgSrc.ImageData + offsetSrc + (blob.MinY * stepSrc);
                byte* pDst = (byte*)imgDst.ImageData + offsetDst + (blob.MinY * stepDst);

                for (int r = blob.MinY; r < blob.MaxY; r++)
                {
                    for (int c = blob.MinX; c < blob.MaxX; c++)
                    {
                        if (labels[r, c] == blob.Label)
                        {
                            pDst[c*3 + 0] = (byte) ((1.0 - alpha)*pSrc[c + 0] + alpha*color.Val0);
                            pDst[c*3 + 1] = (byte) ((1.0 - alpha)*pSrc[c + 1] + alpha*color.Val1);
                            pDst[c*3 + 2] = (byte) ((1.0 - alpha)*pSrc[c + 2] + alpha*color.Val2);
                        }
                    }
                    pSrc += stepSrc;
                    pDst += stepDst;
                }
            }

            if (mode != RenderBlobsMode.None)
            {
                if ((mode & RenderBlobsMode.BoundingBox) == RenderBlobsMode.BoundingBox)
                {
                    Cv.Rectangle(
                        imgDst,
                        new CvPoint(blob.MinX, blob.MinY),
                        new CvPoint(blob.MaxX - 1, blob.MaxY - 1),
                        new CvColor(255, 0, 0));
                }
                if ((mode & RenderBlobsMode.Angle) == RenderBlobsMode.Angle)
                {
                    double angle = blob.Angle();
                    double lengthLine = Math.Max(blob.MaxX - blob.MinX, blob.MaxY - blob.MinY) / 2.0;
                    double x1 = blob.Centroid.X - lengthLine * Math.Cos(angle);
                    double y1 = blob.Centroid.Y - lengthLine * Math.Sin(angle);
                    double x2 = blob.Centroid.X + lengthLine * Math.Cos(angle);
                    double y2 = blob.Centroid.Y + lengthLine * Math.Sin(angle);
                    Cv.Line(imgDst, new CvPoint((int)x1, (int)y1), Cv.Point((int)x2, (int)y2),
                        new CvColor(0, 255, 0));
                }
                if ((mode & RenderBlobsMode.Centroid) == RenderBlobsMode.Centroid)
                {
                    Cv.Line(imgDst,
                        new CvPoint((int)blob.Centroid.X - 3, (int)blob.Centroid.Y),
                        new CvPoint((int)blob.Centroid.X + 3, (int)blob.Centroid.Y),
                        new CvColor(0, 0, 255));
                    Cv.Line(imgDst,
                        new CvPoint((int)blob.Centroid.X, (int)blob.Centroid.Y - 3),
                        new CvPoint((int)blob.Centroid.X, (int)blob.Centroid.Y + 3),
                        new CvColor(0, 0, 255));
                }
            }
        }
예제 #22
0
        /// <summary>
        /// Draws or prints information about a blob.
        /// </summary>
        /// <param name="labels">Label data.</param>
        /// <param name="blob">Blob.</param>
        /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
        /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
        /// <param name="color">Color to render (if CV_BLOB_RENDER_COLOR is used).</param>
        /// <param name="alpha">If mode CV_BLOB_RENDER_COLOR is used. 1.0 indicates opaque and 0.0 translucent (1.0 by default).</param>
        public static void RenderBlob(LabelData labels, CvBlob blob, Mat imgSource, Mat imgDest,
            RenderBlobsMode mode, Scalar color, double alpha = 1.0)
        {
            if (labels == null)
                throw new ArgumentNullException(nameof(labels));
            if (blob == null)
                throw new ArgumentNullException(nameof(blob));
            if (imgSource == null)
                throw new ArgumentNullException(nameof(imgSource));
            if (imgDest == null)
                throw new ArgumentNullException(nameof(imgDest));

            BlobRenderer.PerformOne(labels, blob, imgSource, imgDest, mode, color, alpha);
        }
예제 #23
0
 /// <summary>
 /// Draws or prints information about a blob.
 /// </summary>
 /// <param name="labels">Label data.</param>
 /// <param name="blob">Blob.</param>
 /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
 public static void RenderBlob(LabelData labels, CvBlob blob, IplImage imgSource, IplImage imgDest, RenderBlobsMode mode)
 {
     RenderBlob(labels, blob, imgSource, imgDest, mode, CvColor.White, 1.0);
 }
예제 #24
0
 /// <summary>
 /// Save the image of a blob to a file.
 /// The function uses an image (that can be the original pre-processed image or a processed one, or even the result of cvRenderBlobs, for example) and a blob structure.
 /// Then the function saves a copy of the part of the image where the blob is.
 /// </summary>
 /// <param name="fileName">Name of the file.</param>
 /// <param name="img">Image.</param>
 /// <param name="blob">Blob.</param>
 public static void SaveImageBlob(string fileName, Mat img, CvBlob blob)
 {
     if (String.IsNullOrEmpty(fileName))
         throw new ArgumentNullException(nameof(fileName));
     if (blob == null)
         throw new ArgumentNullException(nameof(blob));
     blob.SaveImage(fileName, img);
 }
예제 #25
0
 /// <summary>
 /// Calculates angle orientation of a blob.
 /// This function uses central moments so cvCentralMoments should have been called before for this blob. (cvAngle)
 /// </summary>
 /// <param name="blob">Blob.</param>
 /// <returns>Angle orientation in radians.</returns>
 public static double CalcAngle(CvBlob blob)
 {
     if (blob == null)
         throw new ArgumentNullException(nameof(blob));
     return blob.Angle();
 }
예제 #26
0
 /// <summary>
 /// Calculates centroid.
 /// Centroid will be returned and stored in the blob structure. (cvCentroid)
 /// </summary>
 /// <param name="blob">Blob whose centroid will be calculated.</param>
 /// <returns>Centroid.</returns>
 public static CvPoint2D64f CalcCentroid(CvBlob blob)
 {
     if (blob == null)
         throw new ArgumentNullException("blob");
     return blob.CalcCentroid();
 }
예제 #27
0
 /// <summary>
 /// Draws or prints information about a blob.
 /// </summary>
 /// <param name="labels">Label data.</param>
 /// <param name="blob">Blob.</param>
 /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="mode">Render mode. By default is CV_BLOB_RENDER_COLOR|CV_BLOB_RENDER_CENTROID|CV_BLOB_RENDER_BOUNDING_BOX|CV_BLOB_RENDER_ANGLE.</param>
 public static void RenderBlob(LabelData labels, CvBlob blob, Mat imgSource, Mat imgDest,
     RenderBlobsMode mode)
 {
     RenderBlob(labels, blob, imgSource, imgDest, mode, Scalar.White, 1.0);
 }
예제 #28
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="labels"></param>
        /// <param name="blob"></param>
        /// <param name="imgSrc"></param>
        /// <param name="imgDst"></param>
        /// <param name="mode"></param>
        /// <param name="color"></param>
        /// <param name="alpha"></param>
        public static void PerformOne(LabelData labels, CvBlob blob, Mat imgSrc, Mat imgDst,
                                      RenderBlobsMode mode, Scalar color, double alpha)
        {
            if (labels == null)
            {
                throw new ArgumentNullException(nameof(labels));
            }
            if (blob == null)
            {
                throw new ArgumentNullException(nameof(blob));
            }
            if (imgSrc == null)
            {
                throw new ArgumentNullException(nameof(imgSrc));
            }
            if (imgDst == null)
            {
                throw new ArgumentNullException(nameof(imgDst));
            }
            if (imgDst.Type() != MatType.CV_8UC3)
            {
                throw new ArgumentException("'img' must be a 3-channel U8 image.");
            }

            if ((mode & RenderBlobsMode.Color) == RenderBlobsMode.Color)
            {
                var pSrc = imgSrc.GetGenericIndexer <Vec3b>();
                var pDst = imgDst.GetGenericIndexer <Vec3b>();

                for (int r = blob.MinY; r <= blob.MaxY; r++)
                {
                    for (int c = blob.MinX; c <= blob.MaxX; c++)
                    {
                        if (labels[r, c] == blob.Label)
                        {
                            byte v0 = (byte)((1.0 - alpha) * pSrc[r, c].Item0 + alpha * color.Val0);
                            byte v1 = (byte)((1.0 - alpha) * pSrc[r, c].Item1 + alpha * color.Val1);
                            byte v2 = (byte)((1.0 - alpha) * pSrc[r, c].Item2 + alpha * color.Val2);
                            pDst[r, c] = new Vec3b(v0, v1, v2);
                        }
                    }
                }
            }

            if (mode != RenderBlobsMode.None)
            {
                if ((mode & RenderBlobsMode.BoundingBox) == RenderBlobsMode.BoundingBox)
                {
                    Cv2.Rectangle(
                        imgDst,
                        new Point(blob.MinX, blob.MinY),
                        new Point(blob.MaxX, blob.MaxY),
                        new Scalar(255, 0, 0));
                }
                if ((mode & RenderBlobsMode.Angle) == RenderBlobsMode.Angle)
                {
                    double angle      = blob.Angle();
                    double lengthLine = Math.Max(blob.MaxX - blob.MinX, blob.MaxY - blob.MinY) / 2.0;
                    double x1         = blob.Centroid.X - lengthLine * Math.Cos(angle);
                    double y1         = blob.Centroid.Y - lengthLine * Math.Sin(angle);
                    double x2         = blob.Centroid.X + lengthLine * Math.Cos(angle);
                    double y2         = blob.Centroid.Y + lengthLine * Math.Sin(angle);
                    Cv2.Line(imgDst, new Point((int)x1, (int)y1), new Point((int)x2, (int)y2),
                             new Scalar(0, 255, 0));
                }
                if ((mode & RenderBlobsMode.Centroid) == RenderBlobsMode.Centroid)
                {
                    Cv2.Line(imgDst,
                             new Point((int)blob.Centroid.X - 3, (int)blob.Centroid.Y),
                             new Point((int)blob.Centroid.X + 3, (int)blob.Centroid.Y),
                             new Scalar(255, 0, 0));
                    Cv2.Line(imgDst,
                             new Point((int)blob.Centroid.X, (int)blob.Centroid.Y - 3),
                             new Point((int)blob.Centroid.X, (int)blob.Centroid.Y + 3),
                             new Scalar(255, 0, 0));
                }
            }
        }
예제 #29
0
 /// <summary>
 /// Calculates centroid.
 /// Centroid will be returned and stored in the blob structure. (cvCentroid)
 /// </summary>
 /// <param name="blob">Blob whose centroid will be calculated.</param>
 /// <returns>Centroid.</returns>
 public static Point2d CalcCentroid(CvBlob blob)
 {
     if (blob == null)
         throw new ArgumentNullException(nameof(blob));
     return blob.CalcCentroid();
 }
예제 #30
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="labels"></param>
        /// <param name="blob"></param>
        /// <param name="imgSrc"></param>
        /// <param name="imgDst"></param>
        /// <param name="mode"></param>
        /// <param name="color"></param>
        /// <param name="alpha"></param>
        public static unsafe void PerformOne(LabelData labels, CvBlob blob, IplImage imgSrc, IplImage imgDst,
                                             RenderBlobsMode mode, CvScalar color, double alpha)
        {
            if (labels == null)
            {
                throw new ArgumentNullException("labels");
            }
            if (blob == null)
            {
                throw new ArgumentNullException("blob");
            }
            if (imgSrc == null)
            {
                throw new ArgumentNullException("imgSrc");
            }
            if (imgDst == null)
            {
                throw new ArgumentNullException("imgDst");
            }
            if (imgDst.Depth != BitDepth.U8 || imgDst.NChannels != 3)
            {
                throw new ArgumentException("'img' must be a 3-channel U8 image.");
            }

            if ((mode & RenderBlobsMode.Color) == RenderBlobsMode.Color)
            {
                int    stepSrc   = imgSrc.WidthStep;
                int    stepDst   = imgDst.WidthStep;
                int    offsetSrc = 0;
                int    offsetDst = 0;
                CvRect roiSrc    = imgSrc.ROI;
                CvRect roiDst    = imgDst.ROI;
                if (roiSrc.Size != imgSrc.Size)
                {
                    offsetSrc = roiSrc.Y * stepSrc + roiSrc.X;
                }
                if (roiDst.Size != imgDst.Size)
                {
                    offsetDst = roiDst.Y * stepDst + roiDst.X;
                }
                byte *pSrc = (byte *)imgSrc.ImageData + offsetSrc + (blob.MinY * stepSrc);
                byte *pDst = (byte *)imgDst.ImageData + offsetDst + (blob.MinY * stepDst);

                for (int r = blob.MinY; r < blob.MaxY; r++)
                {
                    for (int c = blob.MinX; c < blob.MaxX; c++)
                    {
                        if (labels[r, c] == blob.Label)
                        {
                            pDst[c * 3 + 0] = (byte)((1.0 - alpha) * pSrc[c + 0] + alpha * color.Val0);
                            pDst[c * 3 + 1] = (byte)((1.0 - alpha) * pSrc[c + 1] + alpha * color.Val1);
                            pDst[c * 3 + 2] = (byte)((1.0 - alpha) * pSrc[c + 2] + alpha * color.Val2);
                        }
                    }
                    pSrc += stepSrc;
                    pDst += stepDst;
                }
            }

            if (mode != RenderBlobsMode.None)
            {
                if ((mode & RenderBlobsMode.BoundingBox) == RenderBlobsMode.BoundingBox)
                {
                    Cv.Rectangle(
                        imgDst,
                        new CvPoint(blob.MinX, blob.MinY),
                        new CvPoint(blob.MaxX - 1, blob.MaxY - 1),
                        new CvColor(255, 0, 0));
                }
                if ((mode & RenderBlobsMode.Angle) == RenderBlobsMode.Angle)
                {
                    double angle      = blob.Angle();
                    double lengthLine = Math.Max(blob.MaxX - blob.MinX, blob.MaxY - blob.MinY) / 2.0;
                    double x1         = blob.Centroid.X - lengthLine * Math.Cos(angle);
                    double y1         = blob.Centroid.Y - lengthLine * Math.Sin(angle);
                    double x2         = blob.Centroid.X + lengthLine * Math.Cos(angle);
                    double y2         = blob.Centroid.Y + lengthLine * Math.Sin(angle);
                    Cv.Line(imgDst, new CvPoint((int)x1, (int)y1), Cv.Point((int)x2, (int)y2),
                            new CvColor(0, 255, 0));
                }
                if ((mode & RenderBlobsMode.Centroid) == RenderBlobsMode.Centroid)
                {
                    Cv.Line(imgDst,
                            new CvPoint((int)blob.Centroid.X - 3, (int)blob.Centroid.Y),
                            new CvPoint((int)blob.Centroid.X + 3, (int)blob.Centroid.Y),
                            new CvColor(0, 0, 255));
                    Cv.Line(imgDst,
                            new CvPoint((int)blob.Centroid.X, (int)blob.Centroid.Y - 3),
                            new CvPoint((int)blob.Centroid.X, (int)blob.Centroid.Y + 3),
                            new CvColor(0, 0, 255));
                }
            }
        }
예제 #31
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="img"></param>
        /// <param name="blobs"></param>
        /// <returns></returns>
        public static int Perform(Mat img, CvBlobs blobs)
        {
            if (img == null)
            {
                throw new ArgumentNullException(nameof(img));
            }
            if (blobs == null)
            {
                throw new ArgumentNullException(nameof(blobs));
            }
            if (img.Type() != MatType.CV_8UC1)
            {
                throw new ArgumentException("'img' must be a 1-channel U8 image.");
            }

            if (blobs.Labels == null)
            {
                throw new ArgumentException("blobs.Labels == null", nameof(blobs));
            }
            LabelData labels = blobs.Labels;

            //if(labels.GetLength(0) != h || labels.GetLength(1) != w)
            if (labels.Rows != img.Height || labels.Cols != img.Width)
            {
                throw new ArgumentException("img.Size != labels' size");
            }

            int numPixels = 0;

            blobs.Clear();

            int w    = img.Cols;
            int h    = img.Rows;
            int step = (int)img.Step();

            byte[] imgIn;
            unsafe
            {
                byte *imgInPtr = (byte *)img.Data;
                if ((long)h * step > int.MaxValue)
                {
                    throw new ArgumentException("Too big image (image data > 2^31)");
                }
                int length = h * step;
                imgIn = new byte[length];
                Marshal.Copy(new IntPtr(imgInPtr), imgIn, 0, imgIn.Length);
            }
            int    label     = 0;
            int    lastLabel = 0;
            CvBlob?lastBlob  = null;

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (imgIn[x + y * step] == 0)
                    {
                        continue;
                    }

                    bool labeled = labels[y, x] != 0;
                    if (!labeled && ((y == 0) || (imgIn[x + (y - 1) * step] == 0)))
                    {
                        labeled = true;

                        // Label contour.
                        label++;
                        if (label == MarkerValue)
                        {
                            throw new Exception();
                        }

                        labels[y, x] = label;
                        numPixels++;

                        // XXX This is not necessary at all. I only do this for consistency.
                        if (y > 0)
                        {
                            labels[y - 1, x] = MarkerValue;
                        }

                        var blob = new CvBlob(label, x, y);
                        blobs.Add(label, blob);
                        lastLabel = label;
                        lastBlob  = blob;

                        blob.Contour.StartingPoint = new Point(x, y);
                        int  direction  = 1;
                        int  xx         = x;
                        int  yy         = y;
                        bool contourEnd = false;

                        do
                        {
                            for (int numAttempts = 0; numAttempts < 3; numAttempts++)
                            {
                                bool found = false;
                                for (int i = 0; i < 3; i++)
                                {
                                    int nx = xx + MovesE[direction, i, 0];
                                    int ny = yy + MovesE[direction, i, 1];
                                    if ((nx < w) && (nx >= 0) && (ny < h) && (ny >= 0))
                                    {
                                        if (imgIn[nx + ny * step] != 0)
                                        {
                                            found = true;
                                            blob.Contour.ChainCode.Add((CvChainCode)MovesE[direction, i, 3]);
                                            xx        = nx;
                                            yy        = ny;
                                            direction = MovesE[direction, i, 2];
                                            break;
                                        }
                                        labels[ny, nx] = MarkerValue;
                                    }
                                }

                                if (!found)
                                {
                                    direction = (direction + 1) % 4;
                                }
                                else
                                {
                                    if (labels[yy, xx] != label)
                                    {
                                        labels[yy, xx] = label;
                                        numPixels++;

                                        if (xx < blob.MinX)
                                        {
                                            blob.MinX = xx;
                                        }
                                        else if (xx > blob.MaxX)
                                        {
                                            blob.MaxX = xx;
                                        }
                                        if (yy < blob.MinY)
                                        {
                                            blob.MinY = yy;
                                        }
                                        else if (yy > blob.MaxY)
                                        {
                                            blob.MaxY = yy;
                                        }

                                        blob.Area++;
                                        blob.M10 += xx;
                                        blob.M01 += yy;
                                        blob.M11 += xx * yy;
                                        blob.M20 += xx * xx;
                                        blob.M02 += yy * yy;
                                    }
                                    break;
                                }

                                contourEnd = ((xx == x) && (yy == y) && (direction == 1));
                                if (contourEnd)
                                {
                                    break;
                                }
                            }
                        } while (!contourEnd);
                    }

                    if ((y + 1 < h) && (imgIn[x + (y + 1) * step] == 0) && (labels[y + 1, x] == 0))
                    {
                        labeled = true;

                        // Label internal contour
                        int    l;
                        CvBlob?blob;

                        if (labels[y, x] == 0)
                        {
                            l            = labels[y, x - 1];
                            labels[y, x] = l;
                            numPixels++;

                            if (l == lastLabel)
                            {
                                blob = lastBlob;
                            }
                            else
                            {
                                blob      = blobs[l];
                                lastLabel = l;
                                lastBlob  = blob;
                            }
                            if (blob == null)
                            {
                                throw new Exception();
                            }
                            blob.Area++;
                            blob.M10 += x;
                            blob.M01 += y;
                            blob.M11 += x * y;
                            blob.M20 += x * x;
                            blob.M02 += y * y;
                        }
                        else
                        {
                            l = labels[y, x];
                            if (l == lastLabel)
                            {
                                blob = lastBlob;
                            }
                            else
                            {
                                blob      = blobs[l];
                                lastLabel = l;
                                lastBlob  = blob;
                            }
                        }

                        if (blob == null)
                        {
                            throw new Exception();
                        }

                        // XXX This is not necessary (I believe). I only do this for consistency.
                        labels[y + 1, x] = MarkerValue;
                        var contour = new CvContourChainCode
                        {
                            StartingPoint = new Point(x, y)
                        };

                        int direction = 3;
                        int xx        = x;
                        int yy        = y;

                        do
                        {
                            for (int numAttempts = 0; numAttempts < 3; numAttempts++)
                            {
                                bool found = false;

                                for (int i = 0; i < 3; i++)
                                {
                                    int nx = xx + MovesI[direction, i, 0];
                                    int ny = yy + MovesI[direction, i, 1];
                                    if (imgIn[nx + ny * step] != 0)
                                    {
                                        found = true;
                                        contour.ChainCode.Add((CvChainCode)MovesI[direction, i, 3]);
                                        xx        = nx;
                                        yy        = ny;
                                        direction = MovesI[direction, i, 2];
                                        break;
                                    }
                                    labels[ny, nx] = MarkerValue;
                                }

                                if (!found)
                                {
                                    direction = (direction + 1) % 4;
                                }
                                else
                                {
                                    if (labels[yy, xx] == 0)
                                    {
                                        labels[yy, xx] = l;
                                        numPixels++;

                                        blob.Area++;
                                        blob.M10 += xx;
                                        blob.M01 += yy;
                                        blob.M11 += xx * yy;
                                        blob.M20 += xx * xx;
                                        blob.M02 += yy * yy;
                                    }
                                    break;
                                }
                            }
                        } while (!(xx == x && yy == y));

                        blob.InternalContours.Add(contour);
                    }

                    //else if (!imageOut(x, y))
                    if (!labeled)
                    {
                        // Internal pixel
                        int l = labels[y, x - 1];
                        labels[y, x] = l;
                        numPixels++;

                        CvBlob?blob;
                        if (l == lastLabel)
                        {
                            blob = lastBlob;
                        }
                        else
                        {
                            blob      = blobs[l];
                            lastLabel = l;
                            lastBlob  = blob;
                        }
                        if (blob == null)
                        {
                            throw new Exception();
                        }
                        blob.Area++;
                        blob.M10 += x;
                        blob.M01 += y;
                        blob.M11 += x * y;
                        blob.M20 += x * x;
                        blob.M02 += y * y;
                    }
                }
            }


            foreach (var kv in blobs)
            {
                kv.Value.SetMoments();
            }

            GC.KeepAlive(img);

            return(numPixels);
        }
예제 #32
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="img"></param>
        /// <param name="blobs"></param>
        /// <returns></returns>
        public static int Perform(IplImage img, CvBlobs blobs)
        {
            if (img == null)
            {
                throw new ArgumentNullException("img");
            }
            if (blobs == null)
            {
                throw new ArgumentNullException("blobs");
            }
            if (img.Depth != BitDepth.U8 || img.NChannels != 1)
            {
                throw new ArgumentException("'img' must be a 1-channel U8 image.");
            }

            LabelData labels = blobs.Labels;

            if (labels == null)
            {
                throw new ArgumentException("");
            }
            //if(labels.GetLength(0) != h || labels.GetLength(1) != w)
            if (labels.Rows != img.Height || labels.Cols != img.Width)
            {
                throw new ArgumentException("img.Size != labels' size");
            }

            int numPixels = 0;

            blobs.Clear();

            int    step   = img.WidthStep;
            CvRect roi    = img.ROI;
            int    w      = roi.Width;
            int    h      = roi.Height;
            int    offset = 0;

            if (img.ROIPointer != IntPtr.Zero)
            {
                IplROI r = img.ROIValue;
                w      = r.width;
                h      = r.height;
                offset = r.xOffset + (r.yOffset * step);
            }
            byte[] imgIn;
            unsafe
            {
                byte *imgInPtr = img.ImageDataPtr + offset;
                imgIn = new byte[h * step];
                Marshal.Copy(new IntPtr(imgInPtr), imgIn, 0, imgIn.Length);
            }
            int    label     = 0;
            int    lastLabel = 0;
            CvBlob lastBlob  = null;


            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (imgIn[x + y * step] == 0)
                    {
                        continue;
                    }

                    bool labeled = labels[y, x] != 0;
                    if (!labeled && ((y == 0) || (imgIn[x + (y - 1) * step] == 0)))
                    {
                        labeled = true;

                        // Label contour.
                        label++;
                        if (label == MarkerValue)
                        {
                            throw new Exception();
                        }

                        labels[y, x] = label;
                        numPixels++;

                        // XXX This is not necessary at all. I only do this for consistency.
                        if (y > 0)
                        {
                            labels[y - 1, x] = MarkerValue;
                        }

                        CvBlob blob = new CvBlob(label, x, y);
                        blobs.Add(label, blob);
                        lastLabel = label;
                        lastBlob  = blob;

                        blob.Contour.StartingPoint = new CvPoint(x, y);
                        int  direction  = 1;
                        int  xx         = x;
                        int  yy         = y;
                        bool contourEnd = false;

                        do
                        {
                            for (int numAttempts = 0; numAttempts < 3; numAttempts++)
                            {
                                bool found = false;
                                for (int i = 0; i < 3; i++)
                                {
                                    int nx = xx + MovesE[direction, i, 0];
                                    int ny = yy + MovesE[direction, i, 1];
                                    if ((nx < w) && (nx >= 0) && (ny < h) && (ny >= 0))
                                    {
                                        if (imgIn[nx + ny * step] != 0)
                                        {
                                            found = true;
                                            blob.Contour.ChainCode.Add((CvChainCode)MovesE[direction, i, 3]);
                                            xx        = nx;
                                            yy        = ny;
                                            direction = MovesE[direction, i, 2];
                                            break;
                                        }
                                        labels[ny, nx] = MarkerValue;
                                    }
                                }

                                if (!found)
                                {
                                    direction = (direction + 1) % 4;
                                }
                                else
                                {
                                    if (labels[yy, xx] != label)
                                    {
                                        labels[yy, xx] = label;
                                        numPixels++;

                                        if (xx < blob.MinX)
                                        {
                                            blob.MinX = xx;
                                        }
                                        else if (xx > blob.MaxX)
                                        {
                                            blob.MaxX = xx;
                                        }
                                        if (yy < blob.MinY)
                                        {
                                            blob.MinY = yy;
                                        }
                                        else if (yy > blob.MaxY)
                                        {
                                            blob.MaxY = yy;
                                        }

                                        blob.Area++;
                                        blob.M10 += xx;
                                        blob.M01 += yy;
                                        blob.M11 += xx * yy;
                                        blob.M20 += xx * xx;
                                        blob.M02 += yy * yy;
                                    }
                                    break;
                                }

                                contourEnd = ((xx == x) && (yy == y) && (direction == 1));
                                if (contourEnd)
                                {
                                    break;
                                }
                            }
                        } while (!contourEnd);
                    }

                    if ((y + 1 < h) && (imgIn[x + (y + 1) * step] == 0) && (labels[y + 1, x] == 0))
                    {
                        labeled = true;

                        // Label internal contour
                        int    l;
                        CvBlob blob;

                        if (labels[y, x] == 0)
                        {
                            l            = labels[y, x - 1];
                            labels[y, x] = l;
                            numPixels++;

                            if (l == lastLabel)
                            {
                                blob = lastBlob;
                            }
                            else
                            {
                                blob      = blobs[l];
                                lastLabel = l;
                                lastBlob  = blob;
                            }
                            if (blob == null)
                            {
                                throw new Exception();
                            }
                            blob.Area++;
                            blob.M10 += x;
                            blob.M01 += y;
                            blob.M11 += x * y;
                            blob.M20 += x * x;
                            blob.M02 += y * y;
                        }
                        else
                        {
                            l = labels[y, x];
                            if (l == lastLabel)
                            {
                                blob = lastBlob;
                            }
                            else
                            {
                                blob      = blobs[l];
                                lastLabel = l;
                                lastBlob  = blob;
                            }
                        }

                        if (blob == null)
                        {
                            throw new Exception();
                        }

                        // XXX This is not necessary (I believe). I only do this for consistency.
                        labels[y + 1, x] = MarkerValue;
                        var contour = new CvContourChainCode
                        {
                            StartingPoint = new CvPoint(x, y)
                        };

                        int direction = 3;
                        int xx        = x;
                        int yy        = y;

                        do
                        {
                            for (int numAttempts = 0; numAttempts < 3; numAttempts++)
                            {
                                bool found = false;

                                for (int i = 0; i < 3; i++)
                                {
                                    int nx = xx + MovesI[direction, i, 0];
                                    int ny = yy + MovesI[direction, i, 1];
                                    if (imgIn[nx + ny * step] != 0)
                                    {
                                        found = true;
                                        contour.ChainCode.Add((CvChainCode)MovesI[direction, i, 3]);
                                        xx        = nx;
                                        yy        = ny;
                                        direction = MovesI[direction, i, 2];
                                        break;
                                    }
                                    labels[ny, nx] = MarkerValue;
                                }

                                if (!found)
                                {
                                    direction = (direction + 1) % 4;
                                }
                                else
                                {
                                    if (labels[yy, xx] == 0)
                                    {
                                        labels[yy, xx] = l;
                                        numPixels++;

                                        blob.Area++;
                                        blob.M10 += xx;
                                        blob.M01 += yy;
                                        blob.M11 += xx * yy;
                                        blob.M20 += xx * xx;
                                        blob.M02 += yy * yy;
                                    }
                                    break;
                                }
                            }
                        } while (!(xx == x && yy == y));

                        blob.InternalContours.Add(contour);
                    }

                    //else if (!imageOut(x, y))
                    if (!labeled)
                    {
                        // Internal pixel
                        int l = labels[y, x - 1];
                        labels[y, x] = l;
                        numPixels++;

                        CvBlob blob;
                        if (l == lastLabel)
                        {
                            blob = lastBlob;
                        }
                        else
                        {
                            blob      = blobs[l];
                            lastLabel = l;
                            lastBlob  = blob;
                        }
                        if (blob == null)
                        {
                            throw new Exception();
                        }
                        blob.Area++;
                        blob.M10 += x;
                        blob.M01 += y;
                        blob.M11 += x * y;
                        blob.M20 += x * x;
                        blob.M02 += y * y;
                    }
                }
            }


            foreach (var kv in blobs)
            {
                kv.Value.SetMoments();
            }

            return(numPixels);
        }
예제 #33
0
    bool DetectHands(CvBlob blob)
    {
        double cthresh = 0.0;
        Mat blobMat = new Mat(fgthresh, blob.Rect);
        Cv2.Blur(blobMat, blobMat, new Size(5, 5));
        //Cv2.Canny(blobMat, blobMat, cthresh, cthresh * 2, 3);
        Mat[] contoursQuery;
        OutputArray hierarchyQ = InputOutputArray.Create(new List<Vec4i>());
        blobMat.FindContours(out contoursQuery, hierarchyQ, OpenCvSharp.ContourRetrieval.CComp, OpenCvSharp.ContourChain.ApproxTC89KCOS);
        double scoreTotal = 0.0;
        double tested = 0.0;
        foreach (var modelContours in handsContours)
        {
            foreach (var contourToMatch in contoursQuery)
            {
                foreach (var contourB in modelContours)
                {
                        double ratio = Cv2.MatchShapes(contourToMatch, contourB, MatchShapesMethod.I1);
                        //Debug.Log("Matching: " + ratio + " " + contourB.IsContourConvex() + " " + contourToMatch.IsContourConvex() );
                        //if (ratio > 0.0000001)
                        //{
                            scoreTotal += ratio;
                            tested++;
                        //}

                }
            }
        }
        scoreTotal /= tested;
        //Debug.Log(scoreTotal);
        if (scoreTotal > 0.0000001 && scoreTotal <= handsThreshold)
        {
            return true;
        }else{
            return false;
        }
    }
예제 #34
0
 /// <summary>
 /// Draws or prints information about a blob.
 /// </summary>
 /// <param name="labels">Label data.</param>
 /// <param name="blob">Blob.</param>
 /// <param name="imgSource">Input image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 /// <param name="imgDest">Output image (depth=IPL_DEPTH_8U and num. channels=3).</param>
 public static void RenderBlob(LabelData labels, CvBlob blob, Mat imgSource, Mat imgDest)
 {
     RenderBlob(labels, blob, imgSource, imgDest, (RenderBlobsModes)0x000f, Scalar.White, 1.0);
 }