00001 package theba.descriptors;
00002
00003 import java.awt.Point;
00004 import java.awt.Polygon;
00005
00006 import theba.core.ImageFunctions;
00007 import theba.core.RegionDescriptor;
00008 import theba.core.RegionMask;
00009
00010
00011 public class ConvexityDescriptor implements RegionDescriptor {
00012 public String getName() {
00013 return "Convexity";
00014 }
00015
00026 public static double getSolidity(short[] data, int width, int height) {
00027 Polygon pout = getConvexRegion(data, width, height);
00028 int cnt = 0;
00029 int convcnt = 0;
00030 for (int xx = 0; xx < width; xx++) {
00031 for (int yy = 0; yy < height; yy++) {
00032 if (data[xx + yy * width] != 0) {
00033 cnt++;
00034 }
00035 if (pout.contains(xx, yy))
00036 convcnt++;
00037 }
00038 }
00039 if (convcnt == 0)
00040 return 0;
00041 return (cnt / (double) convcnt);
00042 }
00043
00044 public static Polygon getConvexRegion(short[] data, int width, int height) {
00045 int counter = 0;
00046 int i, j, k = 0, m;
00047 for (j = 0; j < width; j++) {
00048 for (i = 0; i < height; i++) {
00049 if (data[j + i * width] != 0)
00050 counter++;
00051 }
00052 }
00053 int[] x = new int[counter + 1];
00054 int[] y = new int[counter + 1];
00055 for (j = 0; j < width; j++) {
00056 for (i = 0; i < height; i++) {
00057 if (data[j + i * width] != 0) {
00058 x[k] = i;
00059 y[k] = j;
00060 k++;
00061 }
00062 }
00063 }
00064
00065 int n = counter, min = 0, ney = 0, h, h2, dx, dy, temp, ax, ay;
00066 double minangle, th, t, v, zxmi = 0;
00067 for (i = 1; i < n; i++) {
00068 if (y[i] < y[min])
00069 min = i;
00070 }
00071 temp = x[0];
00072 x[0] = x[min];
00073 x[min] = temp;
00074 temp = y[0];
00075 y[0] = y[min];
00076 y[min] = temp;
00077 min = 0;
00078 for (i = 1; i < n; i++) {
00079 if (y[i] == y[0]) {
00080 ney++;
00081 if (x[i] < x[min])
00082 min = i;
00083 }
00084 }
00085 temp = x[0];
00086 x[0] = x[min];
00087 x[min] = temp;
00088 temp = y[0];
00089 y[0] = y[min];
00090 y[min] = temp;
00091 min = 0;
00092 m = -1;
00093 x[n] = x[min];
00094 y[n] = y[min];
00095 if (ney > 0)
00096 minangle = -1;
00097 else
00098 minangle = 0;
00099 while (min != n + 0) {
00100 m = m + 1;
00101 temp = x[m];
00102 x[m] = x[min];
00103 x[min] = temp;
00104 temp = y[m];
00105 y[m] = y[min];
00106 y[min] = temp;
00107 min = n;
00108 v = minangle;
00109 minangle = 360.0;
00110 h2 = 0;
00111 for (i = m + 1; i < n + 1; i++) {
00112 dx = x[i] - x[m];
00113 ax = Math.abs(dx);
00114 dy = y[i] - y[m];
00115 ay = Math.abs(dy);
00116 if (dx == 0 && dy == 0)
00117 t = 0.0;
00118 else
00119 t = (double) dy / (double) (ax + ay);
00120 if (dx < 0)
00121 t = 2.0 - t;
00122 else {
00123 if (dy < 0)
00124 t = 4.0 + t;
00125 }
00126 th = t * 90.0;
00127 if (th > v) {
00128 if (th < minangle) {
00129 min = i;
00130 minangle = th;
00131 h2 = dx * dx + dy * dy;
00132 } else {
00133 if (th == minangle) {
00134 h = dx * dx + dy * dy;
00135 if (h > h2) {
00136 min = i;
00137 h2 = h;
00138 }
00139 }
00140 }
00141 }
00142 }
00143 zxmi = zxmi + Math.sqrt(h2);
00144 }
00145 m++;
00146 int[] hx = new int[m];
00147 int[] hy = new int[m];
00148 for (i = 0; i < m; i++) {
00149 hx[i] = x[i];
00150 hy[i] = y[i];
00151 }
00152
00153 Polygon pout = new Polygon(hy, hx, hx.length);
00154 return pout;
00155 }
00156
00165 public static double getConvexity(short[] data, int width, int height) {
00166 Polygon pout = getConvexRegion(data, width, height);
00167 int cnt = 0;
00168 int convcnt = 0;
00169 for (int xx = 0; xx < width; xx++) {
00170 for (int yy = 0; yy < height; yy++) {
00171 if (data[xx + yy * width] != 0) {
00172 cnt++;
00173 }
00174 if (pout.contains(xx, yy))
00175 convcnt++;
00176 }
00177 }
00178 Point start = null;
00179 for (int xx = 0; xx < width; xx++) {
00180 for (int yy = 0; yy < height; yy++) {
00181 if (data[xx + yy * width] != 0) {
00182 start = new Point(xx, yy);
00183 xx = width;
00184 yy = height;
00185 }
00186 }
00187 }
00188 for (int xx = 0; xx < width; xx++) {
00189 for (int yy = 0; yy < height; yy++) {
00190 if (data[xx + yy * width] != 0)
00191 data[xx + yy * width] = (byte) 150;
00192 }
00193 }
00194 if (start == null) {
00195 System.out.println("No region found!");
00196 return 0.0;
00197 }
00198 int count1 = ImageFunctions.countOutlinePixels(data, start.x, start.y,
00199 width, height, (byte) 100);
00200 short[] data2 = new short[data.length];
00201 for (int xx = 0; xx < width; xx++) {
00202 for (int yy = 0; yy < height; yy++) {
00203 if (pout.contains(xx, yy))
00204 data2[xx + yy * width] = (byte) 0x150;
00205 else
00206 data2[xx + yy * width] = 0;
00207 }
00208 }
00209 int count2 = ImageFunctions.countOutlinePixels(data2, start.x, start.y,
00210 width, height, (byte) 100);
00211 return (count2 / (double) count1);
00212 }
00213
00214 public Object measure(RegionMask vmask) {
00215 short[] mask = new short[vmask.getWidth() * vmask.getHeight()];
00216 for (int x = 0; x < vmask.getWidth(); x++)
00217 for (int y = 0; y < vmask.getHeight(); y++)
00218 if (vmask.isSet(x, y, 0))
00219 mask[x + y * vmask.getWidth()] = 1;
00220 return getConvexity(mask, vmask.getWidth(), vmask.getHeight());
00221 }
00222
00223 public String getAbout() {
00224 return "Returns the convexity area of a 2D-shape";
00225 }
00226
00227 public boolean does3D() {
00228 return false;
00229 }
00230
00231 public boolean isNumeric() {
00232 return true;
00233 }
00234 }