Example #1
0
        private static Image <Complex, TDepth> prepareImage <TDepth>(Image <Gray, TDepth> image, int biggestKernelWidth, int biggestKernelHeight,
                                                                     ConvolutionBorder options,
                                                                     out int fillX, out int fillY)
            where TDepth : struct
        {
            int FFTNumOfCols = (int)System.Math.Pow(2.0, System.Math.Ceiling(System.Math.Log(biggestKernelWidth + image.Width, 2.0)));
            int FFTNumOfRows = (int)System.Math.Pow(2.0, System.Math.Ceiling(System.Math.Log(biggestKernelHeight + image.Height, 2.0)));

            fillX = System.Math.Min(image.Width, biggestKernelWidth / 2);
            fillY = System.Math.Min(image.Height, biggestKernelHeight / 2);

            Rectangle            centerRegion = new Rectangle(fillX, fillY, image.Width, image.Height);
            Image <Gray, TDepth> paddedImage  = new Image <Gray, TDepth>(FFTNumOfCols, FFTNumOfRows);

            //center
            paddedImage.GetSubRect(centerRegion).SetValue(image);

            if (options == ConvolutionBorder.BorderMirror)
            {
                ParallelConvolution.MirrorBorders(image, paddedImage, fillX, fillY);
            }

            Image <Complex, TDepth> paddedImageCmplx = new Image <Complex, TDepth>(new Image <Gray, TDepth>[] { paddedImage, paddedImage.CopyBlank() });

            paddedImageCmplx.FFT(FourierTransform.Direction.Forward, true);
            return(paddedImageCmplx);
        }
        private static ComplexF[,] prepareImage(Gray <float>[,] image, int biggestKernelWidth, int biggestKernelHeight,
                                                ConvolutionBorder options,
                                                out int fillX, out int fillY)
        {
            int FFTNumOfCols = (int)System.Math.Pow(2.0, System.Math.Ceiling(System.Math.Log(biggestKernelWidth + image.Width(), 2.0)));
            int FFTNumOfRows = (int)System.Math.Pow(2.0, System.Math.Ceiling(System.Math.Log(biggestKernelHeight + image.Height(), 2.0)));

            fillX = System.Math.Min(image.Width(), biggestKernelWidth / 2);
            fillY = System.Math.Min(image.Height(), biggestKernelHeight / 2);

            var paddedImage = new Gray <float> [FFTNumOfRows, FFTNumOfCols];

            //center
            image.CopyTo(paddedImage, new Point(fillX, fillY));

            if (options == ConvolutionBorder.BorderMirror)
            {
                mirrorBorders(image, paddedImage, fillX, fillY);
            }

            var paddedImageCmplx = paddedImage.ToComplex();

            paddedImageCmplx.FFT(FourierTransform.Direction.Forward, true);
            return(paddedImageCmplx);
        }
Example #3
0
        internal static IImage Convolve(IImage src, IImage[] kernels, ConvolutionBorder options)
        {
            IImage dest = src;

            foreach (var kernel in kernels)
            {
                dest = Convolve(dest, kernel, options);
            }

            return(dest);
        }
Example #4
0
        private static IImage prepareSourceImage(IImage src, Size kernelSize, ConvolutionBorder options, out Rectangle validRegion)
        {
            var       preparedSrc  = Image.Create(src.ColorInfo, src.Width + kernelSize.Width, src.Height + kernelSize.Height);
            Rectangle centerRegion = new Rectangle(kernelSize.Width / 2, kernelSize.Height / 2, src.Width, src.Height);

            preparedSrc.GetSubRect(centerRegion).SetValue(src);

            if (options == ConvolutionBorder.BorderMirror)
            {
                ParallelConvolution.MirrorBorders(src, preparedSrc, centerRegion.X, centerRegion.Y);
            }

            validRegion = centerRegion;
            return(preparedSrc);
        }
Example #5
0
        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));
        }
Example #6
0
 /// <summary>
 /// Convolves the image with the provided kernels.
 /// </summary>
 /// <typeparam name="TColor">Color type.</typeparam>
 /// <param name="src">Source image.</param>
 /// <param name="kernels">Kernels to convolve with.</param>
 /// <param name="options">Border pixels resolvent options.</param>
 /// <returns>Convolved image.</returns>
 public static Image <TColor, float> Convolve <TColor>(Image <TColor, float> src, Image <Gray, float>[] kernels, ConvolutionBorder options)
     where TColor : IColor
 {
     return(Convolve((IImage)src, kernels, options) as Image <TColor, float>);
 }
Example #7
0
 /// <summary>
 /// Convolves the image with the specified kernels.
 /// </summary>
 /// <typeparam name="TColor">Image color type.</typeparam>
 /// <param name="image">Image.</param>
 /// <param name="kernels">Kernels to convolve with.</param>
 /// <param name="options">Options for resolving border pixels.</param>
 /// <returns>Convolved image.</returns>
 public static Image <TColor, double> Convolve <TColor>(Image <TColor, double> image, Image <Gray, double>[] kernels, ConvolutionBorder options)
     where TColor : IColor
 {
     return(Convolve <TColor, double>(image, kernels, options));
 }
