public static Image<Bgr, byte> FindBlobs(Image<Bgr, byte> source)
        {
            //source._EqualizeHist();
            var edges = new Image<Bgr, byte>(source.Width, source.Height);
            // source.SmoothMedian(5);
            for (int i = 0; i < 3; i++)
                edges[i] = source[i].Canny(new Gray(100), new Gray(100));
            var distTransformed = new Image<Gray, float>(source.Width, source.Height);
            var grayEdges = edges.Convert<Gray, byte>().Not();
            CvInvoke.cvDistTransform(grayEdges.Ptr, distTransformed.Ptr, DIST_TYPE.CV_DIST_L2, 3, new[] { 1f, 1f }, IntPtr.Zero);
            var byteDist = distTransformed.ThresholdBinaryInv(new Gray(2), new Gray(255)).Convert<Gray, byte>();
            //return byteDist.Convert<Bgr, byte>();
            Image<Gray, byte> mask = new Image<Gray, byte>(byteDist.Width + 2, byteDist.Height + 2);
            mask.ROI = new Rectangle(1,1,byteDist.Width, byteDist.Height);
            CvInvoke.cvCopy(byteDist, mask, IntPtr.Zero);
            mask.ROI = new Rectangle(0, 0, byteDist.Width+2, byteDist.Height+2);
            edges = grayEdges.Convert<Bgr, byte>();
            /* Flood fill */

            for (int i = 0; i < edges.Width; i++)
            {
                for (int j = 0; j < edges.Height; j++)
                {
                    if (mask.Data[j, i, 0] == 0)
                    {
                        var comp = new MCvConnectedComp();
                        CvInvoke.cvFloodFill(
                            edges.Ptr,
                            new Point(i, j),
                            new MCvScalar(200, 200, 200, 0), // Color
                            new MCvScalar(0, 0, 0), // Lo
                            new MCvScalar(0, 0, 0),  // Up
                            out comp,
                            Emgu.CV.CvEnum.CONNECTIVITY.EIGHT_CONNECTED,
                            Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT,
                            mask.Ptr
                        );

                        if (comp.area > 500 && comp.area < 2500
                            && comp.rect.Size.Height > 10 && comp.rect.Size.Height < 130
                            && comp.rect.Size.Width > 10 && comp.rect.Size.Width < 130)
                        {
                            ReplaceColors(edges, comp.rect);
                        }
                    }
                }
            }

            //TrackBlobs(edges, source);
            return edges;
        }
        public Image<Bgr, Byte> GetMoving(Image<Bgr, Byte> source)
        {
            //var sub = currentImage.AbsDiff(_prevImage).Convert<Gray, Byte>();
            var difference = MovingDetection(source).Convert<Gray, Byte>();
            _prevImage = source.Copy();
            difference = difference.ThresholdBinary(new Gray(50), new Gray(255));
            var distTransformed = new Image<Gray, float>(source.Width, source.Height);
            CvInvoke.cvDistTransform(difference.Ptr, distTransformed.Ptr, DIST_TYPE.CV_DIST_L2, 3, new[] { 1f, 1f }, IntPtr.Zero);
            var byteDist = distTransformed.ThresholdBinary(new Gray(2), new Gray(255)).Convert<Gray, byte>();

            Image<Gray, byte> mask = new Image<Gray, byte>(byteDist.Width + 2, byteDist.Height + 2);
            mask.ROI = new Rectangle(1, 1, byteDist.Width, byteDist.Height);
            CvInvoke.cvCopy(byteDist, mask, IntPtr.Zero);
            mask.ROI = new Rectangle(0, 0, byteDist.Width + 2, byteDist.Height + 2);
            mask = mask.Not();
            //return mask.Convert<Bgr, Byte>();

            var result = mask.Convert<Bgr, Byte>();

            for (int i = 0; i < difference.Width; i++)
            {
                for (int j = 0; j < difference.Height; j++)
                {
                    if (mask.Data[j, i, 0] == 0)
                    {
                        var comp = new MCvConnectedComp();
                        CvInvoke.cvFloodFill(
                            difference.Ptr,
                            new Point(i, j),
                            new MCvScalar(200, 200, 200, 0), // Color
                            new MCvScalar(0, 0, 0), // Lo
                            new MCvScalar(0, 0, 0),  // Up
                            out comp,
                            Emgu.CV.CvEnum.CONNECTIVITY.EIGHT_CONNECTED,
                            Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT,
                            mask.Ptr
                        );

                        if (comp.area > 500 && comp.area < 2500
                            && comp.rect.Size.Height > 10 && comp.rect.Size.Height < 230
                            && comp.rect.Size.Width > 10 && comp.rect.Size.Width < 230)
                        {
                            ReplaceColors(result, comp.rect);
                        }
                    }
                }
            }

            return result.Convert<Bgr, Byte>();
        }
        public ObjectTracking(Image<Bgr, Byte> image, Rectangle ROI)
        {
            // Initialize parameters
            trackbox = new MCvBox2D();
            trackcomp = new MCvConnectedComp();
            hue = new Image<Gray, byte>(image.Width, image.Height);
            hue._EqualizeHist();
            mask = new Image<Gray, byte>(image.Width, image.Height);
            hist = new DenseHistogram(30, new RangeF(0, 180));
            backproject = new Image<Gray, byte>(image.Width, image.Height);

            // Assign Object's ROI from source image.
            trackingWindow = ROI;

            // Producing Object's hist
            CalObjectHist(image);
        }
