/// <summary> /// Safely copies region around given centroid /// </summary> /// <param name="centroid">The centroid around which image region should be copied</param> /// <param name="regionImage">The target of the copy</param> /// <param name="image">The source of the copy operation</param> public static void CopyRegionImage(IppiPoint centroid, Image8 regionImage, Image8 image) { IppiPoint copyStart = new IppiPoint(centroid.x - regionImage.Width / 2, centroid.y - regionImage.Height / 2); int destX = 0; int destY = 0; if (copyStart.x < 0) { destX -= copyStart.x; copyStart.x = 0; } if (copyStart.y < 0) { destY -= copyStart.y; copyStart.y = 0; } IppiSize copySize = new IppiSize(regionImage.Width - destX, regionImage.Height - destY); if (copyStart.x + copySize.width > image.Width) { copySize.width = image.Width - copyStart.x; } if (copyStart.y + copySize.height > image.Height) { copySize.height = image.Height - copyStart.y; } if (copySize.width > 0 && copySize.height > 0) { ip.ippiCopy_8u_C1R(image[copyStart], image.Stride, regionImage[destX, destY], regionImage.Stride, copySize); } }
/// <summary> /// Finds the location of the laser beam in the camera image /// </summary> /// <param name="image">The current image in which to find the beam</param> /// <param name="background">The calculated background image</param> /// <param name="calc">Image buffer for intermediate calculations</param> /// <param name="foreground">Image buffer for foreground extraction</param> /// <returns></returns> private IppiPoint FindBeamLocation(Image8 image, Image8 background, Image8 calc, Image8 foreground) { IppiSize imageSize = new IppiSize(image.Width, image.Height); //Clear foreground and calc ip.ippiSet_8u_C1R(0, foreground.Image, foreground.Stride, imageSize); ip.ippiSet_8u_C1R(0, calc.Image, calc.Stride, imageSize); //Perform background subtraction cv.ippiAbsDiff_8u_C1R(image.Image, image.Stride, background.Image, background.Stride, calc.Image, calc.Stride, imageSize); //remove noise via 3x3 median filtering ip.ippiFilterMedianWeightedCenter3x3_8u_C1R(calc[2, 2], calc.Stride, foreground[2, 2], foreground.Stride, new IppiSize(image.Width - 4, image.Height - 4), 1); //threshold difference ip.ippiThreshold_LTVal_8u_C1IR(foreground.Image, foreground.Stride, imageSize, 111, 0); ip.ippiThreshold_GTVal_8u_C1IR(foreground.Image, foreground.Stride, imageSize, 110, 255); //perform closing operation - 2 step to put result back into foreground _strel3x3.Dilate(foreground, calc, imageSize); _strel3x3.Erode(calc, foreground, imageSize); //feature extraction int nMarkers = 0; cv.ippiLabelMarkers_8u_C1IR(foreground.Image, foreground.Stride, imageSize, 1, 254, IppiNorm.ippiNormInf, &nMarkers, _markerBuffer); BlobWithMoments[] blobsDetected = BlobWithMoments.ExtractBlobs(foreground, nMarkers, new IppiROI(0, 0, image.Width, image.Height)); //re-threshold foreground for display ip.ippiThreshold_LTVal_8u_C1IR(foreground.Image, foreground.Stride, imageSize, 1, 0); //6 ip.ippiThreshold_GTVal_8u_C1IR(foreground.Image, foreground.Stride, imageSize, 0, 255); //5 long maxArea = 0; int maxIndex = -1; if (blobsDetected != null) { for (int i = 0; i < blobsDetected.Length; i++) { if (blobsDetected[i] == null) { break; } //Simply note down the largest blob if (blobsDetected[i].Area > maxArea) { maxArea = blobsDetected[i].Area; maxIndex = i; } } // System.Diagnostics.Debug.WriteLine("Area: {0}", blobsDetected[maxIndex].Area); // System.Diagnostics.Debug.WriteLine("Eccentricity: {0}", blobsDetected[maxIndex].Eccentricity); if (maxArea > 30) { return(blobsDetected[maxIndex].Centroid); } else { return(new IppiPoint(-1, -1)); } } else { return(new IppiPoint(-1, -1)); } }
//Construct image with 1 channel and 32-bit floats for each pixel from scratch public Image32F(int width, int height) { Width = width; Height = height; Size = new IppiSize(width, height); Stride = 4 * width; Image = (float *)Marshal.AllocHGlobal(Stride * height).ToPointer(); }
//Construct image with 1 channel and 16bit for each pixel from scratch public Image16(int width, int height) { Width = width; Height = height; Size = new IppiSize(width, height); Stride = (int)(4 * Math.Ceiling(width * 2 / 4.0)); Image = (ushort *)Marshal.AllocHGlobal(Stride * height).ToPointer(); _isFromPinned = false; }
//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)); }
//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; }
/// <summary> /// Constructs a new DeltaPixel class /// </summary> /// <param name="threshold">The threshold to use to separate imaging noise from signal</param> /// <param name="imageSize">The size of the images that will be supplied</param> public DeltaPixel(byte threshold, IppiSize imageSize) { _threshold = threshold; _imPrevious = new Image8(imageSize); _imDelta = new Image8(imageSize); _imThresh = new Image8(imageSize); _isFirst = true; //blank images ip.ippiSet_8u_C1R(0, _imPrevious.Image, _imPrevious.Stride, _imPrevious.Size); ip.ippiSet_8u_C1R(0, _imDelta.Image, _imDelta.Stride, _imDelta.Size); ip.ippiSet_8u_C1R(0, _imThresh.Image, _imThresh.Stride, _imThresh.Size); }
/// <summary> /// Allocate a new Image16 object directly from a pinned /// garbage collected memory buffer /// </summary> /// <param name="imageBuffer">2D image buffer, 4byte aligned</param> public Image16(ushort[,] imageBuffer) { Height = imageBuffer.GetLength(0); Width = imageBuffer.GetLength(1); Stride = (int)(4 * Math.Ceiling(2.0 * Width / 4.0)); if (Stride != 2 * Width) { throw new ArgumentException("Can only accept 4-byte aligned 2D image buffers!"); } Size = new IppiSize(Width, Height); _hImage = GCHandle.Alloc(imageBuffer, GCHandleType.Pinned); Image = (ushort *)_hImage.AddrOfPinnedObject().ToPointer(); _isFromPinned = true; }
/// <summary> /// Rotates a coordinate within a given reference frame /// </summary> /// <param name="original">The original coordinate</param> /// <param name="size">The dimensions of the reference frame</param> /// <param name="rot">The desired rotation</param> /// <returns>The rotated coordinate</returns> public static IppiPoint Rotate(IppiPoint original, IppiSize size, Rotation rot) { switch (rot) { case Rotation.None: return(original); case Rotation.Clock90: return(new IppiPoint(size.height - original.y, original.x)); case Rotation.Clock180: return(new IppiPoint(size.width - original.x, size.height - original.y)); default: return(new IppiPoint(original.y, size.width - original.x)); } }
/// <summary> /// Inverses a coordinate rotation within a given reference frame /// </summary> /// <param name="original">The rotated coordinate</param> /// <param name="size">The dimensions of the reference frame</param> /// <param name="rot">The original rotation</param> /// <returns>The original point</returns> public static IppiPoint RotateInverse(IppiPoint rotated, IppiSize size, Rotation rot) { switch (rot) { case Rotation.None: return(rotated); case Rotation.Clock90: return(new IppiPoint(rotated.x, size.height - rotated.y)); case Rotation.Clock180: return(new IppiPoint(size.width - rotated.x, size.height - rotated.y)); default: return(new IppiPoint(size.width - rotated.y, rotated.x)); } }
/// <summary> /// Creates a new tail tracker /// </summary> /// <param name="regionToTrack">The ROI in which we should track the tail</param> /// <param name="tailStart">The designated starting point of the tail</param> /// <param name="tailEnd">The designated end point of the tail</param> /// <param name="nsegments">The number of tail segments to track btw. start and end</param> public TailTracker(IppiSize imageSize, IppiPoint tailStart, IppiPoint tailEnd, int nsegments) { _threshold = 20; _morphSize = 8; _frameRate = 200; _strel = BWImageProcessor.GenerateDiskMask(_morphSize); _nSegments = 5; _imageSize = imageSize; _tailStart = tailStart; _tailEnd = tailEnd; //set up our track regions based on the tail positions DefineTrackRegions(); NSegments = nsegments; InitializeImageBuffers(); //set up image buffers InitializeScanPoints(); //create scan points appropriate for the tail parameters //Initialize our angle store for tracking (size never changes) _angleStore = (int *)System.Runtime.InteropServices.Marshal.AllocHGlobal(900 * 4); }
unsafe private Bitmap ApplyFilterSobelVert() { // This is the file name to process string fileName = @"C:\Pictures\Test.jpg"; var originalImage = new Bitmap(fileName); var srcBitmapData = GetBitmapData( originalImage, ImageLockMode.ReadOnly); var destinationImage = new Bitmap( originalImage.Width, originalImage.Height); var dstBitmapData = GetBitmapData( destinationImage, ImageLockMode.ReadWrite); IppiSize roi = new IppiSize( originalImage.Width - 3, originalImage.Height - 3); const int ksize = 5; const int half = ksize / 2; byte * pSrc = (byte *)srcBitmapData.Scan0 + (srcBitmapData.Stride + 3) * half; byte *pDst = (byte *)dstBitmapData.Scan0 + (dstBitmapData.Stride + 3) * half; IppStatus status = ipp.ip.ippiFilterSobelVert_8u_C3R( pSrc, srcBitmapData.Stride, pDst, dstBitmapData.Stride, roi); // Unlock bits for both source and destination originalImage.UnlockBits(srcBitmapData); destinationImage.UnlockBits(dstBitmapData); return(destinationImage); }
public Image8(IppiSize imageSize) : this(imageSize.width, imageSize.height) { }
/// <summary> /// Creates a new circular mask object with an arbitrarily centered circle /// </summary> /// <param name="imageSize">The size of the mask image</param> /// <param name="center">The center of the circle</param> /// <param name="radius">The radius of the circle</param> public CircularMask(IppiSize imageSize, IppiPoint center, int radius) { _mask = new Image8(imageSize.width, imageSize.height); Center = center; Radius = radius; }
/// <summary> /// Creates a new circular mask object with a centered circle /// </summary> /// <param name="imageSize">The size of the mask image</param> /// <param name="radius">The radius of the circle</param> public CircularMask(IppiSize imageSize, int radius) : this(imageSize, new IppiPoint((int)imageSize.width / 2, (int)imageSize.height / 2), radius) { }
public Image8BGR(int width, int height) { Stride = (int)(4 * Math.Ceiling(width * 3 / 4.0)); Size = new IppiSize(width, height); Image = (byte *)Marshal.AllocHGlobal(Stride * height).ToPointer(); }
public IppiROI(Rectangle rect) { _size = new IppiSize(rect.Width, rect.Height); _topleft = new IppiPoint(rect.X, rect.Y); }
/// <summary> /// Implements coordinate smoothing analogous to using filtfilt in matlab with a step function kernel /// (moving average with no peak displacement) /// </summary> /// <param name="src">The source track to smoothen</param> /// <param name="dst">The destination buffer for the smoothened track</param> /// <param name="windowSize">The windowsize for averaging</param> public void SmoothenTrack(CentroidBuffer src, CentroidBuffer dst, int windowSize) { if (IsDisposed) { throw new ObjectDisposedException(this.ToString()); } if (src.Size.width != dst.Size.width) { throw new ArgumentException("Source and destination buffers need to have the same size!"); } //For the internal buffers we require a size that fits both the coordinate buffer we //intend to filter as well as the border pixels required for filtering int borderSize = (int)Math.Ceiling(windowSize / 2.0); int reqSize = src.Size.width + borderSize * 2; //Adjust internal buffers if necessary if (_calc1 == null) { _calc1 = new CentroidBuffer(reqSize); _calc2 = new CentroidBuffer(reqSize); } else if (_calc1.Size.width != reqSize) { _calc1.Dispose(); _calc2.Dispose(); _calc1 = new CentroidBuffer(reqSize); _calc2 = new CentroidBuffer(reqSize); } if (_kernel == null) { _kernelSize = windowSize; _kernel = (float *)Marshal.AllocHGlobal(_kernelSize * 4); int i = 0; while (i < _kernelSize) { _kernel[i++] = 1 / (float)_kernelSize; } } else if (_kernelSize != windowSize) { Marshal.FreeHGlobal((IntPtr)_kernel); _kernelSize = windowSize; _kernel = (float *)Marshal.AllocHGlobal(_kernelSize * 4); int i = 0; while (i < _kernelSize) { _kernel[i++] = 1 / (float)_kernelSize; } } //filter parameters IppiSize regionSize = new IppiSize(src.Size.width, 1); IppiPoint anchor = new IppiPoint(borderSize, 0); IppiSize kernelSize = new IppiSize(_kernelSize, 1); float * calc1XStart = (float *)((byte *)_calc1.Buffer + borderSize * 4); float * calc1YStart = (float *)((byte *)_calc1.Buffer + borderSize * 4 + _calc1.Stride); float * calc2XStart = (float *)((byte *)_calc2.Buffer + borderSize * 4); float * calc2YStart = (float *)((byte *)_calc2.Buffer + borderSize * 4 + _calc2.Stride); //Copy src buffer adding borders IppHelper.IppCheckCall(ip.ippiCopyConstBorder_32f_C1R(src.Buffer, src.Stride, src.Size, _calc1.Buffer, _calc1.Stride, _calc1.Size, 0, borderSize, 0)); //Fill calc2 to have borders ready after filtering IppHelper.IppCheckCall(ip.ippiSet_32f_C1R(0, _calc2.Buffer, _calc2.Stride, _calc2.Size)); //filter x-coordinates with our kernel IppHelper.IppCheckCall(ip.ippiFilter_32f_C1R(calc1XStart, _calc1.Stride, calc2XStart, _calc2.Stride, regionSize, _kernel, kernelSize, anchor)); //filter y-coordinates with our kernel IppHelper.IppCheckCall(ip.ippiFilter_32f_C1R(calc1YStart, _calc1.Stride, calc2YStart, _calc2.Stride, regionSize, _kernel, kernelSize, anchor)); //invert buffer - mirror on vertical axis IppHelper.IppCheckCall(ip.ippiMirror_32f_C1R(_calc2.Buffer, _calc2.Stride, _calc1.Buffer, _calc1.Stride, _calc2.Size, IppiAxis.ippAxsVertical)); //filter x-coordinates with our kernel - now on inverted buffer IppHelper.IppCheckCall(ip.ippiFilter_32f_C1R(calc1XStart, _calc1.Stride, calc2XStart, _calc2.Stride, regionSize, _kernel, kernelSize, anchor)); //filter y-coordinates with our kernel - now on inverted buffer IppHelper.IppCheckCall(ip.ippiFilter_32f_C1R(calc1YStart, _calc1.Stride, calc2YStart, _calc2.Stride, regionSize, _kernel, kernelSize, anchor)); //flip buffer back IppHelper.IppCheckCall(ip.ippiMirror_32f_C1R(_calc2.Buffer, _calc2.Stride, _calc1.Buffer, _calc1.Stride, _calc2.Size, IppiAxis.ippAxsVertical)); //copy to dest IppHelper.IppCheckCall(ip.ippiCopy_32f_C1R(calc1XStart, _calc1.Stride, dst.Buffer, dst.Stride, dst.Size)); }
public IppiROI(IppiPoint topleft, IppiSize roiSize) { _size = roiSize; _topleft = topleft; }
/// <summary> /// Creates a new tail tracker /// </summary> /// <param name="regionToTrack">The ROI in which we should track the tail</param> /// <param name="tailStart">The designated starting point of the tail</param> /// <param name="tailEnd">The designated end point of the tail</param> public TailTracker(IppiSize imageSize, IppiPoint tailStart, IppiPoint tailEnd) : this(imageSize, tailStart, tailEnd, 5) { }
public IppiROI(int x, int y, int width, int height) { _size = new IppiSize(width, height); _topleft = new IppiPoint(x, y); }