/*
* Copyright 2010, 2011 Institut Pasteur.
*
* This file is part of NHerve Main Toolbox, which is an ICY plugin.
*
* NHerve Main Toolbox 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.
*
* NHerve Main Toolbox 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 NHerve Main Toolbox. If not, see <http://www.gnu.org/licenses/>.
*/
package plugins.nherve.toolbox.image.feature.fuzzy;
import icy.image.IcyBufferedImage;
import icy.type.TypeUtil;
import java.util.Arrays;
import java.util.LinkedList;
import plugins.nherve.toolbox.Algorithm;
import plugins.nherve.toolbox.image.feature.region.IcyPixel;
/**
* The Class HysteresisThresholder.
*
* @author Nicolas HERVE - nicolas.herve@pasteur.fr
*/
public class HysteresisThresholder extends Algorithm {
/** The high threshold. */
private double highThreshold;
/** The low threshold. */
private double lowThreshold;
/** The high value. */
private double highValue;
/** The low value. */
private double lowValue;
/**
* Instantiates a new hysteresis thresholder.
*
* @param highThreshold
* the high threshold
* @param lowThreshold
* the low threshold
* @param highValue
* the high value
* @param lowValue
* the low value
*/
public HysteresisThresholder(double highThreshold, double lowThreshold, double highValue, double lowValue) {
super();
this.highThreshold = highThreshold;
this.lowThreshold = lowThreshold;
this.highValue = highValue;
this.lowValue = lowValue;
}
/**
* Instantiates a new hysteresis thresholder.
*
* @param highThreshold
* the high threshold
* @param lowThreshold
* the low threshold
*/
public HysteresisThresholder(double highThreshold, double lowThreshold) {
this(highThreshold, lowThreshold, 255, 0);
}
/**
* Gets the high threshold.
*
* @return the high threshold
*/
public double getHighThreshold() {
return highThreshold;
}
/**
* Gets the low threshold.
*
* @return the low threshold
*/
public double getLowThreshold() {
return lowThreshold;
}
/**
* Gets the high value.
*
* @return the high value
*/
public double getHighValue() {
return highValue;
}
/**
* Gets the low value.
*
* @return the low value
*/
public double getLowValue() {
return lowValue;
}
/**
* Work.
*
* @param gray
* the gray
* @return the icy buffered image
*/
public IcyBufferedImage work(IcyBufferedImage gray) {
LinkedList<IcyPixel> wf = new LinkedList<IcyPixel>();
int w = gray.getWidth();
int h = gray.getHeight();
IcyBufferedImage res = new IcyBufferedImage(w, h, 1, TypeUtil.TYPE_DOUBLE);
double[] table = gray.getDataXYAsDouble(0).clone();
res.setDataXYAsDouble(0, table);
table = res.getDataXYAsDouble(0);
boolean[] done = new boolean[table.length];
Arrays.fill(done, false);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int idx = x + w * y;
if ((done[idx] == false) && (table[idx] >= highThreshold)) {
table[idx] = highValue;
done[idx] = true;
wf.addFirst(new IcyPixel(x, y));
}
}
}
while (!wf.isEmpty()) {
IcyPixel px = wf.removeLast();
int x = (int)px.x;
int y = (int)px.y;
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
int nx = x + dx;
int ny = y + dy;
if ((nx >= 0) && (ny >= 0) && (nx < w) && (ny < h)) {
int idx = nx + w * ny;
if ((!done[idx]) && (table[idx] >= lowThreshold)) {
table[idx] = highValue;
done[idx] = true;
wf.addFirst(new IcyPixel(nx, ny));
}
}
}
}
}
for (int i = 0; i < table.length; i++) {
if (table[i] < highValue) {
table[i] = lowValue;
}
}
res.dataChanged();
return res;
}
}