package de.mpi.rgblab.data;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;
import de.mpi.rgblab.color.ColorModel;
import de.mpi.rgblab.utils.MemoryUtil;
import de.mpi.rgblab.utils.VisUtil;
import de.mpi.rgblab.utils.vector.ByteVector;
import de.mpi.rgblab.utils.vector.FloatVector;
import de.mpi.rgblab.utils.vector.ShortVector;
import de.mpi.rgblab.utils.vector.UnsignedShortVector;
public class Data {
private static final int DIMENSION = 3;
// data byte[x][y]=l - another possibility - saving memory
private ShortVector x;
private ShortVector y;
private ByteVector l;
// metadata
private int capacity;
private int number_points;
private int number_classes;
// size = |C|
private int[] classSize;
// metadata
private int max_x;
private int min_x;
private int max_y;
private int min_y;
// data we need to compute the measures
private int surroundRadius;
private int viewRadius;
// screen data
private int x_res = 0;
private int y_res = 0;
// measures
// size = |P|
private ShortVector saliency;
// size = |P|
// private UnsignedShortVector meanVisibility;
// size = |P|
private FloatVector visibility;
// measures metadata
private int min_saliency;
private int max_saliency;
private float max_visibility;
private float min_visibility;
// help data for compute the measures data
/*
* the sum of the points of every class in the surround, and the sum of the
* background points the first dimenson is the nubmer of the classes + the
* background, the second dimension is the number of the poitns
*
* e.g we have 2 classes and 200 points. Let us take point P and let it
* belongs to class 2. Assume there are 2 different classes in surround -
* class 0 (10 points) and class 1 (5 points) and 3 backround poiints. then
* we have an array with dimensions [3][200].
*
* number_surround_elemtns[2][P] = 3, number_surround_elemtns[1][P] = 5,
* number_surround_elemtns[0][P] = 10
*/
// size = |C|*|P|
private short[][] number_surround_elements = null;
// memory = |C|*|P|
private float[][][] integralSum = null;
// size = Pi*surroundRadius^2
private int[] sliceBoundaries = null;
public Data() {
number_points = 0;
number_classes = 0;
max_x = Integer.MIN_VALUE;
max_y = Integer.MIN_VALUE;
min_x = Integer.MAX_VALUE;
min_y = Integer.MAX_VALUE;
// x = new UnsignedShortVector();
// y = new UnsignedShortVector();
// l = new ByteVector();
}
private void initMinSaliency() {
min_saliency = Integer.MAX_VALUE;
}
private void initMaxSaliency() {
max_saliency = Integer.MIN_VALUE;
}
private void initMinVisibility() {
min_visibility = Float.MAX_VALUE;
}
private void initMaxVisibility() {
max_visibility = Float.MIN_VALUE;
}
private void createImageData(int len) {
// the number of points on the map
capacity = len;
x = new ShortVector(len);
y = new ShortVector(len);
l = new ByteVector(len);
}
private void initMeasures() {
// the number of points on the map
MemoryUtil.printMemoryInMB("before initializing measures");
visibility = new FloatVector(number_points);
saliency = new ShortVector(number_points);
// meanVisibility = new UnsignedShortVector(number_points);
MemoryUtil.printMemoryInMB("after crating vis and saliency vectors");
System.out.println(y_res);
System.out.println(x_res);
integralSum = new float[number_classes + 1][y_res][x_res];
MemoryUtil.printMemoryInMB("after initializing integral sum");
}
public int getNumberOfPoints() {
return this.number_points;
}
public int getNumberOfClasses() {
return this.number_classes;
}
public int getX(int index) {
return this.x.get(index);
}
public int getY(int index) {
return this.y.get(index);
}
public int getLabel(int index) {
return this.l.get(index);
}
public int getMaxSaliency() {
return max_saliency;
}
public int getMinSaliency() {
return min_saliency;
}
public float getMaxVisibility() {
return max_visibility;
}
public float getMinVisibility() {
return min_visibility;
}
public int getSurroundRadius() {
return surroundRadius;
}
public void setSurroundRadius(int radius) {
if (radius != this.surroundRadius) {
this.surroundRadius = radius;
precomputeIntegralClassLabelNumbers();
computeNumberSurroundElements();
}
}
public int getViewRadius() {
return viewRadius;
}
public void setViewRadius(int radius) {
if (radius != this.viewRadius) {
this.viewRadius = radius;
sliceBoundaries = VisUtil.getSliceBoundaries(viewRadius);
}
}
public int getX_res() {
return x_res;
}
public void setX_res(int x_res) {
this.x_res = x_res;
}
public int getY_res() {
return y_res;
}
public void setY_res(int y_res) {
this.y_res = y_res;
}
public void importData(String file, float scale) {
importData(file, 100000, scale);
initNumberSurroundElements();
initMeasures();
}
public void importData(String file) {
long currentTimeInSeconds = System.currentTimeMillis();
importData(file, 100000, 1);
initNumberSurroundElements();
initMeasures();
currentTimeInSeconds = System.currentTimeMillis()
- currentTimeInSeconds;
System.out.println("time: " + currentTimeInSeconds + "milliseconds");
}
private void importDataFit2Screen(String file, int len) {
// int counter = 0;
String this_line;
BufferedReader f;
TreeSet<Integer> class_label_tree = new TreeSet<Integer>();
HashMap<Integer, Integer> data_class_label_index = new HashMap<Integer, Integer>();
try {
// read the file to get the number of the points, number of classes
f = new BufferedReader(new FileReader(file));
createImageData(len);
while ((this_line = f.readLine()) != null) {
String[] result = this_line.split("[,;|]");
if (result.length != DIMENSION)
throw new Exception(
"the file "
+ file
+ " has to have exactly three dimensions - x,y,label");
int x = Integer.valueOf(result[0]);
int y = Integer.valueOf(result[1]);
if (this.max_y < y)
this.max_y = y;
if (this.min_y > y)
this.min_y = y;
if (this.max_x < x)
this.max_x = x;
if (this.min_x > x)
this.min_x = x;
int label = Integer.valueOf(result[2]);
this.x.add(x);
this.y.add(y);
this.l.add(label);
class_label_tree.add(label);
}
f.close();
// // init the number of points, number of classes
Iterator it = class_label_tree.iterator();
for (number_classes = 0; it.hasNext(); number_classes++) {
data_class_label_index.put((Integer) it.next(), number_classes);
}
classSize = new int[number_classes];
this.number_points = this.x.size();
this.capacity = this.x.capacity();
fit2Screen(data_class_label_index);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Can't read file");
System.out.println(e.getMessage());
}
}
public void importData(String file, int len) {
importData(file, len, 1);
initNumberSurroundElements();
initMeasures();
}
public void importData(String file, int len, float scale) {
if (x_res > 0 && y_res > 0) {
importDataFit2Screen(file, len);
return;
}
// int counter = 0;
String this_line;
BufferedReader f;
TreeSet<Integer> class_label_tree = new TreeSet<Integer>();
HashMap<Integer, Integer> data_class_label_index = new HashMap<Integer, Integer>();
try {
// read the file to get the number of the points, number of classes
f = new BufferedReader(new FileReader(file));
createImageData(len);
while ((this_line = f.readLine()) != null) {
String[] result = this_line.split("[,;|]");
if (result.length != DIMENSION)
throw new Exception(
"the file "
+ file
+ " has to have exactly three dimensions - x,y,label");
int x = Integer.valueOf(result[0]);
int y = Integer.valueOf(result[1]);
if (this.max_y < y)
this.max_y = y;
if (this.min_y > y)
this.min_y = y;
if (this.max_x < x)
this.max_x = x;
if (this.min_x > x)
this.min_x = x;
int label = Integer.valueOf(result[2]);
this.x.add(x);
this.y.add(y);
this.l.add(label);
class_label_tree.add(label);
}
f.close();
// init the number of points, number of classes
Iterator it = class_label_tree.iterator();
for (number_classes = 0; it.hasNext(); number_classes++) {
data_class_label_index.put((Integer) it.next(), number_classes);
}
classSize = new int[number_classes];
this.number_points = this.x.size();
this.capacity = this.x.capacity();
if (scale == 1) {
int label;
for (int i = 0; i < number_points; i++) {
label = (data_class_label_index.get(this.l.get(i)));
this.x.set(i, this.x.get(i) - min_x);
this.y.set(i, this.y.get(i) - min_y);
this.l.set(i, label);
classSize[label]++;
}
max_x -= min_x;
max_y -= min_y;
min_x = 0;
min_y = 0;
x_res = max_x;
y_res = max_y;
} else {
x_res = (int) ((max_x - min_x) * scale);
y_res = (int) ((max_y - min_y) * scale);
x_res--;
y_res--;
fit2Screen(data_class_label_index);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Can't read file");
System.out.println(e.getMessage());
}
}
private void initNumberSurroundElements() {
MemoryUtil
.printMemoryInMB("before counting the number of surround elements");
if (number_surround_elements == null)
number_surround_elements = new short[number_classes + 1][number_points];
else if (number_surround_elements.length > (number_classes + 1)
|| number_surround_elements[0].length > number_points) {
number_surround_elements = new short[number_classes + 1][number_points];
}
MemoryUtil
.printMemoryInMB("after counting the number of surround elements");
}
private void computeNumberSurroundElements() {
int[] surroundBoundaries = VisUtil.getSliceBoundaries(surroundRadius);
int x, y; // , l;
int right_x, left_x;
int upperBound_y, lowerBound_y;
for (int i = 0; i < number_points; i++) {
x = getX(i);
y = getY(i);
// l = getLabel(i);
// the number of elements in the surrounding belonging to the pixel
for (int j = 0; j < surroundBoundaries.length; j++) {
right_x = x + j;
left_x = x - j;
// if (left_x < 0) {
// left_x = 0;
// }
// else if (right_x > x_res) {
// right_x = x_res;
// }
upperBound_y = y + surroundBoundaries[j];
lowerBound_y = y - surroundBoundaries[j] - 1;
// check index boundaries
if (upperBound_y > y_res)
upperBound_y = y_res;
else if (lowerBound_y < 0)
lowerBound_y = 0;
float tmp;
for (int k = 0; k <= number_classes; k++) {
try {
tmp = integralSum[k][upperBound_y][right_x]
- integralSum[k][lowerBound_y][right_x];
number_surround_elements[k][i] += tmp;
} catch (Exception e) {
}
if (left_x != right_x) {
try {
tmp = integralSum[k][upperBound_y][left_x]
- integralSum[k][lowerBound_y][left_x];
number_surround_elements[k][i] += tmp;
} catch (Exception e) {
}
}
}
}
}
int k =0;
}
private void precomputeIntegralSaliency() {
MemoryUtil.printMemoryInMB("before precomputing integral SAL");
float[] sum = new float[number_classes];
int count = 0;
for (int x = 0; x < x_res; x++) {
for (int y = 0; y < y_res; y++) {
try {
if (getY(count) == y && getX(count) == x) {
sum[getLabel(count)] += saliency.get(count);
count++;
}
} catch (Exception e) {
}
for (int k = 0; k < number_classes; k++) {
integralSum[k][y][x] = sum[k];
}
}
}
MemoryUtil.printMemoryInMB("after precomputing integral SAL");
}
private void precomputeIntegralClassLabelNumbers() {
MemoryUtil
.printMemoryInMB("before precomputing integral class label numbers");
int[] sum = new int[number_classes + 1];
int i = 0;
int x = 0, y = 0, k = 0;
try {
for (x = 0; x < x_res; x++) {
for (y = 0; y < y_res; y++) {
try {
if (y == getY(i) && x == getX(i)) {
sum[getLabel(i)]++;
i++;
} else {
sum[number_classes]++;
}
} catch (Exception e) {
}
for (k = 0; k <= number_classes; k++) {
integralSum[k][y][x] = sum[k];
}
}
}
} catch (Exception e) {
System.out.println(k);
System.out.println(y);
System.out.println(x);
System.out.println(e.getMessage());
e.printStackTrace();
}
MemoryUtil
.printMemoryInMB("after precomputing integral class label numbers");
}
public boolean computeSaliency(int radius, Vector<ColorModel> rgbColors) {
MemoryUtil.printMemoryInMB("before saliency__");
if (this.surroundRadius != radius)
setSurroundRadius(radius);
Vector<ColorModel> labColors = new Vector<ColorModel>();
VisUtil.rgbToLabColors(rgbColors, labColors);
return computeSaliency(labColors);
}
public boolean computeSaliency(Vector<ColorModel> labColors) {
if (labColors.size() < number_classes) {
System.out.println("you need at least " + number_classes
+ " colors");
return false;
}
initMinSaliency();
initMaxSaliency();
// saliency.clear();
ColorModel currentPointColor;
int l;
int z = 0;
for (int i = 0; i < number_points; i++) {
l = getLabel(i);
currentPointColor = (ColorModel) labColors.elementAt(l);
z = (int) VisUtil.eucl_distance_center_surrounding(
currentPointColor, labColors, number_surround_elements, i,
number_classes);
if (z > max_saliency)
max_saliency = z;
if (z < min_saliency)
min_saliency = z;
saliency.set(i, z);
}
return true;
}
// public boolean computeMeanVisibility(int radius) {
// }
public boolean computeVisibility(int radius) {
setViewRadius(radius);
return computeVisibility();
}
public boolean computeVisibility() {
if (sliceBoundaries == null)
return false;
precomputeIntegralSaliency();
initMinVisibility();
initMaxVisibility();
int x, y, l;
int upperBound_y, right_x;
int lowerBound_y, left_x; // [] = new int[sliceBoundaries.length];
float z = 0;
for (int i = 0; i < number_points; i++) {
x = getX(i);
y = getY(i);
l = getLabel(i);
for (int j = 0; j < sliceBoundaries.length; j++) {
right_x = x + j;
left_x = x - j;
upperBound_y = y + sliceBoundaries[j];
lowerBound_y = y - sliceBoundaries[j] - 1;
// check index boundaries
if (upperBound_y > y_res)
upperBound_y = y_res;
else if (lowerBound_y < 0)
lowerBound_y = 0;
// compute
try {
z += integralSum[l][upperBound_y][right_x]
- integralSum[l][lowerBound_y][right_x];
} catch (Exception e) {
// right_x > res_x or right_x < 0
}
if (left_x != right_x) {
try {
z += integralSum[l][upperBound_y][left_x]
- integralSum[l][lowerBound_y][left_x];
} catch (Exception e) {
}
}
}
if (z > max_visibility)
max_visibility = z;
if (z < min_visibility)
min_visibility = z;
visibility.set(i, z);
z = 0;
}
return true;
}
private void fit2Screen(HashMap<Integer, Integer> data_class_label_index) {
System.out.println("resolution: " + x_res + ", " + y_res);
System.out.println("number of points: " + number_points);
float x_ratio = (x_res - 1) / (float) (max_x - min_x);
float y_ratio = (y_res - 1) / (float) (max_y - min_y);
byte[][] point = new byte[x_res][y_res];
int px = 0, py = 0;
int i = 0;
for (i = 0; i < number_points; i++) {
px = (int) ((getX(i) - min_x) * x_ratio);
py = (int) ((getY(i) - min_y) * y_ratio);
// +1 because 0 means no element - background color
point[px][py] = (byte) (data_class_label_index.get(getLabel(i)) + 1);
}
int l1 = point.length;
int l2 = point[0].length;
int label;
int count = 0;
for (i = 0; i < l1; i++) {
for (int j = 0; j < l2; j++) {
if (point[i][j] != 0) {
x.set(count, i);
y.set(count, j);
label = point[i][j] - 1;
l.set(count, label);
count++;
classSize[label]++;
}
}
}
number_points = count;
max_x = (int) ((max_x - min_x) * x_ratio);
max_y = (int) ((max_y - min_y) * y_ratio);
min_x = 0;
min_y = 0;
}
}