{ Macros to prepare stacks for stereo projection and viewing For stereo effect, process images in stack and try projecting at between 6 and 8 degrees on the Y-axis using Brightest Point Questions/comments regarding PadStack, Deblur, Image Pair, and Rock Image may be directed to Squidney@UNCVX1.oit.unc.edu (9/25/93) The set includes several macros from the already posted 'Stacks' macros as well as 4 of my own which I hope are some help to others. A brief description follows. PadStack: Creates an average of two adjacent images in a stack and places the new image then in between. Note that the size of the stack will be 2N-1 larger than the original. Helps when viewing a stack where there is distance between slices. Deblur: This macro averages an image from above and below the image of interest, blurs (convolves) the averaged image (now a representation of the out of focus light in the image of interest) and then subtracts the blurred image from the image of interest. This is a crude and, and for some, mathamatically repugnant approach to cleaning up a fuzzy stack, but has worked well for some stacks of conventional fluorescence images. Note that size of the stack will be N-1. Image Pair: Takes the first and last image in a stack and puts them side by side into a new scaled window. This makes a single image, or stereo pair, from a projected stack of two images made 6-8 degrees apart on the Y axis for cross-your-eyes stereo. Rock Image: Presents images from top to bottom then bottom to top. This creates a very convincing stereo effect if a stack is projected as 3-5 images at 5-10degree increments using the 'Brightest Point' method of projection. Again, I hope these are of some help to others. These macros were written to facilitate viewing stacks in a 3D manner in conjunction with the Projection... command. Direct comments, suggestions, criticisms to Sidney L. Shaw Squidney@uncvx1.oit.unc.edu } procedure CheckForStack; begin if nPics=0 then begin PutMessage('This macro requires a stack.'); exit; end; if nSlices=0 then begin PutMessage('This window is not a stack.'); exit; end; end; macro 'Add Slice [A]'; begin CheckForStack; AddSlice end; macro 'Delete Slice [D]'; begin CheckForStack; DeleteSlice end; macro 'First Slice [F]'; begin CheckForStack; SelectSlice(1) end; macro 'Last Slice [L]'; begin CheckForStack; SelectSlice(nSlices) end; macro '(-' begin end; macro 'Smooth'; var i:integer; begin CheckForStack; for i:= 1 to nSlices do begin SelectSlice(i); SetOption; Smooth; end; end; macro 'Shadow'; var i:integer; begin CheckForStack; for i:= 1 to nSlices do begin SelectSlice(i); SetOption; Shadow; end; end; macro 'Sharpen'; var i:integer; begin CheckForStack; for i:= 1 to nSlices do begin SelectSlice(i); SetOption; Smooth; SetOption; Sharpen; end; end; macro 'Reduce Noise'; var i:integer; begin CheckForStack; for i:= 1 to nSlices do begin SelectSlice(i); ReduceNoise; end; end; macro 'Invert'; var i:integer; begin CheckForStack; for i:= 1 to nSlices do begin SelectSlice(i); Invert; end; end; macro 'Apply LUT'; var i,stack,slices:integer; begin CheckForStack; stack:=PicNumber; slices:=nSlices; Duplicate('Temp'); for i:= 1 to slices do begin SelectPic(stack); SelectSlice(i); ApplyLut; SelectPic(nPics); if i<>slices then PropagateLut; end; SelectPic(nPics); Dispose; end; {Macro for creating an average image of two slices and placing it in between} Macro 'PadStack'; var advance,c,i,m:integer; begin CheckForStack; ScaleMath(false); advance:=nSlices; Selectslice(nSlices); addslice; m:=0 for c:=1 to advance do begin; i:=c+m; SelectSlice(i); SelectAll; Copy; AddSlice; SelectSlice(i+1); Paste; MultiplyByConstant(.5); SelectSlice(i+2); SelectAll; Copy; AddSlice; SelectSlice(i+3); Paste; MultiplyByConstant(.5); SelectAll; Copy; DeleteSlice; SelectSlice(i+1); Paste; Add; if m=(nSlices) then c:=advance; m:=m+1; end; SelectSlice(i+2); deleteslice; deleteslice; end; {macro for simple Z axis nearest nieghbor deconvolution accomplished by adding the image below and above together, convolving, and subtracting that image (a representation of the out of focus light in the middle image) form the middle image} macro 'Deblur'; var Scale:real; i:integer; Convol:String; begin CheckForStack; ScaleMath(false); Scale:=GetNumber('Contrast (Try 1-3):',2.5); Convol:=GetString('Kernal for Blurring Image:','Gauss(5x5)'); SelectSlice(nSlices); AddSlice; for i:=1 to (nSlices-2) do begin {a Pad a slice} SelectSlice(i+1); AddSlice; {b Take slice from below plane and cut intensities by half} SelectSlice(i); SelectAll; Copy; AddSlice; Paste; MultiplyByConstant(.5); {c Take slice from above plane and cut intensity by half} SelectSlice(i+4); SelectAll; Copy; AddSlice; Paste; MultiplyByConstant(.5); {d Add two slices together to get average and delete one of padded slices} SelectAll; Copy; DeleteSlice; SelectSlice(i+1); Paste; Add; {d' Blur the averaged image and change values before subtracting from middle plane} Convolve(Convol); MultiplyByConstant(.5); {e Subtract blurred image from middle plane and multiply rescale values} SelectSlice(i+2); SelectAll; Copy; SelectSlice(i+3); Paste; SelectSlice(i+1); SelectAll; Copy; SelectSlice(i+3); Paste; Subtract; MultiplyByConstant(scale); {f Delete temporary windows and move deconvoluted image to front} SelectSlice(i+1); DeleteSlice; SelectSlice(i+2); SelectAll; Copy; DeleteSlice; SelectSlice(i); Paste; End; SelectSlice(nSlices); DeleteSlice; DeleteSlice; DeleteSlice; End; macro 'Remove 0 and 255'; { Changes 0 to 1 and 255 to 254 in all slices. We want to do this because pixel values of 0(which always displays as white) and 255(always displays as black) cause problems when pseudo-coloring images. } var i:integer; begin CheckForStack; for i:= 1 to nSlices do begin SelectSlice(i); ChangeValues(0,0,1); ChangeValues(255,255,254); end; end; macro '(-' begin end; procedure CheckForSelection; var x1,y1,x2,y2,LineWidth:integer; begin GetRoi(RoiLeft,RoiTop,RoiWidth,RoiHeight); GetLine(x1,y1,x2,y2,LineWidth); if (RoiWidth=0) or (x1>=0) then begin PutMessage('Please make a rectangular selection.'); exit; end; end; procedure CropAndScale(fast:boolean; angle:real); var i,OldStack,NewStack:integer; RoiLeft,RoiTop,RoiWidth,RoiHeight:integer; N,NewWidth:integer; ScaleFactor:real; OneToOne:boolean; begin CheckForStack; CheckForSelection; SaveState; OldStack:=PicNumber; N:=nSlices; ScaleFactor:=GetNumber('Scale factor(0.05..25):',1.0); OneToOne:=ScaleFactor=1.0; NewWidth:=round(RoiWidth*ScaleFactor); if odd(NewWidth) then begin NewWidth:=NewWidth-1; ScaleFactor:=NewWidth/RoiWidth; end; SetNewSize(RoiWidth*ScaleFactor,RoiHeight*ScaleFactor); MakeNewStack('Stack'); NewStack:=PicNumber; if not OneToOne then begin if fast then SetScaling('Nearest; Create New Window') else SetScaling('Bilinear; Create New Window'); end; SelectPic(OldStack); for i:= 1 to N do begin SelectSlice(1); if OneToOne and (angle=0.0) then Duplicate('Temp') else ScaleAndRotate(ScaleFactor,ScaleFactor,angle); SelectAll; Copy; SelectPic(NewStack); if i<>1 then AddSlice; Paste; SelectPic(nPics); Dispose; {Temp} SelectPic(OldStack); DeleteSlice; end; Dispose; {OldStack} RestoreState; end; macro 'Crop and Scale-FastÉ'; begin CropAndScale(true, 0); end; macro 'Crop and Scale-SmoothÉ'; begin CropAndScale(false, 0); end; {This Macro takes the first and last image in a stack and puts them side by side in a scaled window} Macro 'Image Pair[P]'; Var width,height,Twidth,Theight:integer; a,b,c,x,y:integer; Stack,Stereo:integer; ratio:real; Begin CheckForStack; SaveState; {Scale images and make new scaled window} Stack:=Picnumber; SelectSlice(1); GetPicSize(x,y); b:=0; If x>=330 then b:=1; If y>330 then b:=1; if x>=y then width:=660 height:=(y/(x/330)) ratio:=330/x; if y>x then height:=330 width:=(x/(y/660)) ratio:=330/y; If b=1 then Twidth:=2*x Theight:=y; if b=0 then twidth:=width Theight:=height; SetNewSize(Twidth,Theight); MakeNewWindow('Stereo Pair'); Stereo:=PicNumber; {copy and paste first image into left side of new window} SelectPic(Stack); SelectSlice(1); SelectAll; Copy; SelectPic(Stereo); MakeROI((Twidth/2)-x,(Theight-y)/2,x,y); Paste; {copy and paste second image into right side of window} SelectPic(Stack); SelectSlice(nSlices); SelectAll; Copy; Killroi; SelectPic(Stereo); MakeROI(Twidth-(Twidth/2),(Theight-y)/2,x,y); Paste; {scale images in new window} SetScaling('sameWindow'); SetScaling('bilinear'); ScaleandRotate(ratio,ratio,0); If b=1 then begin If x>=y then MakeROI((Twidth-660)/2,((Theight-(y*ratio))/2),660,y*ratio); If y>x then MakeROI((Twidth/2)-(x*ratio),(Theight-330)/2,2*(x*ratio),330); Copy; Dispose; SetNewSize(Width,height); MakeNewWindow('Stereo Pairs') Paste; KillROI; end; end macro 'Rock Image[R]'; var a,i:integer; begin CheckForStack; i:=0; a:=0; repeat if a=0 then i:=i+1; if a=1 then i:=i-1; {if i>nSlices then i:=1;} Wait(0.2); SelectSlice(i); if i=nSlices then a:=1; if i=1 then a:=0; until button; end;