AvgCurvature.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 import theba.core.math.NonUniformInterpolation;
00010
00011
00012 public class AvgCurvature implements RegionDescriptor {
00013
00014 public Object measure(RegionMask vmask) {
00015 short[] mask = new short[vmask.getWidth() * vmask.getHeight()];
00016 for (int x = 0; x < vmask.getWidth(); x++)
00017 for (int y = 0; y < vmask.getHeight(); y++)
00018 if (vmask.isSet(x, y, 0))
00019 mask[x + y * vmask.getWidth()] = 1;
00020 return measure(mask, vmask.getWidth(), vmask.getHeight());
00021 }
00022
00023 public double measure(short[] pixels, int width, int height) {
00024
00025 final double[] d1xGaussian = { 0.0269, 0.0237, 0.0140, 0, -0.0140,
00026 -0.0237, -0.0269 };
00027 final double[] d2xGaussian = { 0, -0.0066, -0.0124, -0.0148, -0.0124,
00028 -0.0066, 0 };
00029
00030 final int radius = 3;
00031
00032 ArrayList points = ImageFunctions.borderTrace(pixels, width, height);
00033 int[] chaincode = ImageFunctions.getChaincode(points);
00034 double[] s = ImageFunctions.getArcLenghts(chaincode);
00035 int vectorLength = points.size() + 2 * radius;
00036
00037 double x[] = new double[points.size()];
00038 double y[] = new double[points.size()];
00039 Point p = null;
00040 for (int i = 0; i < points.size(); i++) {
00041 p = (Point) points.get(i);
00042 x[i] = p.x;
00043 y[i] = p.y;
00044 }
00045
00046 NonUniformInterpolation nx = new NonUniformInterpolation(s, x);
00047 NonUniformInterpolation ny = new NonUniformInterpolation(s, y);
00048 double step = s[s.length - 1] / s.length;
00049
00050
00051 double xi[] = new double[vectorLength];
00052 double yi[] = new double[vectorLength];
00053 double xMin = Double.MAX_VALUE;
00054 double yMin = Double.MAX_VALUE;
00055 double xMax = Double.MIN_VALUE;
00056 double yMax = Double.MIN_VALUE;
00057 double arcLength = 0;
00058 for (int i = 0; i < s.length; i++) {
00059 xi[i + radius] = nx.interpolate(arcLength);
00060 yi[i + radius] = ny.interpolate(arcLength);
00061
00062 if (xi[i + radius] < xMin)
00063 xMin = xi[i + radius];
00064 if (yi[i + radius] < yMin)
00065 yMin = yi[i + radius];
00066
00067 if (xi[i + radius] > xMax)
00068 xMax = xi[i + radius];
00069 if (yi[i + radius] > yMax)
00070 yMax = yi[i + radius];
00071
00072 arcLength += step;
00073 }
00074
00075
00076 x = xi;
00077 y = yi;
00078
00079
00080
00081 for (int k = 0; k < radius; k++) {
00082 x[k] = x[x.length - 2 * radius + k];
00083 y[k] = y[x.length - 2 * radius + k];
00084 }
00085 for (int k = x.length - radius; k < x.length; k++) {
00086 x[k] = x[k - x.length + 2 * radius];
00087 y[k] = y[k - x.length + 2 * radius];
00088 }
00089
00090
00091 for (int k = 0; k < x.length; k++) {
00092 x[k] -= xMin;
00093 y[k] -= yMin;
00094 }
00095
00096 double[] dx = new double[vectorLength];
00097 double[] dy = new double[vectorLength];
00098 double[] dxx = new double[vectorLength];
00099 double[] dyy = new double[vectorLength];
00100
00101 for (int k = radius; k < vectorLength - radius; k++) {
00102
00103 for (int m = -radius; m <= radius; m++) {
00104 dx[k] += x[k + m] * d1xGaussian[m + radius];
00105 dxx[k] += x[k + m] * d2xGaussian[m + radius];
00106
00107 dy[k] += y[k + m] * d1xGaussian[m + radius];
00108 dyy[k] += y[k + m] * d2xGaussian[m + radius];
00109 }
00110 }
00111
00112 double curvatureSum = 0;
00113 for (int k = radius; k < vectorLength - radius; k++) {
00114 double factor = dx[k] * dyy[k] - dy[k] * dxx[k];
00115 double dividend = Math.pow(dx[k] * dx[k] + dy[k] * dy[k], 1.5);
00116
00117 if (dividend < 0.001) {
00118 dividend = 0.001;
00119 }
00120 curvatureSum += Math.abs(factor / dividend);
00121
00122 }
00123
00124
00125 return curvatureSum / (points.size() * points.size());
00126
00127 }
00128
00129 public String getName() {
00130 return "Average, scale-independent curvature";
00131 }
00132
00133 public String getAbout() {
00134 return "Returns the average, weighted curvature of a 4-connected 2D region";
00135 }
00136
00137 public boolean does3D() {
00138 return false;
00139 }
00140
00141 public boolean isNumeric() {
00142 return true;
00143 }
00144
00145 }