/** * */ package cortexrules; import java.awt.geom.*; // Front End imports import analyze.*; /** *

This program takes the cortex output from * a version of the gabor model and links together * orientation elements that are the same valence. * * In particular, this one finds will find all of the orientations * that are adjacent and create and ordered list. * * It then looks at position, It takes the max (and any adjancent points * with same orientation and the point * most nearly opposite with nearly the same orientation. * So from every point there should be two connections as * nearly opposite as possible. * * These local sets are then joined with those that overlap. * * Ultimately the output should be a general path that * draws a segmented object from this information *

* @author John H. Krantz, Ph.D. * Copyright 2007 * @version 0.1 * */ public class GeoOrientLineJoin { // flags to indicate locations checked private boolean [][] checked; // array of connected objects that make up the joined // first level general paths // private Point2D [][] posPoints; // old method private Point2D [][] negPoints; // initial combination array private double v2 [][][][]; // column index values // numberical values are +/- from the linear direction // private final static int U_UR_LINR = 0; // private final static int U_UR_45 = 1; // private final static int U_UR_90 = 2; // private final static int U_UR_135 = 3; // private final static int R_DR_LINR = 4; // private final static int R_DR_45 = 5; // private final static int R_DR_90 = 6; // private final static int R_DR_135 = 7; // private final static int D_DL_LINR = 8; // private final static int D_DL_45 = 9; // private final static int D_DL_90 = 10; // private final static int D_DL_135 = 11; // private final static int L_UL_LINR = 12; // private final static int L_UL_45 = 13; // private final static int L_UL_90 = 14; // private final static int L_UL_135 = 15; // this static array indicates where in the 16 positions for // the proposed column for V2 for the direction that connection // make to the central point. private final static int [][] ANCHORS = {{12,12,8},{0,-1,8},{0,4,4}}; // rule parameters private double threshMax = 15; // the connection strength // threshold. private double angDiv = 90.0/4.0; // the about to divide // angle differences by to determine connection // strength relative to difference from // linearity // flag for no angle in this position. // if the angle, the difference is at least 90. private final static double NO_ANGLE = 0.0; private final static int NO_POS = -10; // routine to add to list of found shapes private AddPoint addPt = new AddPoint(); private AddPointArray addArray = new AddPointArray(); // rule name public final static String NAME = "Geometry Orientation Line Joined"; // get methods /** * getAllShapes: allows all segmented shapes to be discovered * in the output of the cortex model * @param double [][][] cortex the cortex output data * @param Rectangle2D [][] rfArray the plotting array for the cortex * @return GeneralPath[] the segmented shapes */ /** * second attempt. determine all local connections that are * sufficiently strong. connect only to the strongest * but allow overlaps. Plan to use overlaps later to * build larger objects. */ public GeneralPath [][] getAllShapes(double [][][] cortex, Rectangle2D [][] rfArray){ //if (ANCHORS[0][1]==12) //javax.swing.JOptionPane.showMessageDialog(null, "here"); checked = new boolean[rfArray[0].length][rfArray.length]; // clear the array for (int i = 0; i < checked.length; i ++){ for (int j = 0; j < checked[0].length; j ++){ checked[i][j] = false; } } // create the v2 array // dimesions - x, y, pos/neg, line/orient v2 = new double[checked.length][checked[0].length][2][16]; // objects to return GeneralPath [][] shapes = new GeneralPath[2][]; // clear objects shapes[Rules.POS] = null; shapes[Rules.NEG] = null; negPoints = null; // individual object that is found Point2D [] path; // do not check edges boolean pos = true; // a positive edge // false for a negative going edge for (int x = 1; x < checked.length-1; x ++){ for (int y = 1; y < checked[0].length-1; y ++){ // see if this location has any orientation information if (cortex[PlotOutput.ANGLE][x][y] != PlotOutput.NO_ANGLE & cortex[PlotOutput.ANGLE][x][y] != PlotOutput.BREAK){ path = new Point2D[1]; path[0] = new Point2D.Double(rfArray[y][x].getCenterX(), rfArray[y][x].getCenterY()); if(cortex[PlotOutput.ANGLE][x][y] >= 0){ pos = true; // following positive or maxima } else { pos = false; // following negative or minima } // now see if there are any other // adjacent locations with a line double [][] connectVal = new double[3][3]; for (int i = -1; i < 2; i ++){ for (int j = -1; j < 2; j ++){ // is there an angle here if (cortex[PlotOutput.ANGLE][x+i][y+j] != PlotOutput.NO_ANGLE){ // check to make sure same direction if ((pos & cortex[PlotOutput.ANGLE][x+i][y+j] >= 0) | (!pos & cortex[PlotOutput.ANGLE][x+i][y+j] < 0)){ // determine the angle difference using // the equation so small differences = large values double temp = Math.abs(cortex[PlotOutput.ANGLE][x][y]- cortex[PlotOutput.ANGLE][x+i][y+j]); if (temp < 90) temp = 180 - temp; connectVal[i+1][j+1] = temp; } // end if same direction edge else { // flag for later processing connectVal[i+1][j+1] = NO_ANGLE; } // end no angle } // end if an angle else { connectVal[i+1][j+1] = NO_ANGLE; } } // end for i } // end for j // find the pair of exits from the // central point that have the // minimum connection strength double max = 0; int [] maxI = null; int [] maxJ = null; for (int i = 0; i < connectVal.length; i ++){ for (int j = 0; j < connectVal.length; j ++){ // don't check own point if (!(i == 1 & j == 1)){ for (int k = 0; k < connectVal.length; k ++){ for (int l = j; l < connectVal.length; l ++){ // don't check central point or already checked points if (!(k == 1 & l == 1) & !(k == i & l <= j)){ // determine linearity value double lV = Math.abs(k+i-2.0)+Math.abs(l+j-2); // determined combined connection value double cV = connectVal[i][j]+ connectVal[k][l]+ (180-(lV*angDiv)); if (pos){ v2[x][y][0][ANCHORS[i][j]+(int)lV] += cV; } else { v2[x][y][1][ANCHORS[i][j]+(int)lV] += cV; } if (cV > max){ // create a new list // old max now becomes the // second strongest connection max = cV; maxI = new int [2]; maxJ = new int [2]; maxI[0] = i-1; // set to relative to current maxJ[0] = j-1; // current position maxI[1] = k-1; maxJ[1] = l-1; if (connectVal[i][j] == NO_ANGLE){ maxI[0] = NO_POS; } if (connectVal[k][l] == NO_ANGLE){ maxI[1] = NO_POS; } } // end if new max } // end down check center or current point } // end for k } // end for l } // end don't check own point } // end for j } // end for i max and ma2 have been determined // now add points // path connection must exceed treshold // and connect to at least one adajenct location // also if two poitns added, linearity is preferred if (max > threshMax){ // add to list of points // deal with different conditions for (int i = 0; i < maxI.length; i ++){ if (maxI[i] != NO_POS){ path = addPt.addPoint(path, new Point2D.Double( rfArray[y+maxJ[i]][x+maxI[i]].getCenterX(), rfArray[y+maxJ[i]][x+maxI[i]].getCenterY())); } } // only add point if one other point is connected to // this central point if (path.length > 1){ if (pos){ // posPoints = addArray.addPoint(posPoints,path); } else { negPoints = addArray.addPoint(negPoints, path); } } } } // end if there is an orientation } // end for y }// end for x // join the positive shapes // keep track of where have checked boolean [][][] chk = new boolean [v2.length][v2[0].length] [v2[0][0][0].length]; // now clear the array for (int i = 0; i < chk.length; i ++){ for (int j = 0; j < chk[0].length; j ++){ for (int k = 0; k < chk[0][0].length; k ++){ chk[i][j][k] = false; } } } // end clearing the array // now go through the array for (int x = 0; x < v2.length; x ++){ // x dimension for (int y = 0; y < v2[0].length; y ++){ // y dim. // seach column for (int c = 0; c < 4; c ++){ // search column }// end search column } // end y dimension } // end x dimension // now create the positive shapes. System.gc(); // end making positive shapes // join the negative shapes boolean joined [] = new boolean[negPoints.length]; for (int i = 0; i < joined.length; i ++){ joined [i] = false; } Point2D [][][] negShapePoints = null; // list of points to draw System.gc(); for (int i = 0; i < negPoints.length; i ++){ if (!joined[i]){ if (i == 0){ negShapePoints = new Point2D.Double[1][1][]; negShapePoints[0][0] = negPoints[0]; }// if first shape else { Point2D hold [][][] = new Point2D.Double[negShapePoints.length][][]; for (int x = 0; x < hold.length; x ++){ hold[x] = negShapePoints[x]; } negShapePoints = new Point2D.Double[hold.length+1][][]; for (int x = 0; x < hold.length; x++){ negShapePoints[x] = hold[x]; } // add new array negShapePoints[hold.length] = new Point2D.Double[1][negPoints[i].length]; for (int x = 0; x < negPoints[i].length; x ++){ negShapePoints[hold.length][0][x] = negPoints[i][x]; } }// end setting up first set of points joined [i] = true; int cur = negShapePoints.length-1; // now look for other possible partners boolean anyOver = false; do { // keep checking till all overlaps found anyOver = false; for (int j = 0; j < negPoints.length; j ++){ // here find if points overlap if so add boolean overlap = false; if (j != i & !joined[j]){// do chech same array for (int x = 0; x < negPoints[j].length; x ++){ for (int y = 0; y < negShapePoints[cur].length; y ++){ for (int z = 0; z < negShapePoints[cur][y].length; z ++){ if (negShapePoints[cur][y][z].getX()== negPoints[j][x].getX() & negShapePoints[cur][y][z].getY()== negPoints[j][x].getY()){ overlap = true; } // end if same point } // end for z } // end for y } // end for x // if an overlap add this array if (overlap){ anyOver = true; joined[j] = true; Point2D hold [][] = new Point2D.Double[negShapePoints[cur].length][]; for (int x = 0; x < hold.length; x ++){ hold[x] = negShapePoints[cur][x]; } negShapePoints[cur] = new Point2D.Double[hold.length+1][]; for (int x = 0; x < hold.length; x++){ negShapePoints[cur][x] = hold[x]; } // add new array negShapePoints[cur][hold.length] = new Point2D.Double[negPoints[j].length]; for (int x = 0; x < negPoints[j].length; x ++){ negShapePoints[cur][hold.length][x] = negPoints[j][x]; } } } // end not same point } // end searching for overlap } while (anyOver); // end checking // till all overlaps found }// end if previously not in object } // end joining negative shapes // now create the neg shapes. System.gc(); shapes[Rules.NEG] = new GeneralPath[negShapePoints.length]; for (int i = 0; i < negShapePoints.length; i ++){ shapes[Rules.NEG][i] = new GeneralPath(); for (int j = 0; j < negShapePoints[i].length; j ++){ for (int l = 1; l < negShapePoints[i][j].length; l ++){ shapes[Rules.NEG][i].moveTo(negShapePoints[i][j][0].getX(), negShapePoints[i][j][0].getY()); shapes[Rules.NEG][i].lineTo(negShapePoints[i][j][l].getX(), negShapePoints[i][j][l].getY()); } // end for l } // end for j } // end for i // end making negatve shapes // return the collection return shapes; } }