/// <summary> /// Processes the <paramref name="inputImage"/>. /// </summary> /// <param name="inputImage">Image to process.</param> /// <returns>Processed image.</returns> public override Image Process(Image inputImage) { if (inputImage == null) { throw new ArgumentNullException(nameof(inputImage)); } int[] factors = MakeBinominalFactors(KernelSize.GetKernelNumber()); int[] weights = MakeWeights(factors); var bounds = this.GetProcessingBounds(inputImage); int weightSum = weights.Sum(); if (ProcessAllPlanes) { foreach (var plane in inputImage.Planes) { ProcessPlane(plane, weights, bounds, weightSum); } } else { ProcessPlane(inputImage.Planes[PlaneIndex], weights, bounds, weightSum); } return(inputImage); }
/// <summary> /// Calculate a laplace kernel for the given <paramref name="kernelSize"/>. /// </summary> /// <param name="kernelSize">Kernel size to calculate laplace kernel for.</param> /// <returns>Calculated laplace kernel.</returns> private static int[] CalculateKernel(KernelSize kernelSize) { int kernelNum = kernelSize.GetKernelNumber(); int fullKernelNum = kernelNum * kernelNum; var kernel = new int[fullKernelNum]; for (int i = 0; i < kernel.Length; i++) { kernel[i] = 1; } kernel[(int)System.Math.Floor(fullKernelNum / 2.0)] = 1 - fullKernelNum; return(kernel); }
public static ImagePlane ProcessMonoKernel(ImagePlane plane, Func <byte?[], byte> processingFunc, KernelSize kernel, ProcessingBounds bounds) { if (plane.TryGetLinearAccess(out LinearAccessData data)) { var newImage = Image.FromPlanes(MappingOption.CopyPixels, plane); var newData = newImage.Planes[0].GetLinearAccess(); var yInc = (int)data.YInc; var xInc = (int)data.XInc; var newYInc = (int)newData.YInc; var newXInc = (int)newData.XInc; int boundHeight = plane.Parent.Height - 1; int boundWidth = plane.Parent.Width - 1; int startY = bounds.StartY; int startX = bounds.StartX; int boundsY = startY + bounds.Height; int boundsX = startX + bounds.Width; int kernelSize = kernel.GetKernelNumber(); int kernelArrSize = kernelSize * kernelSize; var kernelFac = (int)System.Math.Floor(kernelSize / 2.0); unsafe { var pBase = (byte *)data.BasePtr; var pBaseNew = (byte *)newData.BasePtr; Parallel.For(startY, boundsY, (y) => { var kernelValues = new byte?[kernelArrSize]; var pLine = pBase + y * yInc; int newLineInc = newYInc * y; for (int x = startX; x < boundsX; x++) { int kernelCounter = -1; var pMiddle = pLine + xInc * x; for (int kRow = -kernelFac; kRow <= kernelFac; kRow++) { byte *pKLine = pMiddle + kRow * yInc; int yKRow = y + kRow; for (int kColumn = -kernelFac; kColumn <= kernelFac; kColumn++) { kernelCounter++; int xKColumn = x + kColumn; if (yKRow < 0 || yKRow > boundHeight || xKColumn < 0 || xKColumn > boundWidth) { continue; } byte *pPixel = pKLine + kColumn * xInc; kernelValues[kernelCounter] = *pPixel; } } if (kernelValues.Any(b => b.HasValue)) { var pTargetLine = pBaseNew + newLineInc; var pTargetPixel = pTargetLine + newXInc * x; // current "middle pixel" in the target image *pTargetPixel = processingFunc.Invoke(kernelValues); } } }); } return(newImage.Planes[0]); } else { throw new ArgumentException("Plane could not be accessed linear", nameof(plane)); } }