Пример #1
0
        /// <summary>
        /// Generates a circular mask to use in morphological operations
        /// with the anchor in the center
        /// </summary>
        /// <param name="radius">The radius of the mask as maximum distance from center pixel (i.e. radius=0 would be 1-pixel mask)</param>
        /// <returns>The mask</returns>
        public static MorphologyMask GenerateDiskMask(int radius)
        {
            if (radius < 1)
            {
                throw new ArgumentOutOfRangeException("radius");
            }
            //Masks in ipps morphological functions don't really allow for stride
            //unless it is guaranteed, that the pixels within the stride are of value0
            //therefore we generate the mask with the minimum possible width and height
            //that is dividable by 4
            int       diameter   = 1 + 2 * radius;//center pixel is extra
            int       imageWidth = (int)(Math.Ceiling(diameter / 4.0) * 4);
            IppiPoint center     = new IppiPoint(radius, radius);
            Image8    mask       = new Image8(imageWidth, diameter);

            //Set all pixels to 0
            IppHelper.IppCheckCall(ip.ippiSet_8u_C1R(0, mask.Image, mask.Stride, mask.Size));
            //Loop over pixels, check distance and set to 1 if within circle
            for (int x = 0; x < mask.Width; x++)
            {
                for (int y = 0; y < mask.Width; y++)
                {
                    if (Distance.Euclidian(new IppiPoint(x, y), center) <= radius)
                    {
                        *mask[x, y] = 1;
                    }
                }
            }
            //default anchor is in the circle's center
            return(new MorphologyMask(mask, center));
        }
Пример #2
0
        /// <summary>
        /// Performs a 3x3 opening operation on an image - removes speckles
        /// </summary>
        /// <param name="imIn">The image to perform an opening operation on</param>
        /// <param name="imOpened">The image after the opening operation</param>
        /// <param name="imCalc">Intermediate image for semi-processed version</param>
        /// <param name="region">The ROI in which to perform the operation</param>
        public static void Open3x3(Image8 imIn, Image8 imOpened, Image8 imCalc, IppiROI roi)
        {
            //Modify region we operate on to allow mask overhang
            var inner = new IppiROI(roi.X + 1, roi.Y + 1, roi.Width - 3, roi.Height - 3);

            IppHelper.IppCheckCall(ip.ippiErode3x3_8u_C1R(imIn[inner.TopLeft], imIn.Stride, imCalc[inner.TopLeft], imCalc.Stride, inner.Size));
            IppHelper.IppCheckCall(ip.ippiDilate3x3_8u_C1R(imCalc[inner.TopLeft], imCalc.Stride, imOpened[inner.TopLeft], imOpened.Stride, inner.Size));
        }
Пример #3
0
        /// <summary>
        /// Performs an opening operation in the specified ROI using the specified
        /// neighborhood mask
        /// </summary>
        /// <param name="imIn">The image to perform the opening operation on</param>
        /// <param name="imOpened">The image after the opening operation</param>
        /// <param name="imCalc">Intermediate buffer for processing</param>
        /// <param name="neighborhood">The mask for the opening operation</param>
        /// <param name="region">The image region in which to perform the operation</param>
        public static void Open(Image8 imIn, Image8 imOpened, Image8 imCalc, MorphologyMask neighborhood, IppiROI roi)
        {
            //Modify region we operate on to allow mask overhang
            var inner = new IppiROI(roi.X + neighborhood.Anchor.x, roi.Y + neighborhood.Anchor.y, roi.Width - neighborhood.Mask.Width, roi.Height - neighborhood.Mask.Height);

            IppHelper.IppCheckCall(ip.ippiErode_8u_C1R(imIn[inner.TopLeft], imIn.Stride, imCalc[inner.TopLeft], imCalc.Stride, inner.Size, neighborhood.Mask.Image, neighborhood.Mask.Size, neighborhood.Anchor));
            IppHelper.IppCheckCall(ip.ippiDilate_8u_C1R(imCalc[inner.TopLeft], imCalc.Stride, imOpened[inner.TopLeft], imOpened.Stride, inner.Size, neighborhood.Mask.Image, neighborhood.Mask.Size, neighborhood.Anchor));
        }
Пример #4
0
 /// <summary>
 /// Multiplies the mask with the image effectively removing
 /// parts outside the mask
 /// </summary>
 /// <param name="image">The image to mask</param>
 public void MaskImage(Image8 image)
 {
     if (!_maskValid)
     {
         GenerateMask();
     }
     IppHelper.IppCheckCall(ip.ippiMul_8u_C1IRSfs(_mask.Image, _mask.Stride, image.Image, image.Stride, image.Size, 0));
 }