Example #4
0
 /// <summary>
 /// Fills a connected component with given color.
 /// </summary>
 /// <param name="src">Input 1- or 3-channel, 8-bit or floating-point image. It is modified by the function unless CV_FLOODFILL_MASK_ONLY flag is set.</param>
 /// <param name="seedPoint">The starting point.</param>
 /// <param name="newVal">New value of repainted domain pixels.</param>
 /// <param name="loDiff">Maximal lower brightness/color difference
 /// between the currently observed pixel and one of its neighbor belong to the component
 /// or seed pixel to add the pixel to component.
 /// In case of 8-bit color images it is packed value.</param>
 /// <param name="upDiff">Maximal upper brightness/color difference
 /// between the currently observed pixel and one of its neighbor belong to the component
 /// or seed pixel to add the pixel to component.
 /// In case of 8-bit color images it is packed value.</param>
 /// <param name="comp">Pointer to structure the function fills with the information about the repainted domain.</param>
 /// <param name="mask">Operation mask,
 /// should be singe-channel 8-bit image, 2 pixels wider and 2 pixels taller than image.
 /// If not IntPtr.Zero, the function uses and updates the mask, so user takes responsibility of initializing mask content.
 /// Floodfilling can't go across non-zero pixels in the mask, for example, an edge detector output can be used as a mask to stop filling at edges.
 /// Or it is possible to use the same mask in multiple calls to the function to make sure the filled area do not overlap.
 /// Note: because mask is larger than the filled image, pixel in mask that corresponds to (x,y) pixel in image will have coordinates (x+1,y+1).</param>
 /// <param name="connectivity">The connectivity of flood fill</param>
 /// <param name="flags">The flood fill types</param>
 public static void cvFloodFill(
    IntPtr src,
    Point seedPoint,
    MCvScalar newVal,
    MCvScalar loDiff,
    MCvScalar upDiff,
    out MCvConnectedComp comp,
    CvEnum.CONNECTIVITY connectivity,
    CvEnum.FLOODFILL_FLAG flags,
    IntPtr mask)
 {
    cvFloodFill(src, seedPoint, newVal, loDiff, upDiff, out comp, (int)connectivity | (int)flags, mask);
 }
Example #5
0
 public static extern void cvFloodFill(
    IntPtr src,
    Point seedPoint,
    MCvScalar newVal,
    MCvScalar loDiff,
    MCvScalar upDiff,
    out MCvConnectedComp comp,
    int flags,
    IntPtr mask);
Example #6
0
 private static extern void cvFloodFill(
    IntPtr src,
    int seedPointX, int seedPointY,
    double newVal0, double newVal1, double newVal2, double newVal3, 
    double loDiff0, double loDiff1, double loDiff2, double loDiff3,
    double upDiff0, double upDiff1, double upDiff2, double upDiff3,
    out MCvConnectedComp comp,
    int flags,
    IntPtr mask);
