/// <summary> /// Convolves the image patch with the provided kernel. /// </summary> /// <param name="src">Source image.</param> /// <param name="srcArea">Area of the image to convolve.</param> /// <param name="kernel">Kernel to convolve with.</param> /// <param name="dest">Destination image. It's size must be equal to the size of the specified area.</param> /// <param name="convolveBorders">True if the borders should be convolved, false otherwise.</param> public static void ConvolvePatch(IImage src, Rectangle srcArea, IImage kernel, IImage dest, bool convolveBorders = false) //TODO: revise whether it should be used or not. { ConvolutionFunc convolutionFunc = null; if (convolutionFuncs.TryGetValue(src.ColorInfo.ChannelType, out convolutionFunc) == false) { throw new NotSupportedException(string.Format("Can not perform spatial convolution on an image of type {0}", src.ColorInfo.ChannelType.Name)); } Rectangle srcWorkingArea = srcArea; if (!convolveBorders) { srcWorkingArea.Width -= kernel.Width; srcWorkingArea.Height -= kernel.Height; //srcWorkingArea.Inflate(-kernel.Width / 2, -kernel.Height / 2); } convolutionFunc(src, srcWorkingArea, dest, new Point(), kernel); }
internal static IImage Convolve(IImage src, IImage kernel, ConvolutionBorder options) { ConvolutionFunc convolutionFunc = null; if (convolutionFuncs.TryGetValue(src.ColorInfo.ChannelType, out convolutionFunc) == false) { throw new NotSupportedException(string.Format("Can not perform spatial convolution on an image of type {0}", src.ColorInfo.ChannelType.Name)); } Rectangle validRegion; var preparedSrc = prepareSourceImage(src, kernel.Size, options, out validRegion); var proc = new ParallelProcessor <IImage, IImage>(src.Size, () => preparedSrc.CopyBlank(), //in-place convolution is not supported due to parallel processing (junction patches handling) (_src, _dest, area) => { Rectangle srcArea = new Rectangle { X = 0, Y = area.Y, Width = _src.Width, Height = area.Height + kernel.Height //get area sufficient to process with the selected kernel; area.Height is processed }; //srcArea.Inflate(-kernel.Width , -kernel.Height ); srcArea.Width -= kernel.Width; srcArea.Height -= kernel.Height; srcArea.Intersect(new Rectangle(new Point(), _src.Size)); convolutionFunc(_src, srcArea, _dest, new Point(kernel.Width / 2, area.Y + kernel.Height / 2), kernel); } /*,new ParallelOptions2D { ForceSequential = true }*/); var dest = proc.Process(preparedSrc); return(dest.GetSubRect(validRegion)); }