Example #8
0
        /// <summary>
        /// Convolves the image with the specified kernels.
        /// </summary>
        /// <typeparam name="TColor">Image color type.</typeparam>
        /// <param name="image">Image.</param>
        /// <param name="kernelArrs">Kernels to convolve with.</param>
        /// <param name="options">Options for resolving border pixels.</param>
        /// <returns>Convolved image.</returns>
        public static Image <TColor, double> Convolve <TColor>(Image <TColor, double> image, double[][,] kernelArrs, ConvolutionBorder options)
            where TColor : IColor
        {
            var kernels = kernelArrs.Select(x => x.AsImage()).ToArray();

            return(Convolve <TColor, double>(image, kernels, options));
        }
Example #9
0
        private static IEnumerable <Image <Gray, TDepth> > ConvolveSeparated <TDepth>(Image <Gray, TDepth> image, Image <Gray, TDepth>[] kernels, ConvolutionBorder options)
            where TDepth : struct /*float and double */
        {
            int biggestKernelWidth, biggestKernelHeight;

            ParallelConvolution.GetTheBiggestSize(kernels, out biggestKernelWidth, out biggestKernelHeight);

            int fillX, fillY;
            var paddedIm = prepareImage(image, biggestKernelWidth, biggestKernelHeight, options, out fillX, out fillY);

            foreach (var kernel in kernels)
            {
                var preparedKernel = prepareKernel(kernel, paddedIm.Size);
                var convolvedIm    = paddedIm.Mul(preparedKernel, null);
                yield return(getConvolutionResult(convolvedIm, fillX, fillY, image.Size, true));
            }
        }
Example #10
0
        private static Image <Gray, TDepth> convolve <TDepth>(Image <Gray, TDepth> image, Image <Gray, TDepth>[] kernels, ConvolutionBorder options)
            where TDepth : struct
        {
            int biggestKernelWidth, biggestKernelHeight;

            ParallelConvolution.GetTheBiggestSize(kernels, out biggestKernelWidth, out biggestKernelHeight);

            int fillX, fillY;
            var paddedIm = prepareImage(image, biggestKernelWidth, biggestKernelHeight, options, out fillX, out fillY);

            Image <Complex, TDepth> convolvedIm = paddedIm;

            foreach (var kernel in kernels)
            {
                var preparedKernel = prepareKernel(kernel, convolvedIm.Size);
                convolvedIm = convolvedIm.Mul(preparedKernel, null);
            }

            return(getConvolutionResult(convolvedIm, fillX, fillY, image.Size, true));
        }
