PRO RED_POWER, spectrum, job, $ WIDTH=f_width, SECTOR=s_width, $ PS=PS_Print, HOLD=hold, EPS=eps, $ BATCH=batch, LOG=log ;=============================================================================== ; (c) 1990 - khd c/o FU BERLIN. A l l r i g h t s r e s e r v e d. || ; -- No part of this software package may be reproduced, transmitted, || ; 1991 transcribed, stored in a retrieval system, or translated into || ; any form by any means without the w r i t t e n permission of || ; Karl-Heinz Dittberner-FU BERLIN, Arnimallee 22, D-1000 Berlin 33 || ;=============================================================================== ; PRO:RED_POWER.PRO K.-H. Dittberner - 14.OKT.1990 ; V 01.14 P 476/27 - 13.FEB.1991 ; ; IDL(V2.0)-Routine: Reduzierung des 2D-Powerspektrums eines (Pixel-)Bildes ; durch Berechnung und Ausgabe folgender Teil-Powerspektren ; (Projektionen => 1D-Kenngroessen): ; ; o p(r) = 1/nf * SUM(power(r,theta) ueber r (RING) ; o p(th)= 1/nf * SUM(power(r,theta) ueber theta (SECTOR) ; o p(x) = 1/ny * SUM(power(fx,fy) ueber fx (V-STRIP) ; o p(y) = 1/nx * SUM(power(fx,fy) ueber fy (H-STRIP) ; ; wobei power(fx,fy) = |F(fx,fy)|^2 ; mit r = SQRT(fx^2 + fy^2) ; und theta = ATAN(fy/fx) ; folgt power(r,theta) = |F(r,theta)|^2 ; mit nf = nf(r) bzw. nf(th). ; ; Realisiert nach einem Vorschlag aus William K. Pratt: ; "Digital Image Processing", New York: Wiley 1978, S.474f. ; ; Die Ergebnisse werden zusaetzlich in einer (ASCII-)Daten- ; File "job.CHARS" (Characteristics!) abgelegt. ; ; HINWEIS: Die komplexe Eingangs-VAR spectrum muss unmittelbar vor- ; her mit der Routine IMAGE_POWER.PRO (P 476/16) ermittelt ; worden sein. Mit der Eingangs-VAR job wird der Name des ; Jobs festgelegt, z.B. "MAC:FOTO"; auch diese VAR wird von ; der Routine IMAGE_POWER zur Verfuegung gestellt. ; ; KEYWORDS: ; /ABEL = Geplante Transformation. ; /BATCH = Muss angegeben werden, wenn dieses Programm im IDL Batch- ; Mode laufen soll. ; /EPS = Ausgabe der Powerspektren erfolgt als Encapsulated Post- ; Script-File unter dem Namen "job_REDPOWER.EPS" zum Import ; in andere Applikationen, z.B. in den PageMaker. ; /HOLD = Die PostScript-File wird zunaechst nicht gedruckt. Sie ; steht unter dem Namen "job_REDPOWER.PS" zur Verfuegung. ; /LOG = Es werden Zwischeninfos ueber den Berechnungsstand ; ausgegeben. ; /PS = Nur PostScript-Ausgabe; keine Ausgabe auf dem Grafik- ; Terminal. ; SECTOR = Oeffnungswinkel in Grad des Sektors fuer das Torten- ; filter; ganzzahliges Vielfaches muss 360 Grad ergeben. ; Defaultwert ist 22,5 Grad => 16 Sektoren/Vollkreis. ; WIDTH = Bandbreite in cycles/image des Kreisringes fuer das ; Ring-Filter. Defaultwert ist 4 cycles/image. ;=============================================================================== ; Liste der verwendeten Programme der Abt. Wiss. Datenverarbeitung am IfP-FUB: ; ---------------------------------------------------------------------------- ; o P476/2 PRINT_PLOT PostScript-Ausgabe der aktuellen Grafik-File. ; o P476/22 F_MATRIX Erzeugen der quadrat. n x n Frequenz-Matrix. ; o P476/23 RING_FILTER Erzeugen eines Kreisring-Filter (Ideal. Bandpass). ; o P476/24 A_MATRIX Erzeugen der quadrat. n x n Angle-Matrix. ; o P476/25 TORT_FILTER Erzeugen eines Torten(stueck)-Filters (Sektor). ;=============================================================================== ; Quelle: Do-it-yourself! Merkposten: o ; C90 231 o Gesamt-Power ? ; o Kernel ABEL-Transform. klaeren. ; Aufruf: z.B. RED_POWER, spektrum, job o Pkt.11: Ausgabe von ... (dazu). ; [, ...] o ; o FOR i=... schneller machen ? ; o ;=============================================================================== ; Aenderungen: [13/11/90-khd] => V 01.2: ; - Vor-Entwurf vom 14/10/90 IMAGE_SPECTRTA => RED_POWER ; umbenannt. ; [21/11/90-khd] => V 01.3: ; - Pkt.6+7: Berechnung der Powerprojektionen mittels horizon- ; taler und vertikaler Streifen auf die Hauptachsen zugefuegt. ; [23/11/90-khd] => V 01.4: ; - Ueberarbeitet, kommentiert und Keywords implementiert. ; [23/11/90-khd] => V 01.5: ; - Ueberschrift, Titel etc. eingefuehrt. ; [26/11/90-khd] => V 01.6: (Copy => SEIDLER) ; - pth-Berechnung modifiziert: Anfangswinkel ; 0 => - s_width/2; dann liegen die Hauptachse exakt ; in einem Sektor. ; - Plots ueberarbeitet. ; - Ausgabe von pr, pth, px, py in dB; bezogen auf den DC-Wert. ; - Pkt.13 "Ausgabe der Ergebnisse in eine Daten-File" zugefuegt. ; [28/11/90-khd] => V 01.7: (Copy => SEIDLER) ; - ON_ERROR,2 aktiviert. ; - In Pkt.5 VAR s_start eingefuehrt wg. Genauigkeit. ; - Beim Aufruf von RING_FILTER (Pkt.4) + TORT_FILTER (Pkt.5) ; Keyword /HIGH_INCLUDE zur Mitnahme der oberen Grenze ; zugefuegt. ; - Pkt.13: Datenausgabe auf einfache (universelle!) ASCII- ; File umgestellt; Struktur "Image_Chars" hat sich wg. ; unterschiedlicher nr, ns, nx, ny nicht bewaehrt. ; [29/11/90-khd] => V 01.8: (Copy => AG KOE + AG GRUE) ; - Keyword /LOG eingefuehrt; dieses in ; Pkt.4,5,6,7 bei PRINT,... verwendet. ; - Filter muessen ueber dem 2D-Powerspektrum g e n a u ; zentriert werden; dieses in Pkt.4+5 durch Ausstanzen ; und Shiften der Masken zugefuegt. ; - Pkt.11 als Merkposten eingefuehrt. ; [18/12/90-khd] => V 01.9: (Copy => SEIDLER) ; - Im Pkt.4+5 das Ausstanzen der Masken (Filter) geaendert ; wg. der Symmetrie zu nx/2 bzw. ny/2. ; - Bedeutung von /HOLD geaendert; dazu unter Pkt.12 beim ; PRINT_PLOT,... /NOPRINT zugefuegt. ; [30/1/91-khd] => V 01.10/11: (Copy => SEIDLER) ; - Im Pkt.10 VAR file => job umbenannt. ; - Output-Files umbenannt "job.PS/EPS" => "job_REDPOWER.PS/EPS". ; - Bei /EPS erfolgt nunmehr in Pkt.8+10 eine andere Format- ; tierung des Plots, so dass Titel und Untertitel innerhalb ; der PS-BoundingBox liegen und damit sichtbar sind. ; [31/1/91-khd] => V 01.12: ; - Y-Achsen der 4 Plots unten von -80 dB => -90 dB mit ; insgesamt 9 Ticks umgestellt. ; [12/2/91-khd] => V 01.13: ; - Im Pkt.4+5 das Ausstanzen + Zentrieren der Masken erneut ; modifiziert, da Plots von pr und pth noch nicht immer ok. ; - Zur Beschleunigung pth wg. Symmetrie nur bis 180 Grad. ; [13/2/91-khd] => V 01.14: ; - Pkt.13: In *.CHARS-File wird nunmehr nr+1 sowie ns+1 ge- ; schrieben, was fuer AVE_POWER.PRO (P 476/29) besser ist. ;=============================================================================== ; 0. Prolog, Variablen und Konstanten: ;=============================================================================== ; ON_ERROR, 2 ; Return => Ruf. Programm. rand = 50 ; Rand fuer (DEC-)Window in Pixel. w0 = 10 ; Fuer Bezugskoo. des (DEC-)Windows. ok = "" ; Typ-Deklaration. PS_Com = "" ; Typ-Deklaration. PSres = 2540. ; point/inch = ipt/inch werden von ; IDL in PostScript-Ausgaben verwen- ; det; PS-Standard = 72 point/inch ! dim = SIZE(spectrum) IF (dim(0) NE 2) $ THEN MESSAGE, "Es sind nur 2D-Spektren zugelassen." nx = dim(1) ; Pixel-Anzahl in X-Richtung. ny = dim(2) ; Pixel-Anzahl in Y-Richtung. ; ;=============================================================================== ; 1. Behandlung der Keywords (Default-Werte): ;=============================================================================== ; IF NOT KEYWORD_SET(f_width) THEN f_width = 4 ; cycles/image. IF NOT KEYWORD_SET(s_width) THEN s_width = 22.5 ; Grad = Pi/8. IF KEYWORD_SET(eps) AND NOT KEYWORD_SET(PS_Print) $ THEN PS_Print = 1 IF KEYWORD_SET(PS_Print) $ THEN PS_Asked = 1 $ ELSE PS_Asked = 0 IF KEYWORD_SET(hold) AND NOT KEYWORD_SET(PS_Print) $ THEN PS_Print = 1 ; ;=============================================================================== ; 2. Berechnung des Powerspektrums: ;=============================================================================== ; DC = ABS(spectrum(0,0))^2 ; Gleichanteil im Powerspektrums. p0 = ALOG10(DC) power = SHIFT(ABS(spectrum)^2, nx/2, ny/2); Powerspektrum in Bildbereichs- ; darstellung. time = SYSTIME(0) ; Zeitpunkt der Berechnung ; ; festhalten (Creation-Date). ;=============================================================================== ; 3. Datenfelder vorbereiten: ;=============================================================================== ; IF (nx GE ny) $ THEN n = nx $ ; n fuer RING_FILTER und ELSE n = ny ; TORT_FILTER. nr = n/(2.*f_width) ; Anzahl der Ringe. ns = 180./s_width ; Anzahl der Sektoren. pr = FLTARR(nr+1) ; + 1 wg. DC-Wert => Ring 0. pth = FLTARR(ns+1) ; + 1 wg. Wert bei 180 Grad. px = FLTARR(nx/2) py = FLTARR(ny/2) nf_r = LONARR(nr+1) ; Anzahl der nf_th = LONARR(ns+1) ; Frequenzwerte. ; ;=============================================================================== ; 4. Berechnung der Funktion pr = p(r) = Ring ueber power(fx,fy): ;=============================================================================== ; f_center = f_width/2 pr(0) = DC nf_r(0) = 1L FOR i = 1, nr DO $ BEGIN bandpass = RING_FILTER( n, f_center + (i-1)*f_width, f_width, $ /IMAGE, /HIGH_INCLUDE) bandpass = bandpass( (n/2-nx/2):(n/2+nx/2-1), $ (n/2-ny/2):(n/2+ny/2-1)) ; Maske ausstanzen. bandpass(0,*) = 0 & bandpass(*,0) = 0 ; Maske zentrieren. index = WHERE(bandpass, nf) ; nf => Anzahl der moeglichen power_part = power * bandpass ; Frequenzorte. pr(i) = TOTAL(power_part(index))/nf ; Summe aller Amplituden im nf_r(i) = nf ; Kreisring/nf => Mittelwert. IF KEYWORD_SET(log) $ THEN PRINT, "Ring ", i, " von ", FIX(nr) ENDFOR pr = 10.*(ALOG10(pr) - ALOG10(DC)) ; In Dezibel. r = FINDGEN(nr+1) * f_width ; x-Achse. ; ;=============================================================================== ; 5. Berechnung der Funktion pth = p(theta) = Sektor ueber power(fx,fy): ;=============================================================================== ; FOR i = 0, ns DO $ BEGIN s_start = (FLOAT(i) - 0.5) * s_width sector = TORT_FILTER( n, s_start, s_width, $ /IMAGE, /HIGH_INCLUDE) sector = sector( (n/2-nx/2):(n/2+nx/2-1), $ (n/2-ny/2):(n/2+ny/2-1)) ; Maske ausstanzen. sector(0,*) = 0 & sector(*,0) = 0 ; Maske zentrieren. index = WHERE(sector, nf) ; nf => Anzahl der moeglichen power_part = power * sector ; Frequenzorte. pth(i) = TOTAL(power_part(index))/nf ; Summe aller Amplituden im nf_th(i) = nf ; Sektor/nf => Mittelwert. IF KEYWORD_SET(log) $ THEN PRINT, "Sektor ", i+1, " von ", FIX(ns) ENDFOR pth = 10.*(ALOG10(pth) - ALOG10(DC)) ; In Dezibel. th = FINDGEN(ns+1) * s_width ; x-Achse. ; ;=============================================================================== ; 6. Berechnung der Funktion px = p(x) = Vertikaler Streifen ueber power(fx,fy): ;=============================================================================== ; FOR i = 0, nx/2-1 DO $ BEGIN px(i) = TOTAL(power(i+nx/2,*))/ny ; Summe aller Amplituden im IF KEYWORD_SET(log) $ ; V-Strip/ny => Mittelwert. THEN PRINT, "V-Strip ", i+1, " von ", nx/2 ENDFOR px = 10.*(ALOG10(px) - ALOG10(DC)) ; In Dezibel. x = FLOAT([0, nx/2]) ; x-Achsenbereich. ; ;=============================================================================== ; 7. Berechnung der Funktion py = p(y) = Horizont. Streifen ueber power(fx,fy): ;=============================================================================== ; FOR i = 0, ny/2-1 DO $ BEGIN py(i) = TOTAL(power(*,i+ny/2))/nx ; Summe aller Amplituden im IF KEYWORD_SET(log) $ ; H-Strip/nx => Mittelwert. THEN PRINT, "H-Strip ", i+1, " von ", ny/2 ENDFOR py = 10.*(ALOG10(py) - ALOG10(DC)) ; In Dezibel. y = FLOAT([0, ny/2]) ; x-Achsenbereich. ; ;=============================================================================== ; 8. Transformation der Funktion pr = p(r) nach ABEL: ;=============================================================================== ; ; GEPLANT! ; ;=============================================================================== ; 9. Setzen von Parametern fuer die folgenden Ausgaben: ;=============================================================================== ; Power_Output: wx = 2 * nx + 3 * rand ; Groesse des (DEC-)Windows wy = 2 * ny + 3 * rand ; = Fenster auf dem Schirm. ;_______________________________________________________________________________ !X.CHARSIZE = 0.9 & !Y.CHARSIZE = 0.9 !P.TICKLEN = -0.03 !X.TICKS = 2 & !Y.TICKS = 3 !X.MINOR = 4 & !Y.MINOR = 3 Plot_Oben = 4.5 & Plot_Unten = 0.5 ; Nur fuer PostScript; Plot_Rand = 1.5 & Plot_Logo = 2.0 ; alle Zahlenangaben Plot_VSize = 6.0 & Plot_HSize = 6.0 ; in Inches. Plot_Shift = Plot_Logo/2. Shift = FIX(Plot_Shift * PSres) Shift = STRCOMPRESS(Shift, /REMOVE) ;_______________________________________________________________________________ Titel = "Log. Teil-Powerspektren von " + job Window_Titel = "Log. Teil-Powerspektren" ;_______________________________________________________________________________ ; Je nach Ausgabe-Art unterschied- IF KEYWORD_SET(PS_Print) $ ; lich zu setzende Parameter: THEN BEGIN ; Bei PostScript-Ausgabe: x_Titel_pr = "f / [cycles/image]" x_Titel_pth = "theta / degree" x_Titel_px = "f!Ix!N / [cycles/image]" x_Titel_py = "f!Iy!N / [cycles/image]" y_Titel_pr = "p!Ir!N / dB" y_Titel_pth = "p!Itheta!N / dB" y_Titel_px = "p!Ix!N / dB" y_Titel_py = "p!Iy!N / dB" SubTitel = "n!Ix!N = " + STRCOMPRESS(nx,/REMOVE) + " pixel;" + $ " n!Iy!N = " + STRCOMPRESS(ny,/REMOVE) + " pixel;" + $ " 0 dB: p(0,0) = " + STRCOMPRESS(DC,/REMOVE) ENDIF $ ELSE BEGIN ; Keine PostScript-Ausgabe: x_Titel_pr = "f / [cycles/image]" x_Titel_pth = "theta / degree" x_Titel_px = "fx / [cycles/image]" x_Titel_py = "fy / [cycles/image]" y_Titel_pr = "pr / dB" y_Titel_pth = "ptheta / dB" y_Titel_px = "px / dB" y_Titel_py = "py / dB" SubTitel = "nx = " + STRCOMPRESS(nx,/REMOVE) + " pixel;" + $ " ny = " + STRCOMPRESS(ny,/REMOVE) + " pixel;" + $ " 0 dB: p(0,0) = " + STRCOMPRESS(DC,/REMOVE) ENDELSE ; ;=============================================================================== ; 10. Ausgabe der berechneten Funktionen: ;=============================================================================== ; IF KEYWORD_SET(batch) OR (PS_Asked EQ 1) THEN GOTO, Do_Plot WINDOW, XPOS=w0, YPOS=w0, $ ; Neues Fenster erzeugen. XSIZE=wx, YSIZE=wy, $ RETAIN=2, /FREE, $ TITLE=Window_Titel LOADCT, 0, /SILENT ; Laden der Color-Table: Lin. Grau. ;_______________________________________________________________________________ Do_Plot: IF KEYWORD_SET(PS_Print) $ ; Bei PostScript-Ausgabe: THEN BEGIN OldDevice = !D.NAME SET_PLOT, "PS", /COPY IF KEYWORD_SET(eps) $ THEN DEVICE, /ENCAPSULATED, FILENAME=job + "_REDPOWER.EPS", $ XSIZE=Plot_HSize, YSIZE=Plot_VSize + Plot_Logo, $ /INCHES, /TIMES, /ITALIC, FONT_SIZE=10 $ ELSE DEVICE, XOFFSET=Plot_Rand, YOFFSET=Plot_Oben, $ XSIZE =Plot_HSize, YSIZE =Plot_VSize, /INCHES, $ /TIMES, /ITALIC, FONT_SIZE=10 ENDIF ;KW_S(PS_Print) ;_______________________________________________________________________________ !P.MULTI = [0,2,2,0,1] ; Clear Page, 4 Plots/Plot-Region. IF KEYWORD_SET(eps) $ THEN BEGIN Scale = Plot_VSize/(Plot_VSize + Plot_Logo) Scale = STRCOMPRESS(Scale, /REMOVE) PS_Com = '0 ' + Shift + ' translate ' + $ '1.0000 ' + Scale + ' scale' PLOT, [0,0], [1,1], /NODATA, $ ; Dummy wg. des PS-Befehls; sonst XSTYLE=4, YSTYLE=4 ; erfolgt neues PS-PageSetup. DEVICE, OUTPUT=PS_Com ; Direkter PostScript-Befehl. !P.MULTI = [4,2,2,0,1] ; Reset => 4 Plots/Plot-Region. ENDIF PLOT, r, pr, FONT=0, $ ; 1. Plot: power(r) YRANGE=[-90., 0.], $ XSTYLE=1, YSTYLE=1, $ XTITLE=x_Titel_pr, $ YTITLE=y_Titel_pr PLOT, th, pth, FONT=0, $ ; 2. Plot: power(theta) YRANGE=[-90., 0.], $ XSTYLE=1, YSTYLE=1, $ XTITLE=x_Titel_pth, $ YTITLE=y_Titel_pth PLOT, px, FONT=0, $ ; 3. Plot: power(x) XRANGE=x, YRANGE=[-90., 0.], $ XSTYLE=1, YSTYLE=1, $ XTITLE=x_Titel_px, $ YTITLE=y_Titel_px PLOT, py, FONT=0, $ ; 4. Plot: power(y) XRANGE=y, YRANGE=[-90., 0.], $ XSTYLE=1, YSTYLE=1, $ XTITLE=x_Titel_py, $ YTITLE=y_Titel_py ;_______________________________________________________________________________ IF KEYWORD_SET(PS_Print) $ ; Titel ueber Plot-Mitte zentriert: THEN IF KEYWORD_SET(eps) $ THEN DEVICE, /TIMES, /BOLD, /ITALIC, FONT_SIZE=16 $ ELSE DEVICE, /TIMES, /BOLD, /ITALIC, FONT_SIZE=12 XYOUTS, 0.5, 1.10, /NORM, Titel, ALIGNMENT=0.5, FONT=0 IF KEYWORD_SET(PS_Print) $ ; Untertitel und Creation-Date THEN BEGIN ; (nur bei PostScript-Ausgabe): IF KEYWORD_SET(eps) $ THEN DEVICE, /TIMES, FONT_SIZE=12 $ ELSE DEVICE, /TIMES, FONT_SIZE=9 XYOUTS, 0.5, 1.05, /NORM, "Creation-Date: " + time, $ ALIGNMENT=0.5, FONT=0 XYOUTS, 0.5, -0.08, /NORM, SubTitel, ALIGNMENT=0.5, FONT=0 ENDIF ;_______________________________________________________________________________ !P.MULTI = 0 ; Reset => 1 Plot/Plot-Region. ; ;=============================================================================== ; 11. Ausgabe ... ;=============================================================================== ; ; ;=============================================================================== ; 12. Ausgabe der PostScript-File der Teil-Powerspektren: ;=============================================================================== ; IF NOT PS_Asked $ THEN BEGIN PS_Asked = 1 PRINT, FORMAT='($, "o Sollen diese Spektren gedruckt werden ? [N]")' READ, ok & ok = STRUPCASE(ok) IF (ok EQ "Y") OR (ok EQ "YES") OR (ok EQ "J") OR (ok EQ "JA") $ THEN BEGIN PS_Print = 1 GOTO, Power_Output ; Am Anfang von Pkt.9. ENDIF ENDIF ;_______________________________________________________________________________ IF KEYWORD_SET(PS_Print) $ THEN BEGIN IF KEYWORD_SET (eps) $ THEN DEVICE, /CLOSE_FILE $ ; EPS-File schliessen. ELSE IF KEYWORD_SET(hold) $ THEN PRINT_PLOT, job + "_REDPOWER.PS", /NOPRINT $ ELSE PRINT_PLOT ; PS-Ausgabe der Spektren. SET_PLOT, OldDevice ENDIF ;KW_S(PS_Print) ; ;=============================================================================== ; 13. Ausgabe der Ergebnisse in eine Daten-File: ;=============================================================================== ; ON_IOERROR, IO_Error OPENW, Out, job + ".CHARS", /GET_LUN ; Oeffnen der neuen Daten-File. PRINTF, Out, job, " ", time & PRINTF, Out, "" PRINTF, Out, LONG(nr+1), LONG(ns+1), nx, ny & PRINTF, Out, "" PRINTF, Out, nf_r & PRINTF, Out, "" PRINTF, Out, nf_th & PRINTF, Out, "" PRINTF, Out, f_width, s_width, DC, p0 & PRINTF, Out, "" PRINTF, Out, pr & PRINTF, Out, "" PRINTF, Out, pth & PRINTF, Out, "" PRINTF, Out, px & PRINTF, Out, "" PRINTF, Out, py & PRINTF, Out, "" GOTO, Ende ; ;=============================================================================== ; 14. Schluss: ;=============================================================================== ; IO_Error: ON_IOERROR, NULL ; Reset der Fehlerverzweigung. PRINT, !ERR_STRING Ende: FREE_LUN, Out ; Schliessen der Daten-File. RETURN END ;===============================================================================