Пример #5
0
 public override void UpdateBackground(Image8 im)
 {
     if (im.Width != width || im.Height != height)
     {
         throw new ArgumentException("The supplied image must have the same dimensions as the background");
     }
     IppHelper.IppCheckCall(cv.ippiAddWeighted_8u32f_C1IR(im.Image, im.Stride, background.Image, background.Stride, im.Size, FractionUpdate));
 }
Пример #6
0
 //Construct 32F image using an 8-bit unsigned image as input
 public Image32F(Image8 im)
 {
     Width  = im.Width;
     Height = im.Height;
     Size   = new IppiSize(Width, Height);
     Stride = 4 * Width;
     Image  = (float *)Marshal.AllocHGlobal(Stride * Height).ToPointer();
     //convert image
     IppHelper.IppCheckCall(ip.ippiConvert_8u32f_C1R(im.Image, im.Stride, Image, Stride, Size));
 }
Пример #7
0
 //Construct 16-bit image using an 8-bit unsigned image as input
 public Image16(Image8 im)
 {
     Width  = im.Width;
     Height = im.Height;
     Size   = new IppiSize(Width, Height);
     Stride = (int)(4 * Math.Ceiling(Width * 2 / 4.0));
     Image  = (ushort *)Marshal.AllocHGlobal(Stride * Height).ToPointer();
     //scale, convert and copy image
     IppHelper.IppCheckCall(ip.ippiScale_8u16u_C1R(im.Image, im.Stride, Image, Stride, Size));
     _isFromPinned = false;
 }
 public virtual void UpdateBackground(Image8 im, BlobWithMoments regionToExclude)
 {
     if (regionToExclude == null)
     {
         UpdateBackground(im);
     }
     else
     {
         //reset our mask to <update all>, then fill bounding box with 0s
         ip.ippiSet_8u_C1R(byte.MaxValue, _updateMask.Image, _updateMask.Stride, _updateMask.Size);
         IppiROI roi = new IppiROI(regionToExclude.BoundingBox.x, regionToExclude.BoundingBox.y, regionToExclude.BoundingBox.width, regionToExclude.BoundingBox.height);
         ip.ippiSet_8u_C1R(0, _updateMask[regionToExclude.BB_TopLeft], _updateMask.Stride, regionToExclude.BB_Size);
         IppHelper.IppCheckCall(cv.ippiAddWeighted_8u32f_C1IMR(im.Image, im.Stride, _updateMask.Image, _updateMask.Stride, background.Image, background.Stride, im.Size, FractionUpdate));
     }
 }
Пример #9
0
        /// <summary>
        /// Generates a rectangular mask to use in morphological operations
        /// with the anchor in the center
        /// </summary>
        /// <param name="width">The width of the rectangle</param>
        /// <param name="height">The height of the rectangle</param>
        /// <returns>The morphology mask</returns>
        public static MorphologyMask GenerateRectMask(int width, int height)
        {
            if (width < 1)
            {
                throw new ArgumentOutOfRangeException("width");
            }
            if (height < 1)
            {
                throw new ArgumentOutOfRangeException("height");
            }
            int       imageWidth = (int)(Math.Ceiling(width / 4.0) * 4);
            IppiPoint center     = new IppiPoint((int)Math.Floor(width / 4.0), (int)Math.Floor(height / 4.0));
            Image8    mask       = new Image8(imageWidth, height);

            //Set all pixels to zero
            IppHelper.IppCheckCall(ip.ippiSet_8u_C1R(0, mask.Image, mask.Stride, mask.Size));
            //Set rectangle to 1
            IppHelper.IppCheckCall(ip.ippiSet_8u_C1R(1, mask.Image, mask.Stride, new IppiSize(width, height)));
            return(new MorphologyMask(mask, center));
        }
        /// <summary>
        /// Update background excluding detected regions from the update
        /// </summary>
        /// <param name="im">The new image to add to the background</param>
        /// <param name="regionsToExclude">The blobs that should be excluded from the update</param>
        public virtual void UpdateBackground(Image8 im, BlobWithMoments[] regionsToExclude)
        {
            if (regionsToExclude == null)
            {
                UpdateBackground(im);
            }
            else
            {
                //reset our mask to <update all>, then fill all bounding boxes with 0s
                ip.ippiSet_8u_C1R(byte.MaxValue, _updateMask.Image, _updateMask.Stride, _updateMask.Size);
                foreach (BlobWithMoments b in regionsToExclude)
                {
                    if (b != null)
                    {
                        ip.ippiSet_8u_C1R(0, _updateMask[b.BB_TopLeft], _updateMask.Stride, b.BB_Size);
                    }
                }

                IppHelper.IppCheckCall(cv.ippiAddWeighted_8u32f_C1IMR(im.Image, im.Stride, _updateMask.Image, _updateMask.Stride, background.Image, background.Stride, im.Size, FractionUpdate));
            }
        }
        public virtual void UpdateBackground(Image8 im, Blob[] regionsToExclude)
        {
            if (regionsToExclude == null)//do a simple update
            {
                UpdateBackground(im);
            }
            else
            {
                //reset our mask to <update all>, then fill all bounding boxes with 0s
                ip.ippiSet_8u_C1R(byte.MaxValue, _updateMask.Image, _updateMask.Stride, _updateMask.Size);
                foreach (Blob b in regionsToExclude)
                {
                    if (b != null)
                    {
                        IppiROI roi = new IppiROI(b.BoundingBox);
                        ip.ippiSet_8u_C1R(0, _updateMask[roi.TopLeft], _updateMask.Stride, roi.Size);
                    }
                }

                IppHelper.IppCheckCall(cv.ippiAddWeighted_8u32f_C1IMR(im.Image, im.Stride, _updateMask.Image, _updateMask.Stride, background.Image, background.Stride, im.Size, FractionUpdate));
            }
        }
