BendingEnergyDescriptor.java
Go to the documentation of this file.00001 package theba.descriptors;
00002
00003 import java.awt.Point;
00004 import java.util.ArrayList;
00005
00006 import theba.core.ImageFunctions;
00007 import theba.core.RegionDescriptor;
00008 import theba.core.RegionMask;
00009
00010
00011 public class BendingEnergyDescriptor implements RegionDescriptor {
00012
00013 public double measure(short[] pixels, int width, int height) {
00014
00015
00016
00017
00018
00019
00020 final double[] d1xGaussian = { 0.0269, 0.0237, 0.0140, 0, -0.0140,
00021 -0.0237, -0.0269 };
00022
00023 final double[] d2xGaussian = { 0, -0.0066, -0.0124, -0.0148, -0.0124,
00024 -0.0066, 0 };
00025
00026 final int radius = 3;
00027
00028 ArrayList points = ImageFunctions.borderTrace(pixels, width, height);
00029 if (points == null)
00030 return -1;
00031
00032 int vectorLength = points.size() + 2 * radius;
00033 double x[] = new double[vectorLength];
00034 double y[] = new double[vectorLength];
00035
00036 Point p = (Point) points.get(0);
00037 double xMin = p.x, yMin = p.y;
00038 for (int k = 0; k < points.size(); k++) {
00039 p = (Point) points.get(k);
00040 x[k + radius] = p.x;
00041 y[k + radius] = p.y;
00042
00043 if (p.x < xMin)
00044 xMin = p.x;
00045 if (p.y < yMin)
00046 yMin = p.y;
00047
00048 }
00049
00050
00051
00052 for (int k = 0; k < radius; k++) {
00053 x[k] = x[x.length - 2 * radius + k];
00054 y[k] = y[x.length - 2 * radius + k];
00055 }
00056 for (int k = x.length - radius; k < x.length; k++) {
00057 x[k] = x[k - x.length + 2 * radius];
00058 y[k] = y[k - x.length + 2 * radius];
00059 }
00060
00061
00062 for (int k = 0; k < x.length; k++) {
00063 x[k] -= xMin;
00064 y[k] -= yMin;
00065 }
00066
00067 double[] dx = new double[vectorLength];
00068 double[] dy = new double[vectorLength];
00069 double[] dxx = new double[vectorLength];
00070 double[] dyy = new double[vectorLength];
00071
00072
00073 for (int k = radius; k < vectorLength - radius; k++) {
00074
00075 for (int m = -radius; m <= radius; m++) {
00076 dx[k] += x[k + m] * d1xGaussian[m + radius];
00077 dxx[k] += x[k + m] * d2xGaussian[m + radius];
00078
00079 dy[k] += y[k + m] * d1xGaussian[m + radius];
00080 dyy[k] += y[k + m] * d2xGaussian[m + radius];
00081 }
00082 }
00083
00084 double bendingEnergySum = 0;
00085 for (int k = radius; k < vectorLength - radius; k++) {
00086 double factor = dx[k] * dyy[k] - dy[k] * dxx[k];
00087 double dividend = Math.pow(dx[k] * dx[k] + dy[k] * dy[k], 1.5);
00088
00089 if (Math.abs(dividend) < 0.001) {
00090 dividend = 0.001;
00091 }
00092 bendingEnergySum += (factor / dividend) * (factor / dividend);
00093
00094 }
00095
00096
00097 return 100 * bendingEnergySum
00098 / (points.size() * points.size() * points.size());
00099 }
00100
00101 public String getName() {
00102 return "Bending energy";
00103 }
00104
00105 public Object measure(RegionMask vmask) {
00106 short[] mask = new short[vmask.getWidth() * vmask.getHeight()];
00107 for (int x = 0; x < vmask.getWidth(); x++)
00108 for (int y = 0; y < vmask.getHeight(); y++)
00109 if (vmask.isSet(x, y, 0))
00110 mask[x + y * vmask.getWidth()] = 1;
00111 return measure(mask, vmask.getWidth(), vmask.getHeight());
00112 }
00113
00114 public String getAbout() {
00115
00116 return null;
00117 }
00118
00119 public boolean does3D() {
00120
00121 return false;
00122 }
00123
00124 public boolean isNumeric() {
00125 return true;
00126 }
00127
00128 }