/// <summary> /// Produces an image in the ring buffer /// </summary> /// <param name="image">The image to write into the buffer</param> public void Produce(Image8 image) { if (_isDisposed) { throw new ObjectDisposedException("PrCoImageRingBuffer"); } if (image == null) { return; } if (image.Width != _imageWidth || image.Height != _imageHeight) { throw new ArgumentException("The produced image is not compatible with the buffer"); } lock (_accessLock) { //advance our production buffer "pointer" to the next place in the ring buffer _lastProduce = (_lastProduce + 1) % _nImages; //increment _imageIndex internally var temp = _imageIndex + 1; //copy image over ip.ippiCopy_8u_C1R(image.Image, image.Stride, _buffers[_lastProduce], _imageStride, new IppiSize(_imageWidth, _imageHeight)); //update the indices in the production place with the current image index _imageIndices[_lastProduce] = temp; //Image has been produced, update index and storage counter _imageIndex = temp; _storageCount++; //Signal waiting threads that we are about to release the lock Monitor.Pulse(_accessLock); } }
public void WriteFrame(Image8 frame) { //if this is the first frame of the current file //we have to create the file if (_firstFrame) { System.Diagnostics.Debug.Assert(_tiffFile == null, "Tried first write but tiffile not null"); _pageIndex = 0; _tiffFile = Tiff.Open(CurrentFileNameWithExtension, "w"); //write first page WritePage(frame); //increment page index _pageIndex++; _firstFrame = false; } else { //TiffStream stream = _tiffFile.GetStream(); if (new FileInfo(CurrentFileNameWithExtension).Length > 1900000000)//limit file size for MATLABs sake { _fileIndex++; _firstFrame = true; _tiffFile.Dispose(); _tiffFile = null; WriteFrame(frame); return; }//if file size maxed out //write next page WritePage(frame); //increment page index _pageIndex++; } }
protected virtual void Dispose(bool disposing) { if (_bgModel != null) { _bgModel.Dispose(); _bgModel = null; } if (_calc != null) { _calc.Dispose(); _calc = null; } if (_foreground != null) { _foreground.Dispose(); _foreground = null; } if (_markerBuffer != null) { Marshal.FreeHGlobal((IntPtr)_markerBuffer); _markerBuffer = null; } if (_momentState != null) { ip.ippiMomentFree_64s(_momentState); _momentState = null; } }
protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { if (_trackWriter != null) { _trackWriter.Dispose(); _trackWriter = null; } if (_imageWriter != null) { _imageWriter.Dispose(); _imageWriter = null; } if (_backgroundWriter != null) { _backgroundWriter.Dispose(); _backgroundWriter = null; } if (_laser != null) { _laser.Dispose(); } if (_scanner != null) { _scanner.Dispose(); } if (_camRegion != null) { _camRegion.Dispose(); _camRegion = null; } } }
public Replay(Queue <string> originalTrackData, Queue <string> originalInfoData, OriginalType originalType, int originalLength, int frameRate, int pxPERmm, string folder, string name, string fishID) : base(folder, name, fishID, originalLength, frameRate, pxPERmm) { if (FileSaver != null) { _trackWriter = FileSaver.GetStreamWriter(".track"); _imageWriter = FileSaver.GetTiffWriter("_camImage.tif", true); _backgroundWriter = FileSaver.GetTiffWriter("_bgImage.tif", true); //Create 10x10 mm region image _camRegion = new Image8(Properties.Settings.Default.PixelsPermm * 10, Properties.Settings.Default.PixelsPermm * 10); } _laser = new SDLPS500Controller(Properties.Settings.Default.DAQ, Properties.Settings.Default.LaserAO); string xchannel = Properties.Settings.Default.DAQ + "/" + Properties.Settings.Default.ScannerX; string ychannel = Properties.Settings.Default.DAQ + "/" + Properties.Settings.Default.ScannerY; //Load scan lookup table from file try { TextReader reader = File.OpenText("main.calib"); var scanTable = BLIScanLookupTable.LoadFromFile(reader); _scanner = new RandomAccessScanner(scanTable, xchannel, ychannel, -10, 10); reader.Dispose(); } catch (IOException) { System.Diagnostics.Debug.WriteLine("Could not find calibration data. No targeting available"); } //This is a closed-loop experiment - try to stay fully up-to-date SuggestedBufferSeconds = 0; _originalType = originalType; _originalTrackData = originalTrackData; _originalInfoData = originalInfoData; _experimentPhase = ExperimentPhase.Replay; }
/// <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> /// Extract blobs from an image in which distinct contiguous regions are marked /// with distinct pixel values such as returned by ippiLabelMarkers /// </summary> /// <param name="imMarkers">The marker image</param> /// <param name="nMarkers">The number of expected markers</param> /// <param name="imOriginal">The original image. Used for pixel-intensity information</param> /// <param name="roi">The roi in which to perform blob extraction</param> /// <returns>An array of discovered blobs</returns> public static BlobWithMoments[] ExtractBlobs(Image8 imMarkers, int nMarkers, IppiROI roi) { if (nMarkers == 0)//no point to iterate over the image if no marker was found { return(null); } BlobWithMoments[] blobs = new BlobWithMoments[nMarkers]; byte markerValue; //loop over ROI in marker image, adding pixels to their appropriate blob for (int i = roi.Y; i < roi.Y + roi.Height; i++) { for (int j = roi.X; j < roi.X + roi.Width; j++) { markerValue = imMarkers.Image[i * imMarkers.Stride + j]; if (markerValue != 0) //it belongs to a blob! { //since the lowest marker has the value 1 we need to deduct 1 from markerValue for 0-index based array mapping! if (blobs[markerValue - 1] == null) { blobs[markerValue - 1] = new BlobWithMoments(); } blobs[markerValue - 1].AddPixel(j, i); } } } return(blobs); }
///// <summary> ///// Computes the augmented rotation matrix for an augmented 2D point around the origin ///// </summary> ///// <param name="theta">The clockwise rotation angle in radians</param> ///// <returns>The augmented (3x3) 2D rotation matrix</returns> //public static Matrix<double> RotationMatrix(double theta) //{ // return DenseMatrix.OfArray(new double[,] // { // {Math.Cos(theta), Math.Sin(theta), 0 }, // {-1*Math.Sin(theta), Math.Cos(theta), 0 }, // {0, 0, 1 } // }); //} ///// <summary> ///// Computes the augmented translation matrix for an augmented 2D point ///// </summary> ///// <param name="dx">Translation amount in x direction</param> ///// <param name="dy">Translation amount in y direction</param> ///// <returns>The augmented (3x3) 2D translation matrix</returns> //public static Matrix<double> TranslationMatrix(double dx, double dy) //{ // return DenseMatrix.OfArray(new double[,] // { // {1, 0, dx }, // {0, 1, dy }, // {0, 0, 1 } // }); //} ///// <summary> ///// Augments a 2D coordinate point ///// </summary> ///// <param name="px">The x-coordinate</param> ///// <param name="py">The y-coordinate</param> ///// <returns>A 3 element vector comprising the point</returns> //public static Vector<double> Augment2DCoordinate(double px, double py) //{ // return DenseVector.OfArray(new double[] { px, py, 1 }); //} ///// <summary> ///// Composes (multiplies) a list of transformation matrices in order ///// NOTE: List should be ordered in order of application which needs to be reversed for the composition! ///// </summary> ///// <param name="matrices">List of transformations to compose</param> ///// <returns>The composed matrix</returns> //public static Matrix<double> Compose(List<Matrix<double>> matrices) //{ // Matrix<double> m = DenseMatrix.CreateIdentity(3); // for(int i = matrices.Count-1; i>=0; i--) // m *= matrices[i]; // return m; //} ///// <summary> ///// Applies transformation to given point ///// </summary> ///// <param name="p"></param> ///// <param name="T"></param> ///// <returns></returns> //public static IppiPoint TransformPoint(IppiPoint p, Matrix<double> T) //{ // Vector<double> result = Augment2DCoordinate(p.x, p.y) * T; // return new IppiPoint((int)result[0], (int)result[1]); //} ///// <summary> ///// Applies transformation to given point ///// </summary> ///// <param name="p"></param> ///// <param name="T"></param> ///// <returns></returns> //public static IppiPoint_32f TransformPoint(IppiPoint_32f p, Matrix<double> T) //{ // Vector<double> result = T * Augment2DCoordinate(p.x, p.y); // return new IppiPoint_32f((float)result[0], (float)result[1]); //} /// <summary> /// Method for creating image background /// </summary> /// <param name="frameNumber">The current camera frame number</param> /// <param name="camImage">The camera image</param> /// <param name="poi">A detected centroid (all null)</param> protected void BuildBackground(int frameNumber, Image8 camImage, out IppiPoint?poi) { _laser.LaserPower = 0; poi = null; if (frameNumber == 0 || _bgModel == null) { _bgModel = new DynamicBackgroundModel(camImage, 1.0f / Properties.Settings.Default.FrameRate); _fgModel = new DynamicBackgroundModel(camImage, 5.0f / Properties.Settings.Default.FrameRate); //Create image intermediates _calc = new Image8(camImage.Size); _foreground = new Image8(camImage.Size); _strel3x3 = Morphology.Generate3x3Mask(camImage.Size); //Initialize buffer for label markers int bufferSize = 0; cv.ippiLabelMarkersGetBufferSize_8u_C1R(camImage.Size, &bufferSize); if (_markerBuffer != null) { Marshal.FreeHGlobal((IntPtr)_markerBuffer); _markerBuffer = null; } _markerBuffer = (byte *)Marshal.AllocHGlobal(bufferSize); } else { _bgModel.UpdateBackground(camImage); } if (frameNumber >= Properties.Settings.Default.FrameRate * 5) { _experimentPhase = ExperimentPhases.ThreePoint; _threePointFrame = 0; _threePointPoints = new CalibrationPoints(); } }
public Tracker90mmDish(int imageWidth, int imageHeight, IppiPoint dishCenter) { _foreground = new Image8(imageWidth, imageHeight); _bgSubtracted = new Image8(imageWidth, imageHeight); _calc = new Image8(imageWidth, imageHeight); _dishCenter = dishCenter; int bufferSize = 0; IppHelper.IppCheckCall(cv.ippiLabelMarkersGetBufferSize_8u_C1R(new IppiSize(imageWidth, imageHeight), &bufferSize)); _markerBuffer = (byte *)Marshal.AllocHGlobal(bufferSize); int momentSize = 0; IppHelper.IppCheckCall(ip.ippiMomentGetStateSize_64f(IppHintAlgorithm.ippAlgHintNone, &momentSize)); _momentState = (IppiMomentState_64f *)Marshal.AllocHGlobal(momentSize); //let ipp decide whether to give accurate or fast results IppHelper.IppCheckCall(ip.ippiMomentInit_64f(_momentState, IppHintAlgorithm.ippAlgHintNone)); _frame = 0; //populate tracking parameters with default values _threshold = 6; _minArea = 11; _maxAllowedArea = 120; _minEccentricity = 0.3; _fullTrustMinArea = 20; _imageROI = new IppiROI(0, 0, imageWidth, imageHeight); _searchRegionSize = 90; _removeCMOSISBrightLineArtefact = false; _strel3x3 = Morphology.Generate3x3Mask(_foreground.Size); //The following calculation for FramesInBackground means that after ~30s of movie //a stationary object will have dissappeared into the background (at 63% level) FramesInBackground = (int)((30 * 250)); FramesInitialBackground = 2 * 30 * 250; BGUpdateEvery = 2; }
/// <summary> /// Extracts an 8-bit image reducing bit depth if necessary /// </summary> /// <param name="imageOut">The container to recieve the image</param> /// <param name="requestedFrame">The framenumber to request</param> /// <returns>The frame number actually retrieved from the buffer</returns> public uint Extract(Image8 imageOut, uint requestedFrame) { uint frameActual, indexActual; if (_bytesPerPixel == 2) { //this requires acquisition into our internal buffer first //followed by handing out a downsized copy frameActual = Extract(_imgDownsize, requestedFrame); //if our bit-depth is not 16 we have a problem - we need //to scale our image first to really fill the 16bits otherwise we run into //problems later... if (_bitsPerPixel < 16) { ip.ippiMulC_16u_C1IRSfs(_scaleFactor, _imgDownsize.Image, _imgDownsize.Stride, _imgDownsize.Size, 0); } //we got handed 8 bits _imgDownsize.ReduceTo8U(imageOut); } else { NIImaq.CheckError(NIImaq.imgSessionCopyBufferByNumber(_sid, requestedFrame, (IntPtr)imageOut.Image, IMG_OVERWRITE_MODE.IMG_OVERWRITE_GET_NEWEST, out frameActual, out indexActual)); if (frameActual != requestedFrame) { System.Diagnostics.Debug.WriteLine("Requested frame {0}; obtained frame {1}", requestedFrame, frameActual); } } _acquiredFrames++; return(frameActual); }
protected void Dispose(bool IsDisposing) { if (_background != null) { _background.Dispose(); _background = null; } if (_foreground != null) { _foreground.Dispose(); _foreground = null; } if (_thresholded != null) { _thresholded.Dispose(); _thresholded = null; } if (_calc1 != null) { _calc1.Dispose(); _calc1 = null; } if (_strel != null) { _strel.Dispose(); _strel = null; } if (_angleStore != null) { System.Runtime.InteropServices.Marshal.FreeHGlobal((IntPtr)_angleStore); _angleStore = null; } }
public Tracker90mmDish(int imageWidth, int imageHeight) { _foreground = new Image8(imageWidth, imageHeight); _calc = new Image8(imageWidth, imageHeight); _labelMarkers = new Image8(imageWidth, imageHeight); int bufferSize = 0; IppHelper.IppCheckCall(cv.ippiLabelMarkersGetBufferSize_8u_C1R(new IppiSize(imageWidth, imageHeight), &bufferSize)); _markerBuffer = (byte *)Marshal.AllocHGlobal(bufferSize); fixed(IppiMomentState_64s **ppState = &_momentState) { //let ipp decide whether to give accurate or fast results IppHelper.IppCheckCall(ip.ippiMomentInitAlloc_64s(ppState, IppHintAlgorithm.ippAlgHintNone)); } _frame = 0; //populate tracking parameters with default values _threshold = 5; _minArea = 10; _maxArea = 300; _fullTrustMinArea = 20; _imageROI = new IppiROI(0, 0, imageWidth, imageHeight); //The following calculation for FramesInBackground means that after ~30s of movie //a stationary object will have dissappeared into the background (at 63% level) FramesInBackground = (int)((30 * 240)); FramesInitialBackground = 2 * FramesInBackground; }
public Image8 copy() { global::System.IntPtr cPtr = libPhotoAssistantImageProcessingPINVOKE.Image8_copy(swigCPtr); Image8 ret = (cPtr == global::System.IntPtr.Zero) ? null : new Image8(cPtr, false); return(ret); }
/// <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)); }
/// <summary> /// Initializes a new tracker instance /// </summary> /// <param name="imageWidth">The width of the images to track</param> /// <param name="imageHeight">The height of the images to track</param> public Tracker(int imageWidth, int imageHeight) { _currentImage = new Image8(imageWidth, imageHeight); _trackThread = new Worker(TrackThreadRun, false, 500); _frames = new PrCoImageRingBuffer(imageWidth, imageHeight, 100); _imageIndex = 0; }
/// <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)); } }
/// <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)); }
/// <summary> /// Constructor /// </summary> /// <param name="im">The initial background image</param> /// <param name="fUpdate">The fraction of the current image to use for updating the background</param> public DynamicBackgroundModel(Image8 im, float fUpdate) : base(im) { if (0 > fUpdate || 1 < fUpdate) { throw new ArgumentOutOfRangeException("fUpdate", "The update fraction has to be bigger than 0 and smaller than 1"); } FractionUpdate = fUpdate; }
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)); }
/// <summary> /// Disposes the mask image /// </summary> public void Dispose() { if (_mask != null) { _mask.Dispose(); _mask = null; } }
/// <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)); }
/// <summary> /// Uses multiplication to draw a mask onto an image /// </summary> /// <param name="maskImage">The mask image to draw</param> /// <param name="image">The camera image to draw the mask on</param> public static void DrawMask(Image8 maskImage, Image8 image) { if (maskImage.Size.width != image.Size.width || maskImage.Size.height != image.Size.height) { throw new ArgumentException("Both images need to have the same dimensions"); } ip.ippiMul_8u_C1IRSfs(maskImage.Image, maskImage.Stride, image.Image, image.Stride, image.Size, 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)); }
public void Dispose() { if (_mask != null) { _mask.Dispose(); _mask = null; } IsDisposed = true; }
/// <summary> /// Process the next frame /// </summary> /// <param name="frameNumber">The frame index</param> /// <param name="camImage">The camera image</param> /// <param name="poi">The fish location</param> /// <returns>Whether experiment should continue or not</returns> public override bool ProcessNext(int frameNumber, Image8 camImage, out IppiPoint?poi) { base.ProcessNext(frameNumber, camImage, out poi); if (_scanner == null) { System.Diagnostics.Debug.WriteLine("Scanner was not initialized. Terminating experiment"); return(false); } int writeEvery = Properties.Settings.Default.FrameRate * 4; if (frameNumber % writeEvery == writeEvery - 1) { _laser.LaserPower = Properties.Settings.Default.LaserCalibPowermW; } else { _laser.LaserPower = 0; } _lastFrame = frameNumber; if (frameNumber >= _totalFrames) { return(false); } BlobWithMoments fish = null; // Every 4s we turn on the laser - those frames won't be tracked but the image will be saved if (frameNumber % writeEvery != 0) { fish = Tracker.Track(camImage); } if (fish != null) { poi = new IppiPoint(fish.Centroid.x, fish.Centroid.y); if (_scanner != null) { _scanner.Hit(poi.GetValueOrDefault()); } } if (_trackWriter != null) { if (fish != null) { _trackWriter.WriteLine("{0}\t{1}\t{2}\t{3}", frameNumber, fish.Centroid.x, fish.Centroid.y, fish.Angle); } else { _trackWriter.WriteLine("NaN\tNaN\tNaN\tNaN"); } // Write image of Laser On frames and the two surrounding frames on each side to file if (frameNumber % writeEvery <= 2 || frameNumber % writeEvery >= writeEvery - 2) { _imageWriter.WriteFrame(camImage); } } return(true); }
/* * * /// <summary> * /// Extract the next image * /// </summary> * /// <returns></returns> * public Image8 Extract() { * var image = new Image8(width, height); * var bufferLength = (uint)(width * height); * uint frameIndex; * CheckError(IMAQdx.IMAQdxGetImageData(session, image.Image, bufferLength, IMAQdx.IMAQdxBufferNumberMode.IMAQdxBufferNumberModeNext, 0, out frameIndex)); * return image; * } * * /// <summary> * /// Extract the next image and return its index * /// </summary> * /// <param name="frameIndex"></param> * /// <returns></returns> * public Image8 Extract(out uint frameIndex) { * var image = new Image8(width, height); * var bufferLength = (uint)(width * height); * CheckError(IMAQdx.IMAQdxGetImageData(session, image.Image, bufferLength, IMAQdx.IMAQdxBufferNumberMode.IMAQdxBufferNumberModeNext, 0, out frameIndex)); * return image; * } * * /// <summary> * /// Extract the image with the specified index * /// </summary> * /// <param name="frameIndex"></param> * /// <returns></returns> * public Image8 Extract(uint frameIndex) { * var image = new Image8(width, height); * uint actualFrameIndex; * CheckError(IMAQdx.IMAQdxGetImageData(session, image.Image, bufferLength, IMAQdx.IMAQdxBufferNumberMode.IMAQdxBufferNumberModeBufferNumber, frameIndex, out actualFrameIndex)); * if (actualFrameIndex != frameIndex) * System.Diagnostics.Debug.WriteLine("Warning: Expected frameIndex " + frameIndex + ", got frameIndex " + actualFrameIndex); * return image; * } * * /// <summary> * /// Extract the next image into an existing Image8 * /// </summary> * /// <param name="imageToReuse"></param> * public void Extract(Image8 imageToReuse) { * if (imageToReuse.Width != width || imageToReuse.Height != height) * throw new Exception("Cannot reuse image, dimensions should be " + width + " x " + height + ", not " + imageToReuse.Width + " x " + imageToReuse.Height); * uint frameIndex; * CheckError(IMAQdx.IMAQdxGetImageData(session, imageToReuse.Image, bufferLength, IMAQdx.IMAQdxBufferNumberMode.IMAQdxBufferNumberModeNext, 0, out frameIndex)); * } * * /// <summary> * /// Extract the next image into an existing Image8 and return its index * /// </summary> * /// <param name="frameIndex"></param> * /// <returns></returns> * public void Extract(Image8 imageToReuse, out uint frameIndex) { * if (imageToReuse.Width != width || imageToReuse.Height != height) * throw new Exception("Cannot reuse image, dimensions should be " + width + " x " + height + ", not " + imageToReuse.Width + " x " + imageToReuse.Height); * CheckError(IMAQdx.IMAQdxGetImageData(session, imageToReuse.Image, bufferLength, IMAQdx.IMAQdxBufferNumberMode.IMAQdxBufferNumberModeNext, 0, out frameIndex)); * }*/ /// <summary> /// Extract the image with the specified index into an existing Image8 /// </summary> /// <param name="frameIndex"></param> /// <returns></returns> public void Extract(Image8 imageToReuse, uint frameIndex) { uint actualFrameIndex; CheckError(IMAQdx.IMAQdxGetImageData(session, imageToReuse.Image, bufferLength, IMAQdx.IMAQdxBufferNumberMode.IMAQdxBufferNumberModeBufferNumber, frameIndex, out actualFrameIndex)); if (actualFrameIndex != frameIndex) { System.Diagnostics.Debug.WriteLine("Warning: Expected frameIndex " + frameIndex + ", got frameIndex " + actualFrameIndex); } }
public override bool ProcessNext(int frameNumber, Image8 camImage, out IppiPoint?poi) { //create tracker if necessary if (Tracker == null) { Tracker = CreateFishTracker(camImage.Width, camImage.Height, new IppiPoint(camImage.Width / 2, camImage.Height / 2)); } poi = null; return(true); }
/// <summary> /// Initializes all internal buffers based on the /// size of the current tracking region /// </summary> protected virtual void InitializeImageBuffers() { //create images _background = new Image8(_imageSize); _foreground = new Image8(_imageSize); _thresholded = new Image8(_imageSize); _calc1 = new Image8(_imageSize); //blank foreground - to ensure that the border is always black! ip.ippiSet_8u_C1R(0, _foreground.Image, _foreground.Stride, _imageSize); }
public Graph(int width, int height) { Width = width; Height = height; //Initialize our color placeholder _color = (byte *)Marshal.AllocHGlobal(3).ToPointer(); //Initialize new canvas for the bgr pixels (hence width*3) _canvas = new Image8(width * 3, height); ClearImage(); }
//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)); }