/* Statistical Region Merging in Java: SRMj by Frank Nielsen and Richard Nock ***Caution: This is the simplest implementation*** Java Applet, May 2006. (Version 1.0 : 6 May 2006) For more, check: Richard Nock, Frank Nielsen: Statistical Region Merging. IEEE Trans. Pattern Anal. Mach. Intell. 26(11): 1452-1458 (2004) Find more in the "Visual Computing: Geometry, Graphics, and Vision" book: http://www.csl.sony.co.jp/person/nielsen/visualcomputing/ */ import java.awt.*; import java.applet.*; import java.awt.event.*; import java.awt.image.*; import java.util.StringTokenizer; import java.net.*; public class Srmjava extends Applet { // Input image Image img; PixelGrabber pg; // Ouput segmented image Image imgseg; // Input image (URL or not) String filenameimg; String filenameimgurl; URL imgurl; // Applet dimension int appletw, appleth; Font helveticafont1; Font helveticafont2; // // For SRM // int[] raster; int[] rastero; int w,h,n; double aspectratio; double Q; UnionFind UF; double g; // number of levels in a color channel double logdelta; // Auxilliary buffers for union-find operations int []N; double []Ravg; double [] Gavg; double [] Bavg; int [] C; // the class number // number of pixels that define a "small region" to be collapsed int smallregion; int borderthickness; // // GUI // TextArea messageArea; Label title; InputPanel inputPanel; ImageCanvas imageCanvas; public void init() { System.out.println("Welcome to SRMj (Frank Nielsen - May 2006) ! Initializing the applet."); Dimension dim= this.getSize(); appletw=dim.width; appleth=dim.height; helveticafont1=new Font("Helvetica", Font.BOLD, 18); helveticafont2=new Font("Helvetica", Font.ITALIC, 40); setLayout(new BorderLayout()); inputPanel = new InputPanel(this); inputPanel.setSize(appletw, 200); add("North", inputPanel); imageCanvas = new ImageCanvas(this); imageCanvas.setSize(appletw, appleth-260); add("Center", imageCanvas); messageArea = new TextArea("", 3, 1); messageArea.setEditable(false); messageArea.setBackground(Color.white); add("South", messageArea); filenameimg=getParameter("img"); filenameimgurl=getParameter("imgurl"); System.out.println("IMG TAG="+filenameimg+"\nIMGURL TAG="+filenameimgurl); if (filenameimgurl!=null) { System.out.println("Opening image at URL:"+filenameimgurl); try{ imgurl = new java.net.URL(filenameimgurl); } catch(Exception e){ System.out.println("URL Error..."); e.printStackTrace(); } img = getImage(imgurl); } else { // Assume image is in the same directory img = getImage(getDocumentBase(),filenameimg); } Q=32; g=256.0; borderthickness=0; // border thickness of regions // // Require a valid image for proceeding // if (img!=null) { pg = new PixelGrabber(img, 0 , 0 , -1 , -1 , true); try { pg.grabPixels(); } catch (InterruptedException e) { } raster= (int[])pg.getPixels(); w=pg.getWidth(); h=pg.getHeight(); aspectratio=(double)h/(double)w; n=w*h; logdelta = 2.0*Math.log(6.0*n); // small regions are less than 0.1% of image pixels smallregion=(int)(0.001*n); // One round of segmentation OneRound(); messageArea.setText("R. Nock, F. Nielsen: Statistical Region Merging. IEEE Trans. Pattern Anal. Mach. Intell. 26(11): 1452-1458 (2004)\nF. Nielsen: Visual Computing: Geometry, Graphics, and Vision. Charles River Media: ISBN: 1584504277 (2005)\nAdjust parameter Q with the scrollbar and press the `Segment' button to segment again."); } else { messageArea.setText("R. Nock, F. Nielsen: Statistical Region Merging. IEEE Trans. Pattern Anal. Mach. Intell. 26(11): 1452-1458 (2004)\nF. Nielsen: Visual Computing: Geometry, Graphics, and Vision. Charles River Media: ISBN: 1584504277 (2005)\n!!! ERROR: COULD NOT READ IMAGE LOCATION FROM APPLET TAGS !!!"); } } // End of applet initialization void OneRound() { UF=new UnionFind(n); Ravg=new double[n]; Gavg=new double[n]; Bavg=new double[n]; N=new int[n]; C=new int[n]; rastero=new int[n]; InitializeSegmentation(); FullSegmentation(); ImageProducer ip = new MemoryImageSource( pg.getWidth() , pg.getHeight() , rastero , 0 , pg.getWidth()); this.imgseg = createImage(ip); } void InitializeSegmentation() { // // Initialization // int x,y,red,green,blue,index; for (y = 0; y < h; y++) { for (x = 0; x < w ; x++) { index=y*w+x; red = (raster[y * w+ x] & 0xFF) ; green = ((raster[y *w+ x] & 0xFF00) >> 8); blue = ((raster[y *w + x] & 0xFF0000) >> 16); Ravg[index]=red; Gavg[index]=green; Bavg[index]=blue; N[index]=1; C[index]=index; } } } void FullSegmentation() { Segmentation(); MergeSmallRegion(); OutputSegmentation(); DrawBorder(); } double min(double a, double b) { if (ab) return a; else return b; } double max3(double a,double b,double c) { return max(a,max(b,c)); } boolean MergePredicate(int reg1, int reg2) { double dR, dG, dB; double logreg1, logreg2; double dev1, dev2, dev; dR=(Ravg[reg1]-Ravg[reg2]); dR*=dR; dG=(Gavg[reg1]-Gavg[reg2]); dG*=dG; dB=(Bavg[reg1]-Bavg[reg2]); dB*=dB; logreg1 = min(g,N[reg1])*Math.log(1.0+N[reg1]); logreg2 = min(g,N[reg2])*Math.log(1.0+N[reg2]); dev1=((g*g)/(2.0*Q*N[reg1]))*(logreg1 + logdelta); dev2=((g*g)/(2.0*Q*N[reg2]))*(logreg2 + logdelta); dev=dev1+dev2; return ( (dR> 8) ; b1=((raster[index] & 0xFF0000) >> 16); r2=raster[index+1] & 0xFF; g2= ((raster[index+1] & 0xFF00) >> 8) ; b2=((raster[index+1] & 0xFF0000) >> 16); order[cpair].diff=(int)max3(Math.abs(r2-r1),Math.abs(g2-g1),Math.abs(b2-b1)); cpair++; // C4 below order[cpair]=new Rmpair(); order[cpair].r1=index; order[cpair].r2=index+w; r2=raster[index+w] & 0xFF; g2= ((raster[index+w] & 0xFF00) >> 8) ; b2=((raster[index+w] & 0xFF0000) >> 16); order[cpair].diff=(int)max3(Math.abs(r2-r1),Math.abs(g2-g1),Math.abs(b2-b1)); cpair++; } } // // The two border lines // for(i=0;i> 8) ; b1=((raster[index] & 0xFF0000) >> 16); r2=raster[index+w] & 0xFF; g2= ((raster[index+w] & 0xFF00) >> 8) ; b2=((raster[index+w] & 0xFF0000) >> 16); order[cpair].diff=(int)max3(Math.abs(r2-r1),Math.abs(g2-g1),Math.abs(b2-b1)); cpair++; } for(j=0;j> 8) ; b1=((raster[index] & 0xFF0000) >> 16); r2=raster[index+1] & 0xFF; g2= ((raster[index+1] & 0xFF00) >> 8) ; b2=((raster[index+1] & 0xFF0000) >> 16); order[cpair].diff=(int)max3(Math.abs(r2-r1),Math.abs(g2-g1),Math.abs(b2-b1)); cpair++; } System.out.println("Sorting all "+cpair+" edges using BucketSort"); // // Sort the edges according to the maximum color channel difference // order=BucketSort(order,npair); // Main algorithm is here!!! System.out.println("Testing the merging predicate in a single loop"); for(i=0;i=0)&&(index rank[y]) {parent[y]=x; return x;} else { parent[x]=y;if (rank[x]==rank[y]) rank[y]++;return y;} } } // // An edge: two indices and a difference value // class Rmpair { int r1,r2; int diff; Rmpair() { r1=0; r2=0; diff=0; } }