import java.awt.event.KeyEvent; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.*; import java.util.Random; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import psychWithJava.FullScreen; import static java.lang.Math.*; public class GaborDetection extends FullScreen implements Runnable{ static final int LEFT = 0; static final int RIGHT = 1; static final int MEAN = 127; static final double CPP = 0.05; static final double PHASE = 0; static final double ORIENTATION = PI/4; static final int SIGMA = 32; static final double INITIAL_CONTRAST = 0.5; static final double DELTA_CONTRAST = 0.05; static final int NOISE_AMPLITUDE = 64; public static void main(String[] args){ GaborDetection gd = new GaborDetection(); gd.setBackground(new Color(MEAN,MEAN,MEAN)); gd.setNBuffers(2); new Thread(gd).start(); } public void run() { try{ hideCursor(); displayText(10,50, "Indicate the location of Gabor patch"); displayText(10,100,"left arrow for LEFT, right arrow for RIGHT"); displayText(10,150,"press ESC to quit"); displayText(10,300,"now press any key to continue"); updateScreen(); getKeyPressed(-1); int correctCount = 0; double contrast = INITIAL_CONTRAST; while(true){ System.out.printf("%3.5f ",contrast); BufferedImage gbr = gabor(MEAN, CPP, contrast, PHASE, SIGMA, ORIENTATION); int position = (int)round(random()); int x; switch(position){ case LEFT: x = getWidth() / 4 - gbr.getWidth() / 2; break; case RIGHT: x = 3 * getWidth()/4 - gbr.getWidth()/2; break; default: x = 0; break; } int y = getHeight()/2 - gbr.getHeight()/2; BufferedImage stimulus = new BufferedImage(getWidth(), getHeight(),BufferedImage.TYPE_BYTE_GRAY); Graphics2D stimG2 = stimulus.createGraphics(); stimG2.setColor(new Color(MEAN,MEAN,MEAN)); stimG2.fillRect(0,0,getWidth(),getHeight()); stimG2.drawImage(gbr,x,y,null); stimG2.dispose(); long ct = System.currentTimeMillis(); stimulus = superposeGaussianNoise(MEAN,NOISE_AMPLITUDE,stimulus); System.out.printf("%d \n", System.currentTimeMillis()-ct); blankScreen(); displayImage(0,0,stimulus); updateScreen(); flushKeyPressed(); int response = getKeyPressed(-1); if((response == KeyEvent.VK_LEFT && position == LEFT) || (response == KeyEvent.VK_RIGHT && position == RIGHT) ){ beep(300,200); correctCount++; System.out.println("success"); if(correctCount == 3){ contrast = max(0,contrast-DELTA_CONTRAST); correctCount = 0; } } else{ beep(3800,200); contrast = min(1,contrast+DELTA_CONTRAST); correctCount = 0; System.out.println("fail"); } blankScreen(); updateScreen(); Thread.sleep(100); } } catch (PixelOutOfRangeException e) { e.printStackTrace(); } catch (LineUnavailableException e) { e.printStackTrace(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } finally { closeScreen(); } } public static BufferedImage gabor(int mean, double cpp, double contrast, double phase, int sigma, double orientation) throws PixelOutOfRangeException { int size = max ( 1, 2 * (int) (sqrt( 2 * log(mean*contrast)) * sigma) ); int[] gPixel = new int[size * size]; int[] tmp = new int[size]; for (int j = 0; j < size; j++) { double x = (j - size / 2); int val = (int) (contrast * mean * sin(phase + x * cpp * 2 * PI)); if ((tmp[j] = val) > 255-mean || tmp[j] < -mean) throw new PixelOutOfRangeException( "Exception in Gabor: calculated pixel value out of range [0,255]"); } for (int i = 0; i < size; i++) for (int j = 0; j < size; j++){ double x2 = (j-size/2) * (j-size/2) + (i-size/2) * (i-size/2); gPixel[i * size + j] = mean + (int)(exp(-x2/(2*sigma*sigma))*tmp[j]); } BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); bi.getRaster().setPixels(0, 0, size, size, gPixel); if(orientation !=0 ){ AffineTransformOp ato = new AffineTransformOp(AffineTransform .getRotateInstance(orientation, (double) size / 2, (double) size / 2), AffineTransformOp.TYPE_BICUBIC); BufferedImage bic = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); Graphics2D bicG = bic.createGraphics(); bicG.setColor(new Color(mean,mean,mean)); bicG.fillRect(0,0,size,size); bicG.dispose(); ato.filter(bi, bic); return bic; } else return bi; } public static BufferedImage superposeGaussianNoise( int mean, int amplitude,BufferedImage bi){ int width = bi.getWidth(); int height = bi.getHeight(); BufferedImage rndMask = new BufferedImage(width,height, BufferedImage.TYPE_BYTE_GRAY); Graphics2D rndMaskG2 = rndMask.createGraphics(); rndMaskG2.drawImage(bi,0,0,null); rndMaskG2.dispose(); int[] pix = new int[width*height]; rndMask.getRaster().getPixels(0,0,width,height,pix); Random rnd = new Random(); for(int i=0; i