/** * */ 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. * * 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 ContOrientSens { // flags to indicate locations checked private boolean [][] checked; // rule parameters double threshMax = 15; // the connection strength // threshold. // routine to add to list of found shapes AddShape add = new AddShape(); // rule name public final static String NAME = "Contiguous Orientation Sensitive"; // 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][]; shapes[0] = null; shapes[1] = null; // individual object that is found GeneralPath shape = new GeneralPath(); // 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){ shape = new GeneralPath(); shape.moveTo(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 ++){ if (!(i ==1 & j==1)){ // don't check own potions 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't check own potions } // end for j } // end for i // to be used, point must connect to one other point // if (maxI.length < 2){ // maxI = null; // } // 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 ++){ shape.lineTo(rfArray[y+maxJ[i]][x+maxI[i]].getCenterX(), rfArray[y+maxJ[i]][x+maxI[i]].getCenterY()); shape.moveTo(rfArray[y][x].getCenterX(), rfArray[y][x].getCenterY()); // return to center } if (pos){ shapes[0] = add.addShape(shapes[0], shape); } else { shapes[1] = add.addShape(shapes[1],shape); } } } // end if there is an orientation } // end for y }// end for x // return the collection return shapes; } }