var {global } FilterSize: real; {0-100% of image size} TransitionWidth: real; {0-100% of filter radius} PlotFilter: boolean; macro 'FFT [F]'; begin fft('foreward'); end; macro 'Abitrary Selection FFT [A]'; var pid1, pid2, x, y, w,h, size: integer; scale: real; begin GetRoi(x, y, w, h); if w = y then begin SelectAll; GetRoi(x, y, w, h); end; if w > h then begin x := x + (w - h) div 2; w := h; MakeRoi(x, y, w, h»); end; if h > w then begin y := y+ (h - w) div 2; h := w; MakeRoi(x, y, w, h); end; size := 2048; if w <= 32 then size := 32 else if w <= 64 then size := 64 else if w <= 128 then size := 128 else if w <= 256 then size := 256 else if w <= 512 then size := 512 else if w <= 1024 then size := 1024; scale := size / w; SetScaling('Bilinear; New Window'); ScaleAndRotate(scale, scale, 0); pid1 := pidNumber; fft('foreward'); pid2 := pidNumber; SelectPic(pid1); dispose; SelectPic(pid2); end; macro 'Inverse FFT [I]'; begin fft('Inverse'); end; macro 'Inverse FFT with Custom Mask [M]'; var w,h, pixWidth, i, nSmooths: integer; begin GetPicSize(w, h); GetHistogram(0, 0, w,h); if (histogram[0] = 0) and (histogram[255] = 0) then begin PutMessage('No mask. You need to edit the power spectrum using black to pass frequencies or white to filter freqwencies.'); exit; end; pixWidth := GetNumber('Transition Width in Pixels:', 6, 0); nSmooths := pixWidth div 2; if histogram[0] <> 0 then ChangeValues(1, 255, 255) else ChangeValues(0, 254, 0); for i := 1 to nSmooths do filter('smooth more'); fft('Inverse with Filter'); end; macro 'Inverse FFT with Filter'; begin fft('Inverse with Filter'); end; { procedure fftFilter(type: string; percent: integer); var width, height, size, loc: integer; begin if percent < 0 then percent := 0; if percent > 100 then percent := 100; SaveState; fft('foreward'); GetPicSize(width, height); size := round(( percent/100) * width); loc := width div 2 - size/2; MakeOvalRoi(loc, loc, size, size); if type = 'high' then SetForeground(0) else SetForeground(255); Fill; fft('Inverse'); RestoreState; end; macro 'High Pass Filter... [H]'; var percent: integer; begin percent := GetNumber('Filter size (0-100%):', 10, 0); fftFilter('high', percent); end; macro 'Low Pass Filter... [L]'; var percent: integer; begin percent := GetNumber('Filter size (0-100%):', 20, 0); fftFilter('low', percent); end; } procedure MakeFilter(size, tWidth, min, max: real); var width, height, roiSize: integer; pixWidth, i, loc, v: integer; begin SaveState; if size > 100 then size := 100; if size < 0 then size := 0; if tWidth > 100 then tWidth := 100; if tWidth < 0 then tWidth := 0; if min > 100 then min := 100; if min < 0 then min := 0; if max > 100 then max := 100; if max < 0 then max := 0; if min > max then min := max; GetPicSize(width, height); SelectAll; size := round(size / 100 * width); min := round(min / 100 * 255); max := round(max / 100 * 255); Setbackground(min); Clear; roiSize := size; pixWidth := round(size div 2 * (tWidth/100)); if pixWidth < 1 then pixWidth := 1; for i := 1 to pixWidth do begin loc := width div 2 - roiSize/2; MakeOvalRoi(loc, loc, roiSize, roiSize); v := (max-min) * exp(-4.5 * sqr(1 - i / pixWidth)) + min; {gaussian shape} SetForeground(v); Fill; roiSize := roiSize - 2; end; KillRoi; RestoreState; end; procedure doFilter(filterType: string); var width, height: integer; begin if FilterSize = 0 then FilterSize := 20; if TransitionWidth = 0 then TransitionWidth := 50; FilterSize := GetNumber('Filter size (0-100%):', FilterSize, 0); TransitionWidth := GetNumber('Transition Width (0-100%):', TransitionWidth, 0); if TransitionWidth = 0 then TransitionWidth := 0.0001; fft('foreward'); MakeFilter(FilterSize, TransitionWidth, 0, 100); if FilterType = 'high' then Invert; if PlotFilter then begin getPicSize(width, height); MakeLineRoi(0, height / 2, width, height / 2); PlotProfile; KillRoi; end; fft('Inverse with Filter'); end; macro '(---'; begin end; macro 'High Pass Filter... [H]'; begin doFilter('high'); end; macro 'Low Pass Filter... [L]'; begin doFilter('low'); end; macro 'Toggle Filter Plotting ... [T]'; begin if PlotFilter then begin PlotFilter := false; PutMessage('Filter profiles will not be plotted.'); end else begin PlotFilter := true; PutMessage('Filter profiles will be plotted.'); end; end; macro '(---'; begin end; macro 'Autocorrelation'; var fft1, fft2: integer; begin fft('foreward'); fft1 := pidNumber; ImageMath('cmul', fft1, fft1, 1, 0, 'FFT2'); fft2 := pidNumber; SelectPic(fft1); Dispose; SelectPic(fft2); fft('Inverse'); fft('Swap Quadrants'); SetPicName('Autocorrelation') end; macro 'Autocorrelation with Padding'; var pad, fft1, fft2: integer; width, height: integer; n,mean,mode,min,max: real; begin SelectAll; Measure; GetResults(n,mean,mode,min,max); Copy; GetPicSize(width, height); SetNewSize(width * 2, height * 2); Setbackgrount(round(mean)); MakeNewWindow('Padded Image'); MakeRoi(0, 0, width, height); Paste; KillRoi; pad := pidNumber; fft('foreward'); fft1 := pidNumber; ImageMath('cmul', fft1, fft1, 1, 0, 'FFT2'); fft2 := pidNumber; SelectPic(pad); Dispose; SelectPic(fft1); Dispose; SelectPic(fft2); fft('Inverse'); fft('Swap Quadrants'); SetPicName('Autocorrelation') end; macro '(---'; begin end; macro 'Make Filter...'; var width, height: integer; begin if FilterSize = 0 then FilterSize := 20; if TransitionWidth = 0 then TransitionWidth := 50; FilterSize := GetNumber('Filter size (0-100%):', FilterSize, 0); TransitionWidth := GetNumber('Transition Width (0-100%):', TransitionWidth, 0); if TransitionWidth = 0 then TransitionWidth := 0.0001; Duplicate('Filter'); MakeFilter(FilterSize, TransitionWidth, 0, 100); end; macro 'Redisplay Power Spectrum'; begin fft('Display Power Spectrum'); end; macro 'Swap Quadrants'; begin fft('Swap Quadrants'); end; macro '(---'; begin end; procedure roi(size: integer); var width, height: integer; begin GetPicSize(width, height); if size > width then size := width; if width = 0 then begin PutMessage('No image window open.'); exit; end; MakeRoi(width/2 - size/2, height/2 - size/2, size, size); end; macro 'Create 32 x 32 selection [1]'; begin roi(32) end; macro 'Create 64 x 64 selection [2]'; begin roi(64) end; macro 'Create 128 x 128 selection [3]'; begin roi(128) end; macro 'Create 256 x 256 selection [4]'; begin roi(256) end; macro 'Create 512 x 512 selection [5]'; begin roi(512) end; procedure AnnularSelection(color: integer); var x1,x2,y1,y2,top,left,width,height, w, h:integer; xcenter,ycenter,radius1, radius2:integer; begin if pos('FFT',WindowTitle) <> 1 then begin beep; PutMessage('Frequency domain (FFT) image required.'); exit; end; GetPicSize(w,h); GetLine(x1,y1,x2,y2,width); if x1<0 then begin beep; PutMessage('Line selection required.'); exit; end; SaveState; SetForeground(color); xcenter:=w/2; ycenter:=h/2; radius1:=sqrt(sqr(abs(x1-xcenter))+sqr(abs(y1-ycenter))); radius2:=sqrt(sqr(abs(x2-xcenter))+sqr(abs(y2-ycenter))); if radius1 < radius2 then begin MakeOvalROI(xcenter-radius1,ycenter-radius1,radius1*2,radius1*2); copy; setbackgroundcolor(0); MakeOvalROI(xcenter-radius2,ycenter-radius2,radius2*2,radius2*2); fill; paste; killroi; end; MakeOvalROI(xcenter-radius2,ycenter-radius2,radius2*2,radius2*2); copy; setbackgroundcolor(0); MakeOvalROI(xcenter-radius1,ycenter-radius1,radius1*2,radius1*2); fill; paste; killroi; RestoreState; end; macro '(---'; begin end; {The annular selection macros are designed to be used in the power spectrum window. Using the line selection tool, a line is drawn that extends through some range of spatial frequencies. This line should be radial from the center of the window since the selection will be from the central to distal portion of the line. After making the line selection, typing W will cause a black annular selection to be made. Following this selection with the Inverse command from the FFT macros will result in passing the range of frequencies selected in the inverse transform. If you want to use the selection as a notch filter, then type W to create a white annular selection.} macro 'Black Annular Selection - Pass [B]'; begin AnnularSelection(255); end; macro 'White Annular Selection - Notch [W]'; begin AnnularSelection(0); end;