Пример #12
0
 /// <summary>
 /// Implements a "greater than" threshold like MATLABS
 /// im2bw function
 /// </summary>
 /// <param name="imIn">The image to threshold</param>
 /// <param name="imThresh">The image after thresholding</param>
 /// <param name="region">The ROI in which to perform the operation</param>
 /// <param name="threshold">The threshold to apply</param>
 public static void Im2Bw(Image8 imIn, Image8 imThresh, IppiROI region, byte threshold)
 {
     IppHelper.IppCheckCall(ip.ippiThreshold_LTVal_8u_C1R(imIn[region.TopLeft], imIn.Stride, imThresh[region.TopLeft], imThresh.Stride, region.Size, (byte)(threshold + 1), 0));
     IppHelper.IppCheckCall(ip.ippiThreshold_GTVal_8u_C1IR(imThresh[region.TopLeft], imThresh.Stride, region.Size, threshold, 255));
 }
Пример #13
0
        void GenerateMask()
        {
            //To generate the mask, we use a euclidian distance transform to the center pixel
            //followed by a thresholding operation
            //To save resources we only do this within the outer square of the circle since
            //all pixels outside of that square will be black anyway
            double xStart, yStart;

            //compute outer square
            xStart = _center.x - _radius;
            yStart = _center.y - _radius;
            if (xStart < 0)
            {
                xStart = 0;
            }
            if (yStart < 0)
            {
                yStart = 0;
            }
            IppiROI outerSquare = new IppiROI((int)xStart, (int)yStart, 2 * _radius, 2 * _radius);

            if (outerSquare.X + outerSquare.Width >= _mask.Width)
            {
                outerSquare.Width = _mask.Width - outerSquare.X - 1;
            }
            if (outerSquare.Y + outerSquare.Height >= _mask.Height)
            {
                outerSquare.Height = _mask.Height - outerSquare.Y - 1;
            }

            //The distance transform will calculate for all non-0 pixels the distance to the closest
            //0 pixel - hence we set all pixels in our mask temporarily to 1 and the circles center to 0
            IppHelper.IppCheckCall(ip.ippiSet_8u_C1R(1, _mask.Image, _mask.Stride, _mask.Size));
            IppHelper.IppCheckCall(ip.ippiSet_8u_C1R(0, _mask[Center], _mask.Stride, new IppiSize(1, 1)));
            //initialize buffers and calculate distance transform within outer square
            //we initialize the distance transform image with a value > radius so that all the
            //untouched pixel outside of the outer square will later be set to 0
            int bufferSize;

            IppHelper.IppCheckCall(cv.ippiTrueDistanceTransformGetBufferSize_8u32f_C1R(outerSquare.Size, &bufferSize));
            byte *   dTransBuffer = (byte *)Marshal.AllocHGlobal(bufferSize);
            Image32F distImage    = new Image32F(_mask);

            IppHelper.IppCheckCall(ip.ippiSet_32f_C1R(Radius + 1, distImage.Image, distImage.Stride, distImage.Size));
            IppHelper.IppCheckCall(cv.ippiTrueDistanceTransform_8u32f_C1R(_mask[outerSquare.TopLeft], _mask.Stride, distImage[outerSquare.TopLeft], distImage.Stride, outerSquare.Size, dTransBuffer));

            //set all pixels whose value after the distance transform is >radius to 0
            IppHelper.IppCheckCall(ip.ippiThreshold_GTVal_32f_C1IR(distImage.Image, distImage.Stride, distImage.Size, Radius, 0));
            //now set all pixels whose value is >0 to 1
            IppHelper.IppCheckCall(ip.ippiThreshold_GTVal_32f_C1IR(distImage.Image, distImage.Stride, distImage.Size, 0, 1));
            //convert dist image, copying it into the mask
            IppHelper.IppCheckCall(ip.ippiConvert_32f8u_C1R(distImage.Image, distImage.Stride, _mask.Image, _mask.Stride, _mask.Size, IppRoundMode.ippRndNear));
            //Clean up
            Marshal.FreeHGlobal((IntPtr)dTransBuffer);
            distImage.Dispose();

            _maskValid = true;

            /*
             * //We want to generate the mask with the least amount of pixel-iterations possible
             * //based on the radius we can define to rectangular regions for which we can
             * //bulk-set the pixels
             * //The inner square of the circle is definitely white (centered around center, side-length = sqrt(r*r/2)
             * //The outer square is definitely black (centerered around center, side-length=radius)
             * double sideLength,xStart,yStart;
             *
             * //compute inner square
             * sideLength = Math.Sqrt(_radius * _radius / 2);
             * xStart = _center.x - sideLength / 2;
             * yStart = _center.y - sideLength / 2;
             * if (xStart < 0)
             *  xStart = 0;
             * if (yStart < 0)
             *  yStart = 0;
             * IppiROI innerSquare = new IppiROI((int)xStart, (int)yStart, (int)sideLength, (int)sideLength);
             * if (innerSquare.X + innerSquare.Width >= _mask.Width)
             * {
             *  innerSquare.Width = _mask.Width - innerSquare.X - 1;
             * }
             * if (innerSquare.Y + innerSquare.Height >= _mask.Height)
             * {
             *  innerSquare.Height = _mask.Height - innerSquare.Y - 1;
             * }
             *
             * //compute outer square
             * xStart = _center.x - _radius / 2.0;
             * yStart = _center.y - _radius / 2.0;
             * if (xStart < 0)
             *  xStart = 0;
             * if (yStart < 0)
             *  yStart = 0;
             * IppiROI outerSquare = new IppiROI((int)xStart, (int)yStart, _radius, _radius);
             * if (outerSquare.X + outerSquare.Width >= _mask.Width)
             * {
             *  outerSquare.Width = _mask.Width - outerSquare.X - 1;
             * }
             * if (outerSquare.Y + outerSquare.Height >= _mask.Height)
             * {
             *  outerSquare.Height = _mask.Height - outerSquare.Y - 1;
             * }
             *
             * //set whole image to black and inner square to 1
             * IppHelper.IppCheckCall(ip.ippiSet_8u_C1R(0, _mask.Image, _mask.Stride, _mask.Size));
             * IppHelper.IppCheckCall(ip.ippiSet_8u_C1R(1, _mask[innerSquare.TopLeft], _mask.Stride, innerSquare.Size));
             *
             * //loop over all the pixels that are in between the boundaries of the outer
             * //and inner square, measure their distance to the center and
             * //p = d>r?0:1;
             */
        }
Пример #14
0
 /// <summary>
 /// Scale image to 8bit representation avoiding clipping
 /// </summary>
 /// <param name="im"></param>
 public void ReduceTo8U(Image8 im)
 {
     System.Diagnostics.Debug.Assert(im.Width == Width);
     System.Diagnostics.Debug.Assert(im.Height == Height);
     IppHelper.IppCheckCall(ip.ippiScale_16u8u_C1R(Image, Stride, im.Image, im.Stride, Size, IppHintAlgorithm.ippAlgHintFast));
 }
Пример #15
0
 public void ReduceTo8U(Image8 im)
 {
     System.Diagnostics.Debug.Assert(im.Width == Width);
     System.Diagnostics.Debug.Assert(im.Height == Height);
     IppHelper.IppCheckCall(ip.ippiConvert_32f8u_C1R(Image, Stride, im.Image, im.Stride, Size, IppRoundMode.ippRndZero));
 }