3

In order to perform drift correction in a SI image as shown in the following figure: drift corrected SI

I write the code :

number max_shift=5
image src := GetFrontImage()
number sx, sy, sz
src.Get3DSize(sx, sy, sz)
result("sx: "+sx+"\n")
result("sy: "+sy+"\n")
result("sz: "+sz+"\n")

// assume a random shift in x
image shift := IntegerImage("xcorrd",4,0, 1, sy)
shift = max_shift*Random() 

// make a coordinate table
image col := IntegerImage("col",4,0, sx, sy)
image row := IntegerImage("row",4,0, sx, sy)
image plane := IntegerImage("plane",4,0, sx, sy)
col = icol
row = irow
plane = iplane

// to expand the shift as the same size with source image
image ones := IntegerImage("ones",4,0, sx, sy)
ones = 1

// create a random column shift of the source SI image
for(number i=0; i<sy; i++) {
    col[i,0,i+1,sx] = col[i,0,i+1,sx]+shift.GetPixel(0,i)*ones[i,0,i+1,sx]
};

// drift corrected
image im := RealImage("test si", 4, sx+max_shift, sy, sz)
im=0
im[col, row, plane] = src[icol,irow,iplane]

im.ImageGetTagGroup().TagGroupCopyTagsFrom(src.ImageGetTagGroup())
im.ImageCopyCalibrationFrom(src)
im.SetName(src.GetName()+"-drift corrected")
im.showimage()

The image can be corrected, however the spectrum cannot be transferred to the corrected SI as shown : the result

I am just wondering what's wrong with my script.

Thank you in advance.

Renfong
  • 153
  • 6
  • 1
    Not exactly sure what you are after, but my guess is that this line only works for image plane 0: im[col, row, plane] = src[icol,irow,iplane]. try a loop. – Don I Mar 24 '21 at 18:42

1 Answers1

1

im[col, row, plane] = src[icol,irow,iplane]

The intrinsic variables icol, irow, iplane will be evaluated by the only fixed size image expression in the line. In your case col, row and plane (all of same size)

However, they are all 2D so what is internally happening is that you iterate over X & Y and then write the values:

im[ col(x,y), row(x,y), plane(x,y) ] = src[x,y,0] // iterated over all x/y

As Don I was mentioning in the comments, you would want to iterate over the z dimension.

Alternatively, you could make all of your images of size (sx,sy,sz) in your script. This would work for the expression, but is horrifically inefficient.

In general, the best solution here is to no t use icol,irow,iplane at all, but make use of the Slice commands. see this answer:


I would possibly code a line-wise x-shift for an SI like below: The script utilizes the fact that one can shift whole "blocks" (X x 1 x Z) in x-direction, iterating over y.

number sx = 256
number sy = 256
number sz = 100
image testSI := realImage("SI",4,sx,sy,sz)
testSI = sin(itheta/(idepth-iplane)*idepth) + (iplane % (icol+1))/idepth
testSI.ShowImage()

image xdrift := RealImage("XDrift per line",4,sy)
xdrift = trunc(random()*5 + 20*sin(icol/iwidth*3*PI()))
xdrift.ShowImage()

// Apply linewise Drift to SI, assuming xDrift holds this data
xDrift -= min(xDrift)   // ensure only positive shifts
image outSI := realImage("SI shifted",4,sx+max(xDrift),sy,sz)
outSI.ShowImage()

for( number y=0; y<sy; y++ ){
    number yShift = sum(xDrift[y,0])
    outSI.slice2( yShift,y,0, 0,sx,1, 2,sz,1 ) = testSI.slice2(0,y,0,0,sx,1,2,sz,1)
}

The script below performs the iteration "plane by plane", but does not have a restriction on the plane-wise shift. In fact, here each pixel gets an assigned XY shift.

Note that you can use warp(source, xexpr, yexpr ) instead of 2D addressing source[ xexpr, yexpr ] if you want to use bilinear interploation of values (and 0 truncation outside the valid range).

number sx = 256
number sy = 256
number sz = 100
image testSI := realImage("SI",4,sx,sy,sz)
testSI = sin(itheta/(idepth-iplane)*idepth) + (iplane % (icol+1))/idepth
testSI.ShowImage()

image xdrift := RealImage("pixelwise XDrift",4,sx,sy)
xdrift = irow%10*random() + 20*cos(irow/iheight*5*PI())
xdrift.ShowImage()

image ydrift := RealImage("pixelwise yDrift",4,sx,sy)
ydrift = 10*abs(cos(icol/iwidth* (irow/iheight) * 10 * PI())) + irow/iheight * 10 
ydrift.ShowImage()

// Apply pixelwise Drift to SI
xDrift -= min(xDrift)   // ensure only positive shifts
yDrift -= min(yDrift)   // ensure only positive shifts
number mx = max(xDrift)
number my = max(yDrift)
image outSI := realImage("SI shifted",4,sx+mx,sy+my,sz)
outSI.ShowImage()
for( number z=0;z<sz;z++){
    image outPlane := outSI.Slice2( 0,0,z, 0,sx+mx,1,1,sy+my,1) 
    image srcPlane := testSI.Slice2( 0,0,z, 0,sx,1,1,sy,1)
    outPlane = srcPlane[ icol + xdrift[icol,irow] - mx, irow + ydrift[icol,irow] - my ]
    // outPlane = srcPlane.warp( icol + xdrift[icol,irow] - mx, irow + ydrift[icol,irow] - my)
}   
BmyGuest
  • 6,331
  • 1
  • 21
  • 35