Example #7
0
      /// <summary>
      /// Fills a connected component with given color.
      /// </summary>
      /// <param name="src">Input 1- or 3-channel, 8-bit or floating-point image. It is modified by the function unless CV_FLOODFILL_MASK_ONLY flag is set.</param>
      /// <param name="seedPoint">The starting point.</param>
      /// <param name="newVal">New value of repainted domain pixels.</param>
      /// <param name="loDiff">Maximal lower brightness/color difference
      /// between the currently observed pixel and one of its neighbor belong to the component
      /// or seed pixel to add the pixel to component.
      /// In case of 8-bit color images it is packed value.</param>
      /// <param name="upDiff">Maximal upper brightness/color difference
      /// between the currently observed pixel and one of its neighbor belong to the component
      /// or seed pixel to add the pixel to component.
      /// In case of 8-bit color images it is packed value.</param>
      /// <param name="comp">Pointer to structure the function fills with the information about the repainted domain.</param>
      /// <param name="flags">The operation flags.
      /// Lower bits contain connectivity value, 4 (by default) or 8, used within the function.
      /// Connectivity determines which neighbors of a pixel are considered.
      /// Upper bits can be 0 or combination of the following flags:
      /// CV_FLOODFILL_FIXED_RANGE - if set the difference between the current pixel and seed pixel is considered,
      /// otherwise difference between neighbor pixels is considered (the range is floating).
      /// CV_FLOODFILL_MASK_ONLY - if set, the function does not fill the image (new_val is ignored),
      /// but the fills mask (that must be non-NULL in this case). </param>
      /// <param name="mask">Operation mask,
      /// should be singe-channel 8-bit image, 2 pixels wider and 2 pixels taller than image.
      /// If not IntPtr.Zero, the function uses and updates the mask, so user takes responsibility of initializing mask content.
      /// Floodfilling can't go across non-zero pixels in the mask, for example, an edge detector output can be used as a mask to stop filling at edges.
      /// Or it is possible to use the same mask in multiple calls to the function to make sure the filled area do not overlap.
      /// Note: because mask is larger than the filled image, pixel in mask that corresponds to (x,y) pixel in image will have coordinates (x+1,y+1).</param>
#if ANDROID
      public static void cvFloodFill(
         IntPtr src,
         Point seedPoint,
         MCvScalar newVal,
         MCvScalar loDiff,
         MCvScalar upDiff,
         out MCvConnectedComp comp,
         int flags,
         IntPtr mask)
      {
         cvFloodFill(
            src,
            seedPoint.X, seedPoint.Y,
            newVal.v0, newVal.v1, newVal.v2, newVal.v3,
            loDiff.v0, loDiff.v1, loDiff.v2, loDiff.v3,
            upDiff.v0, upDiff.v1, upDiff.v2, upDiff.v3,
            out comp,
            flags,
            mask);
      }
        public static List<Event> GetBlobEvents(Image<Bgr, byte> source)
        {
            var events = new List<Event>();

            //source._EqualizeHist();
            var edges = new Image<Bgr, byte>(source.Width, source.Height);
            // source.SmoothMedian(5);
            for (int i = 0; i < 3; i++)
                edges[i] = source[i].Canny(new Gray(100), new Gray(100));
            var distTransformed = new Image<Gray, float>(source.Width, source.Height);
            var grayEdges = edges.Convert<Gray, byte>().Not();
            CvInvoke.cvDistTransform(grayEdges.Ptr, distTransformed.Ptr, DIST_TYPE.CV_DIST_L2, 3, new[] { 1f, 1f }, IntPtr.Zero);
            var byteDist = distTransformed.ThresholdBinaryInv(new Gray(2), new Gray(255)).Convert<Gray, byte>();
            //return byteDist.Convert<Bgr, byte>();
            Image<Gray, byte> mask = new Image<Gray, byte>(byteDist.Width + 2, byteDist.Height + 2);
            mask.ROI = new Rectangle(1, 1, byteDist.Width, byteDist.Height);
            CvInvoke.cvCopy(byteDist, mask, IntPtr.Zero);
            mask.ROI = new Rectangle(0, 0, byteDist.Width + 2, byteDist.Height + 2);
            edges = grayEdges.Convert<Bgr, byte>();
            /* Flood fill */

            for (int i = 0; i < edges.Width; i++)
            {
                for (int j = 0; j < edges.Height; j++)
                {
                    if (mask.Data[j, i, 0] == 0)
                    {
                        var comp = new MCvConnectedComp();
                        CvInvoke.cvFloodFill(
                            edges.Ptr,
                            new Point(i, j),
                            new MCvScalar(200, 200, 200, 0), // Color
                            new MCvScalar(0, 0, 0), // Lo
                            new MCvScalar(0, 0, 0),  // Up
                            out comp,
                            CONNECTIVITY.FOUR_CONNECTED,
                            FLOODFILL_FLAG.DEFAULT,
                            mask.Ptr
                        );

                        if (IsMouse(comp, source, mask))
                        {
                            events.Add(new Event(comp, Event.EventType.ObjectIsFounded));
                        }
                    }
                }
            }
            return events;
        }
 private static bool IsMouse(MCvConnectedComp comp, Image<Bgr, byte> source, Image<Gray, byte> sourcemask)
 {
     if (!IsAreaSizeMousable(comp))
         return false;
     return IsAreaColorMousable(comp, source, sourcemask);
 }
 private static bool IsAreaSizeMousable(MCvConnectedComp comp)
 {
     return comp.area > 500 && comp.area < 2500
            && comp.rect.Size.Height > 10 && comp.rect.Size.Height < 130
            && comp.rect.Size.Width > 10 && comp.rect.Size.Width < 130;
 }
