;+ ; NAME: ; TM_WSHE1 ; ; PURPOSE: ; Die Funktion berechnet die Wasserscheiden fuer ein Bild beliebiger ; Groesse ; ; CATEGORY: ; ; Mathematische Morphologie ; ; CALLING SEQUENCE: ; ; Result = TM_WSHE1(image,MASK=mask,/FOUR,/DISPLAY,/FLOW,/TIME) ; ; INPUTS: ; Image: Das Bild, fuer das die Wasserscheiden berechnet werden sollen ; ; KEYWORD PARAMETERS: ; ; /MASK: Die Wasserscheiden werden nur fuer die Maske berechnet ; ; /FOUR: Es wird nur vierer Nachbarschaft betrachtet. Ist dieser Schalter ; nicht gesetzt, wird achter Nachbarschaft bearbeitet. ; ; /DISPLAY: Ein Fenster wird geoeffnet, um den Input/Output anzuzeigen ; /CLEAR: Bei DISPLAY wird das Fenster wieder geloescht ; ; /FLOW: Schalter um die Schritte der Flutung synchron ausgeben ; zu lassen ; ; /TIME: Wenn der Schalter gesetzt ist, wird nach der Berechnung ; die dafuer benoetigte Zeit ausgegeben ; /VERBOSE: Ein geschwaetziger Ablauf ; ; ; OUTPUTS: ; ; Es wird ein Bild in gleicher Groesse zurueckgegeben, das die Regionen, ; die berechnet wurden, enthaelt. (Der Rand ist immer -1 gesetzt!!!) ; ; ERROR bei falscher MASK Angabe:[B ; Falls eine Maske angegeben wird, die keinen Bildpunkt mit ; dem minimalen Grauwert des ganzen Bildes enthaelt, kann keine ; Wasserscheide bestimmt werden: ; Fehlerrueckgabe = -1 ; ; EXAMPLE: ; ; a = tm_wshe1(Bild,Mask=mask) ; ; a enthaelt ein Bild, das die Regionen der Wasserscheiden der Maske ; des Bildes 'Bild' enthaelt, bezogen auf die vierer-Nachbarschaft ; ; ; b = tm_wshe1(Bild,/EIGHT,/DISPLAY) ; ; b enthaelt ein Bild, das die Regionen der Wasserscheiden des Bildes ; 'Bild' enthaelt, bezogen auf die achter-Nachbarschaft. Zusaetzlich ; wird das Eingabebild und b nebeneinander ausgegeben. ; ; ; ; MODIFICATION HISTORY: ; Written by: Thomas Mick, 19.06.1996 ; ; Last modified: 19.06.1996, 396.356mal. ; Last modified: 28.06.1996, 17undvier mal von Ro ; Last modified: 09.07.97, 3d extension, functions inlined Ro ; ; ; Der Algorithmus wurde abgekupfert von LUC VINCENT und PIERRE SOILLE, ; die ihn in der Veroeffentlichung ; ; "Watersheds in digital spaces: An Efficient ; Algorithm Based on Immersion Simulations" ; ; (Recognitions on Pattern Analysis and Machine Intelligence, ; Vol.13,No.6,June 1991) ; ; ; publik gemacht haben. Danke, Jungs!. Dank gilt auch meiner Mutter, ; die mich unermuedlich unterstuetzt, mir in Zeiten der Verzweiflung ; eine rettende Hand und in Zeiten des Hungers einen Geldschein fuer ; eine warme Suppe hingehalten hat, es aber im Endeffekt doch nicht ; geschafft hat, mir beizubringen, wie ich mir die Schuhe binden kann. ; ; Special thanks fuer die musikalische Unterstuetzung von den Gruppen ; K's choice und Garbage. Dieses Programm ist nicht unter ; ; http://www.sex.com ; ; dokumentiert. Gruesse auch an Mahadma Ghandi und nicht (ausdruecklich ; nicht!!!) an den Papst. Besondere Gruesse an Douglas Adams: mach's ; gut und danke fuer den Fisch. ; ; ;******************************************************************************* ;- FUNCTION tm_wshe1, imi, FOUR=nba, MASK=msk, $ DISPLAY=disp, FLOW=flo, TIME=time, $ VERBOSE=verb, CLEAR=clear t1 = systime(1) mask = -2l wshed = 0l init = -1l current_label = 0l current_dist = 0l queue = -1l fict_pixel = -2l hilf = size(imi) size_spalte = hilf(1) size_zeile = hilf(2) dimen = hilf[0] CASE dimen OF 1: BEGIN diff=[1l, -1l] imo = make_array(size_spalte, /long, value=init) imd = bytarr(size_spalte) hmin = min(imi[1:size_spalte-2],max=hmax) zw = fix(imi) zw[0] = -1 & zw[size_spalte-1] = -1 END 2: BEGIN IF keyword_set(nba) THEN $ ; Four neighbours diff=[1l, size_spalte, -1l, -size_spalte] $ ELSE $ ; Eight Neighbors diff=[ 1l, size_spalte+1l, size_spalte, size_spalte-1l, $ -1l, -size_spalte-1l, -size_spalte, -size_spalte+1l] imo = make_array(size_spalte,size_zeile, /long, value=init) imd = bytarr(size_spalte,size_zeile) hmin = min(imi[1:size_spalte-2,1:size_zeile-2],max=hmax) zw = fix(imi) zw[0,*] = -1 & zw[size_spalte-1,*] = -1 zw[*,0] = -1 & zw[*,size_zeile-1 ] = -1 END 3: BEGIN nsz = size_spalte*size_zeile IF keyword_set(nba) THEN $ ; Six neighbors diff=[1l, size_spalte, -1l, -size_spalte, nsz, -nsz] $ ELSE $ ; Twentysix neighbors diff=[ 1l, size_spalte+1l, size_spalte, size_spalte-1l, $ -1l, -size_spalte-1l, -size_spalte, -size_spalte+1l, $ nsz, $ nsz+1l, size_spalte+1l+nsz, size_spalte+nsz, size_spalte-1l+nsz, $ nsz-1l,-size_spalte-1l+nsz,-size_spalte+nsz,-size_spalte+1l+nsz, $ -nsz, $ -nsz+1l, size_spalte+1l-nsz, size_spalte-nsz, size_spalte-1l-nsz, $ -nsz-1l,-size_spalte-1l-nsz,-size_spalte-nsz,-size_spalte+1l-nsz] size_depth = hilf[3] imo = make_array(size_spalte, size_zeile, size_depth, /long, value=init) imd = bytarr(size_spalte, size_zeile, size_depth) hmin = min(imi[1:size_spalte-2,1:size_zeile-2,1:size_depth-2],max=hmax) zw = fix(imi) zw[0,*,*] = -1 & zw[size_spalte-1,*,*] = -1 zw[*,0,*] = -1 & zw[*,size_zeile-1 ,*] = -1 zw[*,*,0] = -1 & zw[*,*,size_depth-1 ] = -1 END ELSE: message,'Wrong dimension of input' ENDCASE nbanz = n_elements(diff)-1 IF (keyword_set(disp) OR keyword_set(flo)) THEN BEGIN IF (disp EQ 1) THEN window,/free,Title='Output Watershed', $ xsize=size_spalte, ysize=size_zeile $ ELSE wset, disp IF (dimen EQ 2) THEN tvscl,imi ELSE tvscl,imi[*,*,size_depth/2] ENDIF IF keyword_set(msk) THEN zw=temporary(zw)*msk-(msk EQ 0) h = histogram(temporary(zw), reverse_ind=r, min=fix(hmin), max=fix(hmax)) IF keyword_set(verb) THEN FOR l = 0, r[0]-2 DO $ IF (r[l] NE r[l+1]) THEN print, l, imi[r[r[l]]], r[l+1]-r[l] IF keyword_set(verb) THEN print,systime(1)-t1," sec. elapsed" ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * FOR l = 0, r[0]-2 DO IF (r[l] NE r[l+1]) THEN BEGIN p = r[r[l]:r[l+1]-1] panz = n_elements(p)-1 FOR k = 0l, panz DO BEGIN imo[p[k]] = mask ; nb=where(imo(nachbar(p(k))) ge 0,cnb) nb = where(imo[replicate(p[k],n_elements(diff)) + diff] GE 0,cnb) IF (cnb NE 0) THEN BEGIN imd[p[k]] = 1 ; fifo_add,p(k) IF (n_elements(queue) EQ 1) THEN queue = [p[k],-1] $ ELSE queue = [queue[0:n_elements(queue)-2],p[k],-1] ENDIF ENDFOR ; for k=0l,panz current_dist = 1 ; fifo_add,fict_pixel IF (n_elements(queue) EQ 1) THEN queue = [fict_pixel,-1] $ ELSE queue = [queue[0:n_elements(queue)-2],fict_pixel,-1] start: ;repeat ; fifo_first,pix pix = queue[0] queue = queue[1:n_elements(queue)-1] IF (pix EQ fict_pixel) THEN IF (n_elements(queue) EQ 1) THEN GOTO, ende $ ELSE BEGIN ; fifo_add,fict_pixel IF (n_elements(queue) EQ 1) THEN queue = [fict_pixel,-1] $ ELSE queue = [queue[0:n_elements(queue)-2],fict_pixel,-1] current_dist = current_dist+1 ; fifo_first,pix pix = queue[0] queue = queue[1:n_elements(queue)-1] ENDELSE ; nachbarn (pix) nb = replicate(pix,n_elements(diff))+diff FOR i=0l,nbanz DO BEGIN imdnbi = imd[nb[i]] imonbi = imo[nb[i]] imopix = imo[pix] IF (imdnbi LT current_dist) AND (imonbi GE 0) THEN BEGIN IF (imonbi GT 0) THEN BEGIN IF (imopix EQ mask) OR (imopix EQ wshed) THEN imo[pix] = imonbi $ ELSE IF (imopix NE imo[nb[i]]) THEN imo[pix] = wshed ENDIF ELSE IF (imopix EQ mask) THEN imo[pix] = wshed ENDIF ELSE IF (imonbi EQ mask) AND (imdnbi EQ 0) THEN BEGIN imd[nb[i]] = current_dist+1 ; fifo_add,nb(i) IF (n_elements(queue) EQ 1) THEN queue = [nb[i],-1] $ ELSE queue = [queue[0:n_elements(queue)-2],nb[i],-1] ENDIF ENDFOR ; for i=0,nbanz GOTO, start ende: ;repeat FOR k = 0l, panz DO BEGIN imd[p[k]] = 0 IF (imo[p[k]] EQ mask) THEN BEGIN current_label = current_label+1 ; fifo_add,p(k) IF (n_elements(queue) EQ 1) THEN queue = [p[k], -1] $ ELSE queue = [queue[0:n_elements(queue)-2], p[k], -1] imo[p[k]] = current_label WHILE (n_elements(queue) GT 1) DO BEGIN ; fifo_first ; nachbarn nb = replicate(queue[0],n_elements(diff))+diff queue = queue[1:n_elements(queue)-1] FOR g = 0l, nbanz DO BEGIN IF (imo[nb[g]] EQ mask) THEN BEGIN ; fifo_add,nb(g) IF (n_elements(queue) EQ 1) THEN queue = [nb[g], -1] $ ELSE queue = [queue[0:n_elements(queue)-2], nb[g], -1] imo[nb[g]]=current_label ENDIF ENDFOR ; for g= nbanz ENDWHILE ; while ENDIF ; if imo(p(k)) eq mask ENDFOR ; for k=panz IF keyword_set(flo) THEN $ IF (dimen EQ 2) THEN tvscl,imo $ ELSE tvscl,imo[*,*,size_depth/2] IF keyword_set(verb) THEN $ print,l,':',imi[r[r[l]]],r[l+1]-r[l], $ (systime(1)-t1)/(r[l+1]-r[0]), systime(1)-t1," sec. elapsed" ENDIF ; for l=0,n_elements(wo_wechsel) do if IF keyword_set(time) THEN print,systime(1)-t1," sec. elapsed" IF keyword_set(disp) THEN $ IF (dimen EQ 2) THEN tvscl,imo $ ELSE tvscl,imo[*,*,size_depth/2] IF (keyword_set(disp) AND keyword_set(clear)) THEN IF (disp EQ 1) THEN wdelete RETURN, imo ;******************************************************************************* END ;MAIN