/* * This file is part of the JFeatureLib project: https://github.com/locked-fg/JFeatureLib * JFeatureLib is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * JFeatureLib 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JFeatureLib; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * You are kindly asked to refer to the papers of the according authors which * should be mentioned in the Javadocs of the respective classes as well as the * JFeatureLib project itself. * * Hints how to cite the projects can be found at * https://github.com/locked-fg/JFeatureLib/wiki/Citation */ package de.lmu.ifi.dbs.jfeaturelib.edgeDetector; import de.lmu.ifi.dbs.jfeaturelib.Descriptor; import de.lmu.ifi.dbs.jfeaturelib.Descriptor.Supports; import de.lmu.ifi.dbs.jfeaturelib.Progress; import ij.plugin.filter.PlugInFilter; import ij.process.ColorProcessor; import ij.process.ImageProcessor; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.EnumSet; /** * The Marr Hildreth edge detector uses the Laplacian of the Gaussian function * to detect edges. Faster runtimes could by achieved by using Difference of * Gaussians instead. */ public class MarrHildreth implements Descriptor { private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); private ColorProcessor image; private float[] kernel = null; /** * Gaussian deviation */ private double deviation; /** * Kernel size */ private int kernelSize; /** * How many times to apply laplacian gaussian operation */ private int times; /** * Creates Marr Hildreth edge detection with default parameters */ public MarrHildreth() { this.deviation = 0.6; this.kernelSize = 7; this.times = 1; } /** * Creates Marr Hildreth edge detection * * @param deviation * @param kernelSize * @param times */ public MarrHildreth(double deviation, int kernelSize, int times) { this.deviation = deviation; this.kernelSize = kernelSize; this.times = times; } /* * @author Giovane.Kuhn - brain@netuno.com.br * http://www.java2s.com/Open-Source/Java-Document/Graphic-Library/apollo/org/apollo/effect/LaplacianGaussianEffect.java.htm * * Create new laplacian gaussian operation @return New instance */ private float[] createLoGOp() { float[] data = new float[kernelSize * kernelSize]; double first = -1.0 / (Math.PI * Math.pow(deviation, 4.0)); double second = 2.0 * Math.pow(deviation, 2.0); double third; int r = kernelSize / 2; int x, y; for (int i = -r; i <= r; i++) { x = i + r; for (int j = -r; j <= r; j++) { y = j + r; third = (Math.pow(i, 2.0) + Math.pow(j, 2.0)) / second; data[x + y * kernelSize] = (float) (first * (1 - third) * Math.exp(-third)); } } return data; } public void process() { // laplacian gaussian operation kernel = createLoGOp(); for (int i = 0; i < times; i++) { image.convolve(kernel, kernelSize, kernelSize); int progress = (int) Math.round(i * (100.0 / (double) times)); pcs.firePropertyChange(Progress.getName(), null, new Progress(progress, "Step " + i + " of " + times)); } } /** * Defines the capability of the algorithm. * * @see PlugInFilter * @see #supports() */ @Override public EnumSet<Supports> supports() { EnumSet set = EnumSet.of(Supports.DOES_RGB); return set; } /** * Starts the canny edge detection. * * @param ip ImageProcessor of the source image */ @Override public void run(ImageProcessor ip) { if (!ip.getClass().isAssignableFrom(ColorProcessor.class)) { throw new IllegalArgumentException("incompatible processor"); } pcs.firePropertyChange(Progress.getName(), null, Progress.START); image = (ColorProcessor) ip; process(); pcs.firePropertyChange(Progress.getName(), null, Progress.END); } @Override public void addPropertyChangeListener(PropertyChangeListener listener) { pcs.addPropertyChangeListener(listener); } //<editor-fold defaultstate="collapsed" desc="accessors"> /** * @return deviation value */ public double getDeviation() { return deviation; } /** * Sets deviation * * @param deviation */ public void setDeviation(double deviation) { this.deviation = deviation; } /** * @return kernel size */ public int getKernelSize() { return kernelSize; } /** * Sets size of kernel * * @param kernelSize */ public void setKernelSize(int kernelSize) { this.kernelSize = kernelSize; } /** * @return amount of iterations */ public int getIterations() { return times; } /** * Sets number of iterations * * @param times */ public void setIterations(int times) { this.times = times; } //</editor-fold> }