// Catalano Imaging Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
// Copyright (c) 2011, Vitomir Struc
// Copyright (c) 2009, Gabriel Peyre
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are 
// met:
//
//    * Redistributions of source code must retain the above copyright 
//      notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright 
//      notice, this list of conditions and the following disclaimer in 
//      the documentation and/or other materials provided with the distribution
//      
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
// POSSIBILITY OF SUCH DAMAGE.
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

package Catalano.Imaging.Filters.Photometric;

import Catalano.Imaging.Filters.*;
import Catalano.Imaging.FastBitmap;
import Catalano.Imaging.Tools.ImageUtils;
import Catalano.Imaging.Tools.Kernel;
import Catalano.Math.Functions.Gaussian;
import Catalano.Math.Matrix;

/**
 * Difference of Gaussians is a feature enhancement algorithm that involves the subtraction of one blurred version of an original image from another.
 * 
 * 

  • Supported types: Grayscale, RGB. *
  • Coordinate System: Matrix. * * @author Diego Catalano */ public class DifferenceOfGaussian implements IPhotometricFilter{ private double sigma1; private double sigma2; private double[][] gv1; private double[][] gv2; /** * Get sigma 1. * @return Sigma value. */ public double getSigma1() { return sigma1; } /** * Set sigma 1. * @param sigma1 Sigma value. */ public void setSigma1(double sigma1) { this.sigma1 = sigma1; BuildKernels(); } /** * Get sigma 2. * @return Sigma value. */ public double getSigma2() { return sigma2; } /** * Set sigma 2. * @param sigma2 Sigma value. */ public void setSigma2(double sigma2) { this.sigma2 = sigma2; BuildKernels(); } /** * Initialize a new instance of the DifferenceOfGaussian class. *
    *
    Default: *
    Sigma 1: 1 *
    Sigma 2: 2 */ public DifferenceOfGaussian() { this(1,2); } /** * Initialize a new instance of the DifferenceOfGaussian class. * @param windowSize1 First window size. * @param windowSize2 Second window size. * @param sigma1 First sigma value. * @param sigma2 Second sigma value. */ public DifferenceOfGaussian(double sigma1, double sigma2) { this.sigma1 = sigma1; this.sigma2 = sigma2; BuildKernels(); } private void BuildKernels(){ int size1 = 2 * (int)Math.ceil(3*sigma1) + 1; Gaussian ga = new Gaussian(sigma1); double[][] g1 = ga.Kernel2D(size1); int size2 = 2 * (int)Math.ceil(3*sigma2) + 1; ga.setSigma(sigma2); double[][] g2 = ga.Kernel2D(size2); //Decompose kernels gv1 = Kernel.Decompose(g1); gv2 = Kernel.Decompose(g2); } @Override public void applyInPlace(FastBitmap fastBitmap) { if(fastBitmap.isGrayscale()){ double[][] image = fastBitmap.toMatrixGrayAsDouble(); ImageUtils.Normalize(image); double[][] im1 = ImageUtils.Convolution(image, gv1[0], gv1[1], true); double[][] im2 = ImageUtils.Convolution(image, gv2[0], gv2[1], true); im1 = Matrix.Subtract(im1, im2); //Normalization double min = Double.MAX_VALUE; double max = -Double.MAX_VALUE; for (int i = 0; i < im1.length; i++) { for (int j = 0; j < im1[0].length; j++) { min = Math.min(min, im1[i][j]); max = Math.max(max, im1[i][j]); } } for (int i = 0; i < im1.length; i++) { for (int j = 0; j < im1[0].length; j++) { fastBitmap.setGray(i, j, (int)Catalano.Math.Tools.Scale(min, max, 0, 255, im1[i][j])); } } } else if(fastBitmap.isRGB()){ double[][][] image = fastBitmap.toMatrixRGBAsDouble(); double[][][] im1 = ImageUtils.Convolution(image, gv1[0], gv1[1], true); double[][][] im2 = ImageUtils.Convolution(image, gv2[0], gv2[1], true); //Subtract operation for (int i = 0; i < im1.length; i++) { for (int j = 0; j < im1[0].length; j++) { im1[i][j][0] = im1[i][j][0] - im2[i][j][0]; im1[i][j][1] = im1[i][j][1] - im2[i][j][1]; im1[i][j][2] = im1[i][j][2] - im2[i][j][2]; } } //Normalization double minR,minG,minB; double maxR,maxG,maxB; minR = minG = minB = Double.MAX_VALUE; maxR = maxG = maxB = -Double.MAX_VALUE; for (int i = 0; i < im1.length; i++) { for (int j = 0; j < im1[0].length; j++) { minR = Math.min(minR, im1[i][j][0]); minG = Math.min(minG, im1[i][j][1]); minB = Math.min(minB, im1[i][j][2]); maxR = Math.max(maxR, im1[i][j][0]); maxG = Math.max(maxG, im1[i][j][1]); maxB = Math.max(maxB, im1[i][j][2]); } } for (int i = 0; i < im1.length; i++) { for (int j = 0; j < im1[0].length; j++) { int r = (int)Catalano.Math.Tools.Scale(minR, maxR, 0, 255, im1[i][j][0]); int g = (int)Catalano.Math.Tools.Scale(minG, maxG, 0, 255, im1[i][j][1]); int b = (int)Catalano.Math.Tools.Scale(minB, maxB, 0, 255, im1[i][j][2]); fastBitmap.setRGB(i, j, r,g,b); } } HistogramAdjust ha = new HistogramAdjust(); ha.applyInPlace(fastBitmap); } } /** * Process the image as matrix. * @param image Image. * @param normalize True if the image needs to be normalized. * @return DoG of the image. */ public double[][] Process(double[][] image, boolean normalize){ double[][] copy = Matrix.Copy(image); ImageUtils.Normalize(copy); double[][] im1 = ImageUtils.Convolution(copy, gv1[0], gv1[1]); double[][] im2 = ImageUtils.Convolution(copy, gv2[0], gv2[1]); im1 = Matrix.Subtract(im1, im2); if(normalize){ ImageUtils.Normalize(im1); } return im1; } }
  • Ads help maintain this website.