/*
* 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;
import icy.image.IcyBufferedImage;
import icy.roi.ROI2DArea;
import icy.sequence.Sequence;
import icy.type.TypeUtil;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.vecmath.Point3i;
import plugins.adufour.connectedcomponents.ConnectedComponent;
import plugins.nherve.toolbox.image.feature.region.IcyPixel;
import plugins.nherve.toolbox.image.toolboxes.MorphologyToolbox;
/**
* The Class My2DConnectedComponent.
*
* @author Nicolas HERVE - nicolas.herve@pasteur.fr
*/
public class My2DConnectedComponent implements PointsEnsemble {
/** The points. */
private ArrayList<Point3i> points;
/** The perimeter. */
private ArrayList<Point3i> perimeter;
/** The height. */
private int minX, minY, width, height;
/** The label. */
private int label;
/**
* Instantiates a new my2 d connected component.
*
* @param label
* the label
* @param internal
* the internal
*/
public My2DConnectedComponent(int label, Point3i[] internal) {
this(label);
int maxX = 0;
int maxY = 0;
int x = 0;
int y = 0;
for (Point3i p : internal) {
x = p.x;
y = p.y;
if (x > maxX) {
maxX = x;
}
if (x < minX) {
minX = x;
}
if (y > maxY) {
maxY = y;
}
if (y < minY) {
minY = y;
}
this.points.add(new Point3i(x, y, 0));
}
this.width = maxX - minX;
this.height = maxY - minY;
}
public My2DConnectedComponent(int label, List<Point3i> internal) {
this(label);
int maxX = 0;
int maxY = 0;
int x = 0;
int y = 0;
for (Point3i p : internal) {
x = p.x;
y = p.y;
if (x > maxX) {
maxX = x;
}
if (x < minX) {
minX = x;
}
if (y > maxY) {
maxY = y;
}
if (y < minY) {
minY = y;
}
this.points.add(new Point3i(x, y, 0));
}
this.width = maxX - minX;
this.height = maxY - minY;
}
public My2DConnectedComponent(int label) {
super();
this.minX = Integer.MAX_VALUE;
this.minY = Integer.MAX_VALUE;
this.points = new ArrayList<Point3i>();
this.label = label;
this.perimeter = null;
}
/**
* Instantiates a new my2 d connected component.
*
* @param label
* the label
* @param internal
* the internal
*/
public My2DConnectedComponent(int label, ConnectedComponent internal) {
this(label, internal.getPoints());
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.PointsEnsemble#getHeight()
*/
public int getHeight() {
return height;
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.PointsEnsemble#getId()
*/
@Override
public int getId() {
return getLabel();
}
/**
* Gets the label.
*
* @return the label
*/
public int getLabel() {
return label;
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.PointsEnsemble#getMinX()
*/
public int getMinX() {
return minX;
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.PointsEnsemble#getMinY()
*/
public int getMinY() {
return minY;
}
/**
* Gets the bounds.
*
* @return the bounds
*/
public Rectangle getBounds() {
return new Rectangle(getMinX(), getMinY(), getWidth(), getHeight());
}
@Override
public List<Point3i> getPoints() {
return points;
}
/**
* Gets the surface.
*
* @return the surface
*/
public int getSurface() {
return points.size();
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.PointsEnsemble#getWidth()
*/
public int getWidth() {
return width;
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.PointsEnsemble#getXCenter()
*/
@Override
public int getXCenter() {
return getMinX() + getWidth() / 2;
}
/**
* Contains.
*
* @param px
* the px
* @return true, if successful
*/
public boolean contains(IcyPixel px) {
return contains((int) px.x, (int) px.y);
}
/**
* Contains.
*
* @param x
* the x
* @param y
* the y
* @return true, if successful
*/
public boolean contains(int x, int y) {
for (Point3i pt : points) {
if ((pt.x == x) && (pt.y == y)) {
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.PointsEnsemble#getYCenter()
*/
@Override
public int getYCenter() {
return getMinY() + getHeight() / 2;
}
/**
* Find perimeter.
*/
private void findPerimeter() {
int xOffset = getMinX() - 1;
int yOffset = getMinY() - 1;
int w = getWidth() + 3;
BinaryIcyBufferedImage bin1 = asBinaryImage();
BinaryIcyBufferedImage bin2 = bin1.getCopy();
MorphologyToolbox.erodeInPlace(bin2);
bin1.remove(bin2);
perimeter = new ArrayList<Point3i>();
byte[] raw = bin1.getRawData();
for (int i = 0; i < raw.length; i++) {
if (raw[i] == BinaryIcyBufferedImage.TRUE) {
perimeter.add(new Point3i(xOffset + i % w, yOffset + i / w , 0));
}
}
}
/**
* Gets the perimeter points.
*
* @return the perimeter points
*/
public List<Point3i> getPerimeterPoints() {
if (perimeter == null) {
findPerimeter();
}
return perimeter;
}
/**
* As ro i2 d area.
*
* @param seq
* the seq
* @return the rO i2 d area
*/
public ROI2DArea asROI2DArea(Sequence seq) {
ROI2DArea asa = new ROI2DArea(new Point2D.Float(0, 0));
int bbw = getWidth() + 1;
int bbh = getHeight() + 1;
Rectangle bbx = new Rectangle(minX, minY, bbw, bbh);
boolean[] data = new boolean[bbw * bbh];
Arrays.fill(data, false);
for (Point3i pt : points) {
data[pt.x - minX + bbw * (pt.y - minY)] = true;
}
asa.setAsBooleanMask(bbx, data);
asa.attachTo(seq);
return asa;
}
/**
* As binary image.
*
* @return the binary icy buffered image
*/
public BinaryIcyBufferedImage asBinaryImage() {
int xOffset = getMinX() - 1;
int yOffset = getMinY() - 1;
int w = getWidth() + 3;
int h = getHeight() + 3;
return asBinaryImage(w, h, xOffset, yOffset);
}
/**
* As binary image.
*
* @param w
* the w
* @param h
* the h
* @param xOffset
* the x offset
* @param yOffset
* the y offset
* @return the binary icy buffered image
*/
public BinaryIcyBufferedImage asBinaryImage(int w, int h, int xOffset, int yOffset) {
BinaryIcyBufferedImage bin = new BinaryIcyBufferedImage(w, h);
byte[] raw = bin.getRawData();
for (Point3i pt : points) {
raw[pt.x - xOffset + w * (pt.y - yOffset)] = BinaryIcyBufferedImage.TRUE;
}
return bin;
}
/**
* As image.
*
* @return the icy buffered image
*/
public IcyBufferedImage asImage() {
int xOffset = getMinX() - 1;
int yOffset = getMinY() - 1;
int w = getWidth() + 3;
int h = getHeight() + 3;
IcyBufferedImage bin = new IcyBufferedImage(w, h, 3, TypeUtil.TYPE_BYTE);
byte[][] raw = bin.getDataXYCAsByte();
int idx = 0;
for (Point3i pt : points) {
idx = pt.x - xOffset + w * (pt.y - yOffset);
raw[0][idx] = (byte) 255;
raw[1][idx] = (byte) 255;
raw[2][idx] = (byte) 255;
}
return bin;
}
/**
* As image.
*
* @param w
* the w
* @param h
* the h
* @return the icy buffered image
*/
public IcyBufferedImage asImage(int w, int h) {
return asImage(w, h, points);
}
/**
* As image.
*
* @param w
* the w
* @param h
* the h
* @param points
* the points
* @return the icy buffered image
*/
public static IcyBufferedImage asImage(int w, int h, List<Point3i> points) {
IcyBufferedImage bin = new IcyBufferedImage(w, h, 3, TypeUtil.TYPE_BYTE);
byte[][] raw = bin.getDataXYCAsByte();
Arrays.fill(raw[0], (byte) 255);
Arrays.fill(raw[1], (byte) 255);
Arrays.fill(raw[2], (byte) 255);
int idx = 0;
for (Point3i pt : points) {
idx = pt.x + w * pt.y;
raw[0][idx] = (byte) 0;
raw[1][idx] = (byte) 0;
raw[2][idx] = (byte) 0;
}
return bin;
}
}