PRO otrack2,smov,out,lf ;OTRACK - object tracking in a 3-D segmented movie, based on ;the identification of objects in a pair of frames (preceding ;and actual). Two objects are identified if they have at least ;one pixel at common position in both frames. ;Called routine: OBJEKT1 ;VERSION 2 - complete, includes splitting and merging of objects. ;15 April 1996, checked on 5 long-lived CUDs, OK. Michal. sm=size(smov) if sm(0) ne 3 then begin print,'ERROR: Input must be a 3-D array. STOPPED (type RETALL).' stop endif ;LF - working array, 0-no.of repetitions, 1-actual object no. lf=intarr(2,2000) clf=0 ;counter of objects ;OUT - output array, 1st dimension - resulting data: ; 0-peak intensity, 1-peak position, 2-size ; 2nd dimension - frames (i.e. time) ; 3rd dimension - objects out=intarr(3,sm(3),2000) ;beginning imao=smov(*,*,0) ;1st frame OBJEKT1,imao,tabo ;find objects in frame tabo=tabo(*,where(tabo(0,*))) ;exclude 0 (1-pix) objects iman=smov(*,*,1) ;2nd frame OBJEKT1,iman,tabn ;find objects tabn=tabn(*,where(tabn(0,*))) ;exclude 0 (1-pix) objects nobj=max(tabn(0,*)) ;number of objects for j=1,nobj do begin ;loop over objects pcn=tabn(1,where(tabn(0,*) eq j,c)) ;set of j-th object coords for k=0,c-1 do begin ;search over pixels in object w=where(tabo(1,*) eq pcn(k),cw) ; until the first coincidence if cw ne 0 then begin lf(0,clf)=1 ;1st repetition lf(1,clf)=j ;actual object no. oon=tabo(0,w(0)) ;old object no ton=tabo(1,where(tabo(0,*) eq oon, np)) out(0,0,clf)=max(imao(ton),pos) ;record preceding out(1,0,clf)=ton(pos) out(2,0,clf)=np out(0,1,clf)=max(iman(pcn),pos) ;record actual out(1,1,clf)=pcn(pos) out(2,1,clf)=c clf=clf+1 ;increment counter of objects goto,new0 endif endfor new0: endfor ;Main body - Loop over frames for i=2,sm(3)-1 do begin print,'Frame',i imao=iman ;preceding frame iman=smov(*,*,i) ;actual frame tabo=tabn ;preceding table of objects OBJEKT1,iman,tabn ;find acual objects tabn=tabn(*,where(tabn(0,*))) nobj=max(tabn(0,*)) olf=lf ;old LF - cannot be changed in object loop for j=1,nobj do begin ;loop over objects pcn=tabn(1,where(tabn(0,*) eq j,c)) ;MERGE - 0, 1 or more old objects identified oon=intarr(c) ;prepare list of old object nos. - oons for k=0,c-1 do begin ;search over pixels in object w=where(tabo(1,*) eq pcn(k),cw) if cw ne 0 then oon(k)=tabo(0,w(0)) ;old object nos. array endfor ;list of oons, but raw if total(oon) gt 0 then begin ;oon is not empty oon=oon(where(oon)) ;get rid of zeros soo=n_elements(oon) if soo gt 1 then begin oon=oon(sort(oon)) oo=intarr(soo) ;temporary o=0 ;temporary counter oo(0)=oon(0) for k=1,soo-1 do begin ;eliminate repeating oons if oon(k) ne oon(k-1) then begin o=o+1 oo(o)=oon(k) endif endfor oo=oo(0:o) oon=oo ;final list of oons soo=o+1 ;size of oon endif endif else begin oon=0 ;no coincidence at all soo=0 endelse if soo gt 1 then begin ;MERGE case - 2 or more wlf=lonarr(soo) ; preceding objects lif=intarr(soo) ;array of lifetimes for k=0,soo-1 do begin wlff=where(olf(1,*) eq oon(k),cr) ;object already in OLF? if cr gt 0 then begin ;yes wlf(k)=wlff(0) lif(k)=olf(0,wlf(k)) endif else begin ;no lif(k)=0 ;wlf(k)=-1 ;might be skipped after tunning endelse endfor maxlif=max(lif,k) ;find maximum lifetime if maxlif gt 0 then wlf(0)=wlf(k) else begin ;output WLF(0) oon=oon(0) ;NEWly identified objects, goto,newobj ; take first as predecessor endelse endif if soo eq 1 then begin ;single preceding object wlf=where(olf(1,*) eq oon(0),cr) ;object already in OLF? ;yes, output WLF(0) if cr eq 0 then begin ;no oon=oon(0) goto,newobj ;NEWly identified object endif endif if soo lt 1 then goto,new1 ;empty oon (soo=0), ; go to new actual object ;The body to process actual staying object - input WLF(0) if lf(0,wlf(0)) eq olf(0,wlf(0)) then begin ;no change yet - ; - no SPLIT yet lf(0,wlf(0))=lf(0,wlf(0))+1 ;increment repetition lf(1,wlf(0))=j ;actual object no. out(0,i,wlf(0))=max(iman(pcn),pos) ;output values out(1,i,wlf(0))=pcn(pos) ; (peak intensity, out(2,i,wlf(0))=c ; (coord., size) endif else begin ;LF already changed,same WLF(0), ie.SPLIT maxnew=max(iman(pcn),pos) if maxnew gt out(0,i,wlf(0)) then begin ;overwrite, lf(1,wlf(0))=j ; if this object is brighter, out(0,i,wlf(0))=maxnew ; else do nothing (fainter out(1,i,wlf(0))=pcn(pos) ; object ignored) out(2,i,wlf(0))=c endif endelse goto,new1 ;finish, go to new actual ; object ;NEWly identified object body newobj: lf(0,clf)=1 ;1st repetition lf(1,clf)=j ;actual object no. ton=tabo(1,where(tabo(0,*) eq oon,np)) out(0,i-1,clf)=max(imao(ton),pos) ;output - predecessor out(1,i-1,clf)=ton(pos) out(2,i-1,clf)=np out(0,i,clf)=max(iman(pcn),pos) ;output - actual out(1,i,clf)=pcn(pos) out(2,i,clf)=c clf=clf+1 new1: ;processing of actual object finished endfor ;end loop objects (j) olf=lf-olf ;differences new-old LF lf(1,where(olf(0,*) eq 0))=0 ;DISAPPEARED objects - ;-where no incrementation, set obj.no=0 endfor ;end loop frames (i) lf=lf(*,0:clf-1) ;shorten array ;histo,lf(0,*),bin=1,/abs,min=0,max=max(lf(0,*))+1 out=out(*,*,0:clf-1) ;shorten array end