/** * */ 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, it joines immediate neighbors, but only to points * that have the closest to the same orientation. other * points with more disimilar orientations will not be joined. * * It then finds segments that overlap and puts those together. * * Those that do not overlap arenot joined. * * 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 ContOrientSensJoin { // flags to indicate locations checked private boolean [][] checked; // array of connected objects that make up the joined // first level general paths private Point2D [][] posPoints; private Point2D [][] negPoints; // rule parameters private double threshMax = 15; // the connection strength // threshold. // 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 = "Contiguous Orientation Sensitive 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){ 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; } } // objects to return GeneralPath [][] shapes = new GeneralPath[2][]; // clear objects shapes[Rules.POS] = null; shapes[Rules.NEG] = null; posPoints = 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 ++){ // are we in bounds if (x+i >=0 & x+i < checked.length & y+j >=0 & y+j < checked[0].length){ // 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)){ 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 } // end if an angle }// end if in bounds } // end for i } // end for j // find the maximum connectin 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)){ if (connectVal[i][j] > max){ // create a new list max = connectVal[i][j]; maxI = new int [1]; maxJ = new int [1]; maxI[0] = i-1; // set to relative to current maxJ[0] = j-1; // current position } else if (connectVal[i][j] == max & maxI != null){ int tempI [] = new int [maxI.length]; int tempJ [] = new int [maxJ.length]; // move current list to temp lists for (int idx = 0; idx < maxI.length; idx ++){ tempI[idx] = maxI[idx]; tempJ[idx] = maxJ[idx]; } // lengthen list maxI = new int[tempI.length+1]; maxJ = new int[tempJ.length+1]; // restore old items for (int idx = 0; idx < tempI.length; idx ++){ maxI[idx] = tempI[idx]; maxJ[idx] = tempJ[idx]; } // add new item maxI[maxI.length-1] = i-1; maxJ[maxJ.length-1] = j-1; } } // end don'w check own point } // end for j } // end for i // now create the connected general path // path connection must exceed treshold // and connect to at least one adajenct location if (max > threshMax & maxI != null){ for (int i = 0; i < maxI.length; i ++){ // add to list of points path = addPt.addPoint(path, new Point2D.Double( rfArray[y+maxJ[i]][x+maxI[i]].getCenterX(), rfArray[y+maxJ[i]][x+maxI[i]].getCenterY())); } 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 boolean [] joined = new boolean[posPoints.length]; for (int i = 0; i < joined.length; i ++){ joined [i] = false; } Point2D [][][] posShapePoints = null; // list of points to draw System.gc(); for (int i = 0; i < posPoints.length; i ++){ if (!joined[i]){ if (i == 0){ posShapePoints = new Point2D.Double[1][1][]; posShapePoints[0][0] = posPoints[0]; }// if first shape else { Point2D hold [][][] = new Point2D.Double[posShapePoints.length][][]; for (int x = 0; x < hold.length; x ++){ hold[x] = posShapePoints[x]; } posShapePoints = new Point2D.Double[hold.length+1][][]; for (int x = 0; x < hold.length; x++){ posShapePoints[x] = hold[x]; } // add new array posShapePoints[hold.length] = new Point2D.Double[1][posPoints[i].length]; for (int x = 0; x < posPoints[i].length; x ++){ posShapePoints[hold.length][0][x] = posPoints[i][x]; } }// end setting up first set of points joined [i] = true; int cur = posShapePoints.length-1; // now look for other possible partners boolean anyOver = false; do { // keep checking until no overlap is found anyOver = false; for (int j = 0; j < posPoints.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 < posPoints[j].length; x ++){ for (int y = 0; y < posShapePoints[cur].length; y ++){ for (int z = 0; z < posShapePoints[cur][y].length; z ++){ if (posShapePoints[cur][y][z].getX()== posPoints[j][x].getX() & posShapePoints[cur][y][z].getY()== posPoints[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){ joined[j] = true; anyOver = true; Point2D hold [][] = new Point2D.Double[posShapePoints[cur].length][]; for (int x = 0; x < hold.length; x ++){ hold[x] = posShapePoints[cur][x]; } posShapePoints[cur] = new Point2D.Double[hold.length+1][]; for (int x = 0; x < hold.length; x++){ posShapePoints[cur][x] = hold[x]; } // add new array posShapePoints[cur][hold.length] = new Point2D.Double[posPoints[j].length]; for (int x = 0; x < posPoints[j].length; x ++){ posShapePoints[cur][hold.length][x] = posPoints[j][x]; } } } // end not same point } // end searching for overlap } while(anyOver); // through until no overlap // is found }// end if previously not in object } // end joining positive shapes // now create the positive shapes. System.gc(); shapes[Rules.POS] = new GeneralPath[posShapePoints.length]; for (int i = 0; i < posShapePoints.length; i ++){ shapes[Rules.POS][i] = new GeneralPath(); for (int j = 0; j < posShapePoints[i].length; j ++){ for (int l = 1; l < posShapePoints[i][j].length; l ++){ shapes[Rules.POS][i].moveTo(posShapePoints[i][j][0].getX(), posShapePoints[i][j][0].getY()); shapes[Rules.POS][i].lineTo(posShapePoints[i][j][l].getX(), posShapePoints[i][j][l].getY()); } // end for l } // end for j } // end for i // end making positive shapes // join the negative shapes 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; } }