Example #11
0
 public static extern int cvCamShift(
     IntPtr probImage,
     Rectangle window,
     MCvTermCriteria criteria,
     out MCvConnectedComp comp,
     out MCvBox2D box);
Example #12
0
 public static extern int cvMeanShift(
     IntPtr probImage,
     Rectangle window,
     MCvTermCriteria criteria,
     out MCvConnectedComp comp);
        public List<Event> GetMovingEvents(Image<Bgr, Byte> source)
        {
            var events = new List<Event>();

            var difference = MovingDetection(source).Convert<Gray, Byte>();
            _prevImage = source.Copy();
            difference = difference.ThresholdBinary(new Gray(80), new Gray(255));
            var distTransformed = new Image<Gray, float>(source.Width, source.Height);
            CvInvoke.cvDistTransform(difference.Ptr, distTransformed.Ptr, DIST_TYPE.CV_DIST_L2, 3, new[] { 1f, 1f }, IntPtr.Zero);
            var byteDist = distTransformed.ThresholdBinary(new Gray(1), new Gray(255)).Convert<Gray, byte>();

            Image<Gray, byte> mask = new Image<Gray, byte>(byteDist.Width + 2, byteDist.Height + 2);
            mask.ROI = new Rectangle(1, 1, byteDist.Width, byteDist.Height);
            CvInvoke.cvCopy(byteDist, mask, IntPtr.Zero);
            mask.ROI = new Rectangle(0, 0, byteDist.Width + 2, byteDist.Height + 2);
            mask = mask.Not();
            //return mask.Convert<Bgr, Byte>();

            var result = difference.Convert<Bgr, Byte>();

            for (int i = 0; i < difference.Width; i++)
            {
                for (int j = 0; j < difference.Height; j++)
                {
                    if (mask.Data[j, i, 0] == 0)
                    {
                        var comp = new MCvConnectedComp();
                        CvInvoke.cvFloodFill(
                            difference.Ptr,
                            new Point(i, j),
                            new MCvScalar(200, 200, 200, 0), // Color
                            new MCvScalar(0, 0, 0), // Lo
                            new MCvScalar(0, 0, 0),  // Up
                            out comp,
                            Emgu.CV.CvEnum.CONNECTIVITY.EIGHT_CONNECTED,
                            Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT,
                            mask.Ptr
                        );

                        if (comp.area > 500 && comp.area < 2500
                            && comp.rect.Size.Height > 10 && comp.rect.Size.Height < 230
                            && comp.rect.Size.Width > 10 && comp.rect.Size.Width < 230
                            && BlobDetector.IsAreaColorMousable(comp, source, mask))
                        {
                            events.Add(new Event(comp.rect, Event.EventType.SomethingIsMoving));
                        }
                    }
                }
            }
            return events.Count > 3 ? new List<Event>() : events;
        }
Example #14
0
 public Event(MCvConnectedComp comp, EventType type)
 {
     EventCoords = comp.rect;
     AverageColor = new Bgr(comp.value.v0, comp.value.v1, comp.value.v2);
     Type = type;
 }
 public static bool IsAreaColorMousable(MCvConnectedComp comp, Image<Bgr, byte> source, Image<Gray, byte> sourcemask)
 {
     var newRect = new Rectangle(comp.rect.Left, comp.rect.Top, comp.rect.Width, comp.rect.Height);
     newRect.Inflate(-4, -4);
     var mask = sourcemask.SmoothGaussian(7).Dilate(7).Erode(7).Copy();
     var oldRoi = source.ROI;
     var oldMaskRoi = mask.ROI;
     source.ROI = newRect;
     mask.ROI = newRect;
     var hlscolor = source.Convert<Hls, byte>().GetAverage(mask);
     var rgbcolor = source.GetAverage(mask);
     using (var file = new System.IO.StreamWriter("output.html", true))
     {
         file.Write(
             "<p><div style=\"background-color: #{3:X2}{4:X2}{5:X2}; width: 24px; height: 24px; float: left;\"></div>{0}, {1}, {2}</p>",
             hlscolor.Hue, hlscolor.Lightness, hlscolor.Satuation, (int) rgbcolor.Red, (int) rgbcolor.Green, (int) rgbcolor.Blue);
     }
     //mask.Convert<Bgr, byte>().Copy(source, mask);
     source.ROI = oldRoi;
     mask.ROI = oldMaskRoi;
     //source.Draw(comp.rect, rgbcolor, -1);
     return hlscolor.Lightness > 102 && hlscolor.Hue < 160 && hlscolor.Satuation < 80;
 }