{ Section Alignment Macros -------------------------------- Each macro asks an opened stack and outputs separate images that must be stacked manually (this is to save memory by avoiding to keep two complete stacks simultaneously in memory). To use the macros, frames are supposed to be arranged in composite pictures (like posters) with 4 lines of 5 frames (contiguous), approximatively oriented. You have to mark the 3 reference points each by a 4x4 black spot (using the 4x4 brush tool). The spots MUST be the only occurence of the 255 pixel value in your picture. To be sure of that, substract 1 to your picture before drawing the spots. The first macro "decoupe planche" is used to cut the composite pictures assembled as a stack and create a serie of individual pictures all of the same size (the size your ROI when you start), saved as "PICxxx". When all your sections are isolated and gathered in the same folder, open them in Image using the ' open all' facility. then convert them into a stack (image to stack). Select on your stack a ROI large enough to contain in each frame the 3 reference spots and run the "rot XYscal Transl" macro that rotates and rescale each picture of the stack. The pictures are saved as previously in individual files called "coupexxx". Open all the aligned pictures and convert into stack. The last macro picks up an oval selection at the relevant place Guy (bonnot@jouy.inra.fr) } macro 'Decoupe planche [D]'; var i,j,planche,wcl,hcl,gaucheini,hautini,lima,hima niv,bord,l,t,w,h,boucle,pn,npl :integer; fic : string; begin npl:=nSlices; if npl=0 then begin PutMessage('Cette macro opere uniquement sur une pile'); exit; end; boucle:=0; pn:=PicNumber; GetRoi(l,t,w,h); if w=0 then begin PutMessage('Cette macro exige une selection rectangulaire'); exit; end; wcl:=w; hcl:=h; SetNewSize(wcl,hcl); hautini:=t; gaucheini:= l; for planche:=1 to npl do begin pn:=PicNumber; SelectSlice(planche); GetPicSize(w,h); if w=0 then begin PutMessage('Cette macro exige une Planche ouverte'); exit; end; lima:=w/5; hima:=h/4; for i:=0 to 3 do begin for j:= 0 to 4 do begin makeRoi(gaucheini+j*lima,hautini+i*hima,wcl,hcl); copy; boucle:=boucle+1; MakeNewWindow('PIC',boucle:3); paste; SaveAs('PIC',boucle:3); dispose; SelectPic(pn); SelectSlice(planche); end; end; end; end; macro 'rot XYscal Translat [R]'; var i,j,wcl,hcl,l,t,w,h,boucle,xc,yc,margex,margey,pn :integer; slicenb,wfin,hfin,pixx1,pixy1,left,top x1,x1,x2,x3,y1,y2,y3,dx,dy,scalx,scaly: integer; alpha,beta,angle,ro1,gama1 :real; fic : string; begin pn:=PicNumber; SetOptions('X-Y Center'); slicenb:=nSlices; if slicenb=0 then begin PutMessage('Cette macro opere uniquement sur une pile'); exit; end; boucle:=1; SelectSlice(boucle); GetRoi(l,t,wfin,hfin); if wfin=0 then begin PutMessage('Cette macro exige une selection rectangulaire'); exit; end; SaveState; SetThreshold(255); AnalyzeParticles; if rCount <>3 then begin PutMessage('Je compte plus ou moins de 3 references'); exit; end; x1:=rX[1]; x2:=rX[2]; x3:=rX[3]; y1:=rY[1]; y2:=rY[2]; y3:=rY[3]; dx:=x2-x1; dy:=y3-y1; if y3=y1 then alpha:=1.570796 else alpha:= arctan((x3-x1)/(y3-y1)); margex:=x1-l; margey:=y1-t; SelectPic(pn); RestoreState; RestoreRoi; copy; SetNewSize(wfin,hfin); MakeNewWindow('Coupe',boucle:3); paste; SaveAs('Coupe',boucle:3); dispose; SetScaling('Nearest; Same Window'); for boucle:=2 to slicenb do begin SelectPic(pn); SelectSlice(boucle); SelectAll; GetRoi(l,t,w,h); Copy; SetNewSize(w+100,h+100); MakeNewWindow('Montage'); Paste; Duplicate('miroir'); SelectAll; SetThreshold(255); AnalyzeParticles; if rCount <>3 then begin PutMessage('Je compte plus ou moins de 3 rˇfˇrences'); exit; end; x1:=rX[1]; x2:=rX[2]; x3:=rX[3]; y1:=rY[1]; y2:=rY[2]; y3:=rY[3]; if y3=y1 then beta:=1.570796 else beta:= arctan((x3-x1)/(y3-y1)); angle:=180*(beta-alpha)/3.141592654; dispose; SelectWindow('Montage'); SelectAll; ScaleAndRotate(1,1,angle); SetThreshold(255); AnalyzeParticles; if rCount <>3 then begin PutMessage('Je compte plus ou moins de 3 rˇfˇrences'); exit; end; x1:=rX[1]; x2:=rX[2]; x3:=rX[3]; y1:=rY[1]; y2:=rY[2]; y3:=rY[3]; RestoreRoi; scaly:=dy/(y3-y1); scalx:=dx/(x2-x1); RestoreRoi; GetRoi(l,t,w,h); SetScaling('Nearest; New Window'); ScaleSelection(scalx,scaly); x1:=x1*scalx; y1:=y1*scaly; MakeRoi(x1-margex,y1-margey,wfin,hfin); Copy; Dispose; SetNewSize(wfin,hfin); MakeNewWindow('Coupe',boucle:3); Paste; EnhanceContrast; ApplyLut; SaveAs('Coupe',boucle:3); dispose; end end; macro 'Isole[I]'; var i,j,planche,wcl,hcl,gaucheini,hautini,lima,hima niv,bord,l,t,w,h,boucle,pn,npl :integer; fic : string; begin npl:=nSlices; if npl=0 then begin PutMessage('Cette macro opere uniquement sur une pile'); exit; end; boucle:=0; pn:=PicNumber; GetRoi(l,t,w,h); if w=0 then begin PutMessage('Cette macro exige une selection'); exit; end; wcl:=w; hcl:=h; SetNewSize(wcl,hcl); hautini:=t; gaucheini:= l; for planche:=1 to npl do begin pn:=PicNumber; SelectSlice(planche); MakeOvalRoi(gaucheini,hautini,wcl,hcl); Copy; MakeNewWindow('image',planche:3); paste; SaveAs('Image',planche:3); dispose; SelectPic(pn); SelectSlice(planche) end; end;