Example #11
0
        /// <summary>
        /// Convolves the image with the specified kernels.
        /// </summary>
        /// <typeparam name="TColor">Image color type.</typeparam>
        /// <typeparam name="TDepth">Channel type.</typeparam>
        /// <param name="image">Image.</param>
        /// <param name="kernels">Kernels to convolve with.</param>
        /// <param name="options">Options for resolving border pixels.</param>
        /// <returns>Convolved image.</returns>
        internal static Image <TColor, TDepth> Convolve <TColor, TDepth>(Image <TColor, TDepth> image, Image <Gray, TDepth>[] kernels, ConvolutionBorder options)
            where TColor : IColor
            where TDepth : struct
        {
            if (typeof(TColor).Equals(typeof(Gray)) == true) //saving time on channel splitting and creating an image from channels (can function without this)
            {
                return(convolve <TDepth>(image as Image <Gray, TDepth>, kernels, options) as Image <TColor, TDepth>);
            }

            var channels          = image.SplitChannels();
            var convolvedChannels = new List <Image <Gray, TDepth> >();

            foreach (var ch in channels)
            {
                var convolvedCh = convolve(ch as Image <Gray, TDepth>, kernels, options);
                convolvedChannels.Add(convolvedCh);
            }

            return(new Image <TColor, TDepth>(convolvedChannels.ToArray()));
        }
        private static Image <TColor, TDepth> Convolve <TColor, TDepth, TKernel>(Image <TColor, TDepth> src, TKernel[][,] kernelArrs, ConvolutionBorder options, bool forceSpatialConvolution = false)
            where TColor : IColor
            where TDepth : struct
            where TKernel : struct
        {
            var kernels = kernelArrs.Select(x => x.AsImage()).ToArray();

            return(Convolve <TColor, TDepth, TKernel>(src, kernels, options, forceSpatialConvolution));
        }
 /// <summary>
 /// Convolves an image with kernels.
 /// Convolution type (FFT or spatial) is automatically selected based on kernels size.
 /// </summary>
 /// <param name="src">Input image.</param>
 /// <param name="kernels">Kernels</param>
 /// <param name="options">Border options</param>
 /// <param name="forceSpatialConvolution">Use spatial convolution even if FFT should be used.</param>
 /// <returns>Convolved image</returns>
 public static Image <TColor, TDepth> Convolve <TColor, TDepth>(this Image <TColor, TDepth> src, float[][,] kernels, ConvolutionBorder options, bool forceSpatialConvolution = false)
     where TColor : IColor
     where TDepth : struct
 {
     return(Convolve <TColor, TDepth, float>(src, kernels, options, forceSpatialConvolution));
 }
        internal static Image <TColor, TDepth> Convolve <TColor, TDepth, TKernel>(this Image <TColor, TDepth> src, Image <Gray, TKernel>[] kernels, ConvolutionBorder options, bool forceSpatialConvolution = false)
            where TColor : IColor
            where TDepth : struct
            where TKernel : struct
        {
            bool useFFT = ShouldUseFFT(kernels) && !forceSpatialConvolution;

            Type[] supportedTypes = null;
            if (useFFT)
            {
                supportedTypes = ParallelFFTConvolution.SupportedTypes;
            }
            else
            {
                supportedTypes = ParallelSpatialConvolution.SupportedTypes;
            }

            supportedTypes = supportedTypes.Where(x => x.Equals(typeof(TKernel))).ToArray();
            if (supportedTypes.Length == 0)
            {
                throw new NotSupportedException(string.Format("Kernel of type {0} is not supported. Used convolution: {1}. Supported types for used convolution: {2}." +
                                                              "Please use different kernel type, or force convolution method.",
                                                              typeof(TKernel).Name,
                                                              (useFFT) ? "FFT" : "Spatial",
                                                              supportedTypes.Select(x => x.Name)));
            }

            /************************************** convert src ********************************/
            var    supportedColors = supportedTypes.Select(x => ColorInfo.GetInfo(typeof(TColor), x)).ToArray();
            var    conversionPath  = ColorConverter.GetPath(src.ColorInfo, supportedColors);
            IImage convertedSrc    = ColorConverter.Convert(src, conversionPath.ToArray(), false);

            if (convertedSrc == null)
            {
                throw new Exception(string.Format("Convolution does not support images of type {0}", src.ColorInfo.ChannelType));
            }
            /************************************** convert src ********************************/

            IImage dest = null;

            if (useFFT)
            {
                dest = ParallelFFTConvolution.Convolve <TColor, TKernel>(convertedSrc as Image <TColor, TKernel>, kernels, options);
            }
            else
            {
                dest = ParallelSpatialConvolution.Convolve(convertedSrc, kernels, options);
            }


            /************************************** convert back ********************************/
            var    backwardConversion = ColorConverter.GetPath(dest.ColorInfo, src.ColorInfo);
            IImage convertedDest      = ColorConverter.Convert(dest, backwardConversion.ToArray(), false);

            if (convertedDest == null)
            {
                throw new Exception(string.Format("Convolution does not support images of type {0}", src.ColorInfo.ChannelType));
            }
            /************************************** convert back ********************************/

            return(convertedDest as Image <TColor, TDepth>);
        }
        /// <summary>
        /// Convolves the image with the specified kernels.
        /// </summary>
        /// <typeparam name="TColor">Image color type.</typeparam>
        /// <param name="image">Image.</param>
        /// <param name="kernels">Kernels.</param>
        /// <param name="options">Options for resolving border pixels.</param>
        /// <returns>Convolved image.</returns>
        public static TColor[,] ConvolveFFT <TColor>(this TColor[,] image, IList <float[, ]> kernels, ConvolutionBorder options)
        where TColor : struct, IColor <float>
        {
            var channels          = image.SplitChannels <TColor, float>();
            var convolvedChannels = new List <Gray <float> [, ]>();

            foreach (var channel in channels)
            {
                var convolvedChannel = convolve(channel, kernels, options);
                convolvedChannels.Add(convolvedChannel);
            }

            var destination = convolvedChannels.MergeChannels <TColor, float>();

            return(destination);
        }
        private static Gray <float>[,] convolve(Gray <float>[,] image, IList <float[, ]> kernels, ConvolutionBorder options)
        {
            int biggestKernelWidth, biggestKernelHeight;

            getTheBiggestSize(kernels, out biggestKernelWidth, out biggestKernelHeight);

            int fillX, fillY;
            var paddedIm = prepareImage(image, biggestKernelWidth, biggestKernelHeight, options, out fillX, out fillY);

            var convolvedIm = paddedIm;

            foreach (var kernel in kernels)
            {
                var preparedKernel = prepareKernel(kernel, convolvedIm.Size());
                convolvedIm = convolvedIm.MulComplex(preparedKernel, inPlace: false);
            }

            return(getConvolutionResult(convolvedIm, fillX, fillY, image.Size()));
        }