blob: 41d8aee1afd6f9c48c9f9e39d5cf54500f24a98b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2008 IBM Corporation and Others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Junji MAEDA - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.visualization.engines.lowvision.image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.WritableRaster;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Stack;
import java.util.Vector;
import org.eclipse.actf.visualization.engines.lowvision.color.ColorUtil;
/*
* Labeled image obtained by connected component detection.
*
* use (width, height, label) or (numComponents, components)
*
* label bg-> 0 fg (connected components) > 1 (Integer)
*
*/
public class LabeledImage {
public static final short METHOD_8_CONNECTIVITY = 0;
public static final short METHOD_4_CONNECTIVITY = 1;
int width;
int height;
int[][] label;
int numComponents; // numComponents == components.length
ConnectedComponent[] components;
short method;
int left;
int right;
int top;
int bottom;
int count;
public LabeledImage(BinaryImage _bi) {
this(_bi, METHOD_8_CONNECTIVITY);
}
public LabeledImage(BinaryImage _bi, short _method) {
width = _bi.width;
height = _bi.height;
label = new int[height][width];
method = _method;
Vector<ConnectedComponent> ccVector = new Vector<ConnectedComponent>();
int currentLabel = 1;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
// same color & not labeled
if (_bi.data[j][i] > 0 && label[j][i] == 0) {
label[j][i] = currentLabel;
count = 1;
labelNeighbor(_bi, i, j, currentLabel, _method);
ConnectedComponent currentCC = new ConnectedComponent(left,
top, right - left + 1, bottom - top + 1, count);
for (int j2 = top; j2 <= bottom; j2++) {
for (int i2 = left; i2 <= right; i2++) {
if (label[j2][i2] == currentLabel) {
currentCC.shape.data[j2 - top][i2 - left] = 1;
}
}
}
ccVector.addElement(currentCC);
currentLabel++;
}
}
}
numComponents = currentLabel - 1;
components = new ConnectedComponent[numComponents];
short conn = ConnectedComponent.CONNECTIVITY_UNSET;
if (method == METHOD_8_CONNECTIVITY)
conn = ConnectedComponent.CONNECTIVITY_8;
else if (method == METHOD_4_CONNECTIVITY)
conn = ConnectedComponent.CONNECTIVITY_4;
for (int i = 0; i < numComponents; i++) {
components[i] = (ConnectedComponent) (ccVector.elementAt(i));
components[i].connectivity = conn;
}
}
/*
* search connected components for pixel(_i, _j)
*/
private void labelNeighbor(BinaryImage _bi, int _i, int _j, int _label,
short _method) {
left = _i;
right = _i;
top = _j;
bottom = _j;
Stack<Coord> labelingStack = new Stack<Coord>();
Coord startCoord = new Coord(_i, _j);
labelingStack.push(startCoord);
while (!labelingStack.empty()) {
Coord co = (Coord) (labelingStack.pop());
int i = co.x;
int j = co.y;
// right
if (i < width - 1 && _bi.data[j][i + 1] > 0 && label[j][i + 1] == 0) {
label[j][i + 1] = _label;
count++;
if (right < i + 1)
right = i + 1;
Coord co2 = new Coord(i + 1, j);
labelingStack.push(co2);
}
// left
if (i > 0 && _bi.data[j][i - 1] > 0 && label[j][i - 1] == 0) {
label[j][i - 1] = _label;
count++;
if (left > i - 1)
left = i - 1;
Coord co2 = new Coord(i - 1, j);
labelingStack.push(co2);
}
// upper
if (j > 0 && _bi.data[j - 1][i] > 0 && label[j - 1][i] == 0) {
label[j - 1][i] = _label;
count++;
if (top > j - 1)
top = j - 1;
Coord co2 = new Coord(i, j - 1);
labelingStack.push(co2);
}
// bottom
if (j < height - 1 && _bi.data[j + 1][i] > 0
&& label[j + 1][i] == 0) {
label[j + 1][i] = _label;
count++;
if (bottom < j + 1)
bottom = j + 1;
Coord co2 = new Coord(i, j + 1);
labelingStack.push(co2);
}
if (_method == METHOD_8_CONNECTIVITY) {
// upper left
if (j > 0 && i > 0 && _bi.data[j - 1][i - 1] > 0
&& label[j - 1][i - 1] == 0) {
label[j - 1][i - 1] = _label;
count++;
if (left > i - 1)
left = i - 1;
if (top > j - 1)
top = j - 1;
Coord co2 = new Coord(i - 1, j - 1);
labelingStack.push(co2);
}
// upper right
if (j > 0 && i < width - 1 && _bi.data[j - 1][i + 1] > 0
&& label[j - 1][i + 1] == 0) {
label[j - 1][i + 1] = _label;
count++;
if (right < i + 1)
right = i + 1;
if (top > j - 1)
top = j - 1;
Coord co2 = new Coord(i + 1, j - 1);
labelingStack.push(co2);
}
// bottom left
if (j < height - 1 && i > 0 && _bi.data[j + 1][i - 1] > 0
&& label[j + 1][i - 1] == 0) {
label[j + 1][i - 1] = _label;
count++;
if (left > i - 1)
left = i - 1;
if (bottom < j + 1)
bottom = j + 1;
Coord co2 = new Coord(i - 1, j + 1);
labelingStack.push(co2);
}
// bottom right
if (j < height - 1 && i < width - 1
&& _bi.data[j + 1][i + 1] > 0
&& label[j + 1][i + 1] == 0) {
label[j + 1][i + 1] = _label;
count++;
if (right < i + 1)
right = i + 1;
if (bottom < j + 1)
bottom = j + 1;
Coord co2 = new Coord(i + 1, j + 1);
labelingStack.push(co2);
}
}
}
}
public int getWidth() {
return (width);
}
public int getHeight() {
return (height);
}
public int[][] getLabel() {
return (label);
}
public int getNumComponents() {
return (numComponents);
}
public ConnectedComponent[] getComponents() {
return (components);
}
public short getMethod() {
return (method);
}
public BinaryImage toBinaryImage() {
BinaryImage bi = new BinaryImage(width, height);
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
if (label[j][i] != 0)
bi.data[j][i] = 1;
}
}
return (bi);
}
/*
* assign color to each label and generate bufferd image
*/
public BufferedImage toBufferedImage() throws ImageException {
if ((numComponents >> 24) != 0) {
throw new ImageException("Too many labels to make bufferedImage.");
}
BufferedImage destImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
WritableRaster destRaster = destImage.copyData(null);
DataBufferInt destBufInt = (DataBufferInt) (destRaster.getDataBuffer());
int[] destArray = destBufInt.getData();
// int pixel = 0;
int k = 0;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
destArray[k] = ColorUtil.distinguishableColor(label[j][i]);
k++;
}
}
destImage.setData(destRaster);
return (destImage);
}
public void dump(PrintStream _ps, boolean _printLabel) {
PrintWriter pw = new PrintWriter(_ps, true);
dump(pw, _printLabel);
}
public void dump(PrintWriter _pw, boolean _printLabel) {
if (_printLabel)
dumpLabel(_pw);
else
dumpComponents(_pw);
}
public void dumpLabel(PrintStream _ps) {
PrintWriter pw = new PrintWriter(_ps, true);
dumpLabel(pw);
}
public void dumpLabel(PrintWriter _pw) {
_pw.println("-------------------------------");
_pw.println("Dumping a labeledImage");
_pw.println("Width = " + width + ", Height = " + height);
for (int j = 0; j < height; j++) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < width; i++) {
if (label[j][i] == 0)
sb.append(".");
else
sb.append("" + (label[j][i] % 10));
}
_pw.println(sb.toString());
}
_pw.println("-------------------------------");
}
public void dumpComponents(PrintStream _ps) {
PrintWriter pw = new PrintWriter(_ps, true);
dumpComponents(pw);
}
public void dumpComponents(PrintWriter _pw) {
_pw.println("-------------------------------");
_pw.println("Dumping components");
_pw.println("# of components = " + numComponents);
for (int i = 0; i < numComponents; i++) {
dumpComponents(_pw, i);
}
_pw.println("-------------------------------");
}
public void dumpComponents(PrintStream _ps, int _i) {
PrintWriter pw = new PrintWriter(_ps, true);
dumpComponents(pw, _i);
}
public void dumpComponents(PrintWriter _pw, int _i) {
_pw.println("-----");
_pw.println("Components # = " + _i);
components[_i].dump(_pw);
}
}