Subtract filter - subtract pixel values of two images.

The subtract filter takes two images (source and overlay images) of the same size and pixel format and produces an image, where each pixel equals to the difference value of corresponding pixels from provided images (if difference is less than minimum allowed value, 0, then it is truncated to that minimum value).

The filter accepts 8 and 16 bpp grayscale images and 24, 32, 48 and 64 bpp color images for processing.

Sample usage:

// create filter Subtract filter = new Subtract( overlayImage ); // apply the filter Bitmap resultImage = filter.Apply( sourceImage );

Source image:

Overlay image:

Result image:

Inheritance: BaseInPlaceFilter2
        /// <summary>
        ///   Initializes a new instance of the <see cref="DifferenceOfGaussians"/> class.
        /// </summary>
        ///
        public DifferenceOfGaussians()
        {
            formatTranslations = new Dictionary <PixelFormat, PixelFormat>();
            formatTranslations[PixelFormat.Format8bppIndexed]    = PixelFormat.Format8bppIndexed;
            formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale;
            formatTranslations[PixelFormat.Format24bppRgb]       = PixelFormat.Format24bppRgb;
            formatTranslations[PixelFormat.Format32bppRgb]       = PixelFormat.Format32bppRgb;
            formatTranslations[PixelFormat.Format32bppArgb]      = PixelFormat.Format32bppArgb;
            formatTranslations[PixelFormat.Format48bppRgb]       = PixelFormat.Format48bppRgb;
            formatTranslations[PixelFormat.Format64bppArgb]      = PixelFormat.Format64bppArgb;

            this.first = new GaussianBlur()
            {
                Size  = 3,
                Sigma = 0.4
            };

            this.second = new GaussianBlur()
            {
                Size  = 5,
                Sigma = 0.4
            };

            this.subtract = new Subtract();
        }
Example #2
0
        private void SetFilter()
        {
            ImageType = ImageTypes.Rgb24bpp;
            Af.Subtract newFilter = new Af.Subtract();
            newFilter.OverlayImage = Overlay;

            imageFilter = newFilter;
        }
        /// <summary>
        ///   Initializes a new instance of the <see cref="DifferenceOfGaussians"/> class.
        /// </summary>
        /// 
        public DifferenceOfGaussians()
        {
            formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
            formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed;
            formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale;
            formatTranslations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb;
            formatTranslations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb;
            formatTranslations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb;
            formatTranslations[PixelFormat.Format48bppRgb] = PixelFormat.Format48bppRgb;
            formatTranslations[PixelFormat.Format64bppArgb] = PixelFormat.Format64bppArgb;

            this.first = new GaussianBlur()
            {
                Size = 3,
                Sigma = 0.4
            };

            this.second = new GaussianBlur()
            {
                Size = 5,
                Sigma = 0.4
            };

            this.subtract = new Subtract();
        }
