00001 package watershed; 00002 00003 import java.util.ArrayList; 00004 00005 /* 00006 * Watershed algorithm 00007 * 00008 * Copyright (c) 2003 by Christopher Mei (christopher.mei@sophia.inria.fr) 00009 * 00010 * This plugin is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License version 2 00012 * as published by the Free Software Foundation. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this plugin; if not, write to the Free Software 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00022 */ 00023 00066 public class Watershed_Algorithm { 00067 00068 final static int HMIN = 0; 00069 00070 final static int HMAX = 256; 00071 00072 int width, height; 00073 00074 public void run(short[] pixels, int width, int height) { 00075 this.width = width; 00076 this.height = height; 00077 00082 WatershedStructure watershedStructure = new WatershedStructure(pixels, 00083 width, height); 00084 00086 WatershedFIFO queue = new WatershedFIFO(); 00087 int curlab = 0; 00088 00089 int heightIndex1 = 0; 00090 int heightIndex2 = 0; 00091 00092 for (int h = HMIN; h < HMAX; h++) /* 00093 * Geodesic SKIZ of level h-1 inside 00094 * level h 00095 */{ 00096 00097 for (int pixelIndex = heightIndex1; pixelIndex < watershedStructure 00098 .size(); pixelIndex++) /* mask all pixels at level h */{ 00099 WatershedPixel p = watershedStructure.get(pixelIndex); 00100 00101 if (p.getIntHeight() != h) { 00103 heightIndex1 = pixelIndex; 00104 break; 00105 } 00106 00107 p.setLabelToMASK(); 00108 00109 ArrayList neighbours = p.getNeighbours(); 00110 for (int i = 0; i < neighbours.size(); i++) { 00111 WatershedPixel q = (WatershedPixel) neighbours.get(i); 00112 00113 if (q.getLabel() >= 0) {/* 00114 * Initialise queue with neighbours 00115 * at level h of current basins or 00116 * watersheds 00117 */ 00118 p.setDistance(1); 00119 queue.fifo_add(p); 00120 break; 00121 } // end if 00122 } // end for 00123 } // end for 00124 00125 int curdist = 1; 00126 queue.fifo_add_FICTITIOUS(); 00127 00128 while (true) 00129 { 00130 WatershedPixel p = queue.fifo_remove(); 00131 00132 if (p.isFICTITIOUS()) 00133 if (queue.fifo_empty()) { 00134 break; 00135 } else { 00136 queue.fifo_add_FICTITIOUS(); 00137 curdist++; 00138 p = queue.fifo_remove(); 00139 } 00140 00141 ArrayList neighbours = p.getNeighbours(); 00142 for (int i = 0; i < neighbours.size(); i++) /* 00143 * Labelling p by 00144 * inspecting 00145 * neighbours 00146 */{ 00147 WatershedPixel q = (WatershedPixel) neighbours.get(i); 00148 00149 if ((q.getDistance() <= curdist) && (q.getLabel() >= 0)) { 00150 /* q belongs to an existing basin or to a watershed */ 00151 00152 if (q.getLabel() > 0) { 00153 if (p.isLabelMASK()) 00154 // Removed from original algorithm || 00155 // p.isLabelWSHED() ) 00156 p.setLabel(q.getLabel()); 00157 else if (p.getLabel() != q.getLabel()) 00158 p.setLabelToWSHED(); 00159 } // end if lab>0 00160 else if (p.isLabelMASK()) 00161 p.setLabelToWSHED(); 00162 } else if (q.isLabelMASK() && (q.getDistance() == 0)) { 00163 00164 q.setDistance(curdist + 1); 00165 queue.fifo_add(q); 00166 } 00167 } // end for, end processing neighbours 00168 00169 } // end while (loop) 00170 00171 /* Detect and process new minima at level h */ 00172 for (int pixelIndex = heightIndex2; pixelIndex < watershedStructure 00173 .size(); pixelIndex++) { 00174 WatershedPixel p = watershedStructure.get(pixelIndex); 00175 00176 if (p.getIntHeight() != h) { 00178 heightIndex2 = pixelIndex; 00179 break; 00180 } 00181 00182 p.setDistance(0); /* Reset distance to zero */ 00183 00184 if (p.isLabelMASK()) { /* the pixel is inside a new minimum */ 00185 curlab++; 00186 p.setLabel(curlab); 00187 queue.fifo_add(p); 00188 00189 while (!queue.fifo_empty()) { 00190 WatershedPixel q = queue.fifo_remove(); 00191 00192 ArrayList neighbours = q.getNeighbours(); 00193 00194 for (int i = 0; i < neighbours.size(); i++) /* 00195 * inspect 00196 * neighbours 00197 * of p2 00198 */{ 00199 WatershedPixel r = (WatershedPixel) neighbours 00200 .get(i); 00201 00202 if (r.isLabelMASK()) { 00203 r.setLabel(curlab); 00204 queue.fifo_add(r); 00205 } 00206 } 00207 } // end while 00208 } // end if 00209 } // end for 00210 } 00213 byte[] newPixels = new byte[pixels.length]; 00214 00215 for (int pixelIndex = 0; pixelIndex < watershedStructure.size(); pixelIndex++) { 00216 WatershedPixel p = watershedStructure.get(pixelIndex); 00217 00218 if (p.isLabelWSHED() && !p.allNeighboursAreWSHED()) 00219 newPixels[p.getX() + p.getY() * width] = (byte) 255; 00220 } 00221 for (int i = 0; i < pixels.length; i++) 00222 pixels[i] = newPixels[i]; 00223 } 00224 00225 }