Example #4
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        /// <param name="overlay">Overlay image data.</param>
        ///
        protected override void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
        {
            BaseResizeFilter resizer = new ResizeNearestNeighbor(
                (int)(image.Width * _subSamplingRatio),
                (int)(image.Height * _subSamplingRatio));

            UnmanagedImage imageSub = resizer.Apply(image);
            UnmanagedImage overlaySub = resizer.Apply(overlay);
            byte kernelSizeSub = (byte)(_kernelSize * _subSamplingRatio);

            UnmanagedImage imageBorder = new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(
                GetFilledImage(imageSub.Width, imageSub.Height, imageSub.PixelFormat, Color.White));

            UnmanagedImage imageMean = new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(imageSub);
            new Divide(imageBorder).ApplyInPlace(imageMean);

            UnmanagedImage overlayMean = new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(overlaySub);
            new Divide(imageBorder).ApplyInPlace(overlayMean);

            UnmanagedImage mulMean = new Multiply(overlaySub).Apply(imageSub);
            overlaySub.Dispose();
            new FastBoxBlur(kernelSizeSub, kernelSizeSub).ApplyInPlace(mulMean);
            new Divide(imageBorder).ApplyInPlace(mulMean);

            //This is the covariance of (image, overlay) in each local patch.
            UnmanagedImage mulCov = new Subtract(new Multiply(overlayMean).Apply(imageMean)).Apply(mulMean);
            mulMean.Dispose();

            UnmanagedImage imageMean2 = new Multiply(imageSub).Apply(imageSub);
            imageSub.Dispose();
            new FastBoxBlur(kernelSizeSub, kernelSizeSub).ApplyInPlace(imageMean2);
            new Divide(imageBorder).ApplyInPlace(imageMean2);

            UnmanagedImage imageVar = new Subtract(new Multiply(imageMean).Apply(imageMean)).Apply(imageMean2);
            imageMean2.Dispose();

            byte cc = (byte)(255 * _epsilon);
            var imageEpsilon = GetFilledImage(
                imageVar.Width, imageVar.Height, imageVar.PixelFormat, Color.FromArgb(cc, cc, cc));

            new Add(imageEpsilon).ApplyInPlace(imageVar);
            imageEpsilon.Dispose();

            UnmanagedImage a = new Divide(imageVar).Apply(mulCov);
            imageVar.Dispose();
            mulCov.Dispose();

            UnmanagedImage b = new Subtract(new Multiply(imageMean).Apply(a)).Apply(overlayMean);
            imageMean.Dispose();
            overlayMean.Dispose();

            UnmanagedImage aMean = new Divide(imageBorder).Apply(new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(a));
            UnmanagedImage bMean = new Divide(imageBorder).Apply(new FastBoxBlur(kernelSizeSub, kernelSizeSub).Apply(b));
            imageBorder.Dispose();
            a.Dispose();
            b.Dispose();

            resizer = new ResizeBilinear(image.Width, image.Height);

            aMean = resizer.Apply(aMean);
            bMean = resizer.Apply(bMean);

            new Multiply(aMean).ApplyInPlace(image);
            aMean.Dispose();
            new Add(bMean).ApplyInPlace(image);
            bMean.Dispose();
        }
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="image">Source image data.</param>
        /// <param name="overlay">Overlay image data.</param>
        ///
        protected override void ProcessFilter(UnmanagedImage image, UnmanagedImage overlay)
        {
            // TODO: Refactor, add "using" clauses, manipulate pixel/pointers directly
            BaseResizeFilter resizer = new ResizeNearestNeighbor(
                (int)(image.Width * _subSamplingRatio),
                (int)(image.Height * _subSamplingRatio));

            UnmanagedImage imageSub   = resizer.Apply(image);
            UnmanagedImage overlaySub = resizer.Apply(overlay);

            byte        kernelSizeSub = (byte)(_kernelSize * _subSamplingRatio);
            FastBoxBlur blur          = new FastBoxBlur(kernelSizeSub, kernelSizeSub);

            UnmanagedImage imageBorder = blur.Apply(GetFilledImage(imageSub.Width, imageSub.Height, imageSub.PixelFormat, Color.White));

            UnmanagedImage imageMean = blur.Apply(imageSub);

            new Divide(imageBorder).ApplyInPlace(imageMean);

            UnmanagedImage overlayMean = blur.Apply(overlaySub);

            new Divide(imageBorder).ApplyInPlace(overlayMean);

            UnmanagedImage mulMean = new Multiply(overlaySub).Apply(imageSub);

            overlaySub.Dispose();
            blur.ApplyInPlace(mulMean);
            new Divide(imageBorder).ApplyInPlace(mulMean);

            // This is the covariance of (image, overlay) in each local patch.
            UnmanagedImage mulCov = new Subtract(new Multiply(overlayMean).Apply(imageMean)).Apply(mulMean);

            mulMean.Dispose();

            UnmanagedImage imageMean2 = new Multiply(imageSub).Apply(imageSub);

            imageSub.Dispose();
            blur.ApplyInPlace(imageMean2);
            new Divide(imageBorder).ApplyInPlace(imageMean2);

            UnmanagedImage imageVar = new Subtract(new Multiply(imageMean).Apply(imageMean)).Apply(imageMean2);

            imageMean2.Dispose();

            byte cc           = (byte)(255 * _epsilon);
            var  imageEpsilon = GetFilledImage(
                imageVar.Width, imageVar.Height, imageVar.PixelFormat, Color.FromArgb(cc, cc, cc));

            new Add(imageEpsilon).ApplyInPlace(imageVar);
            imageEpsilon.Dispose();

            UnmanagedImage a = new Divide(imageVar).Apply(mulCov);

            imageVar.Dispose();
            mulCov.Dispose();

            UnmanagedImage b = new Subtract(new Multiply(imageMean).Apply(a)).Apply(overlayMean);

            imageMean.Dispose();
            overlayMean.Dispose();

            UnmanagedImage aMean = new Divide(imageBorder).Apply(blur.Apply(a));
            UnmanagedImage bMean = new Divide(imageBorder).Apply(blur.Apply(b));

            imageBorder.Dispose();
            a.Dispose();
            b.Dispose();

            resizer = new ResizeBilinear(image.Width, image.Height);

            aMean = resizer.Apply(aMean);
            bMean = resizer.Apply(bMean);

            new Multiply(aMean).ApplyInPlace(image);
            aMean.Dispose();
            new Add(bMean).ApplyInPlace(image);
            bMean.Dispose();
        }