Skip to content

Instantly share code, notes, and snippets.

@ekatrukha
Last active January 28, 2021 16:41
Show Gist options
  • Save ekatrukha/46b928f7d4559771dff69c4c31153177 to your computer and use it in GitHub Desktop.
Save ekatrukha/46b928f7d4559771dff69c4c31153177 to your computer and use it in GitHub Desktop.
ImageJ macro for illustration of "Straighten" ROI function
// Providing an image and polyline, macro illustrates
// (creates a stack with animation)
// "Straighten" ROI function of ImageJ
// 2021.01.28 Eugene Katrukha / katpyxa at gmail dot com
if (nImages<1)
{
exit("This macro needs an input image. Open something");
}
if(selectionType()!=6)
{
exit("Please, first you need to make a polyline selection (ROI).");
}
origID=getImageID();
imH=getHeight();
imW=getWidth();
Dialog.create("Create straightening animation")
Dialog.addNumber("Final number of frames in the animation (>1):", 12);
Dialog.addNumber("Resampling factor in pixels (0.1-1):", 0.5);
Dialog.addMessage("Smaller resampling = longer processing, less artifacts");
Dialog.addCheckbox("Pre-fill slides with foreground color (unchecked=black,0)", false);
Dialog.addCheckbox("Batch mode? (hide intermediate steps)", false);
Dialog.show();
steps=Dialog.getNumber()-1;
resampleFactor=Dialog.getNumber();
bFill=Dialog.getCheckbox();
bBatch=Dialog.getCheckbox();
if(bBatch)
setBatchMode(bBatch);
imTitle=getTitle();
run("Fit Spline");
strrun="interval="+toString(resampleFactor)+" smooth";
run("Interpolate", strrun);
Roi.getCoordinates(x2,y2);
selectImage(origID);
l = x2.length;
//orientation of poly line ROI (assumed from left to right, LR),
//needs to be reversed, if from right to left
bROI_LR=true;
if(x2[0]>x2[l-1])
{
bROI_LR=false;
}
//mean x and y
xMean=0;
yMean=0;
for(i=0;i<l;i++)
{
xMean+=x2[i];
yMean+=y2[i];
}
xMean=xMean/l;
yMean=yMean/l;
w=Roi.getStrokeWidth;
//makeLine(xMean-l*0.5*resampleFactor, yMean, xMean+l*0.5*resampleFactor, yMean, w);
if(imW<(xMean+l*0.5*resampleFactor))
{
imWN=xMean+l*0.5*resampleFactor+5;
}
else {
imWN=imW;
}
imBit=bitDepth();
if (imBit==24) {
newImage("Straighten_"+imTitle, "RGB", imWN, imH, 1, 1, steps+1);
}
else {
newImage("Straighten_"+imTitle, toString(imBit)+"-bit", imWN, imH, 1, 1, steps+1);
}
anim=getImageID();
selectImage(origID);
x0=newArray(l);
y0=newArray(l);
for(i=0;i<l;i++)
{
if(bROI_LR)
{x0[i]=xMean-l*0.5*resampleFactor+i*resampleFactor;}
else
{x0[i]=xMean+l*0.5*resampleFactor-i*resampleFactor;}
y0[i]=yMean;
}
xn = newArray(l);
yn = newArray(l);
selectImage(anim);
showStatus("Making straightening animation...");
showProgress(0.0);
for(s=0;s<=steps;s++)
{
showStatus("Making straightening animation...frame("+toString(s+1)+"/"+toString(steps+1)+")");
setSlice(s+1);
if(bFill)
floodFill(1, 1);
//building new polyline
for(i=0;i<l;i++)
{
xn[i]=x2[i]+s*(x0[i]-x2[i])/steps;
yn[i]=y2[i]+s*(y0[i]-y2[i])/steps;
}
//get new line along the width
xw=newArray(l);
yw=newArray(l);
for (dk=0;dk<=w;dk+=resampleFactor)
//for (dw=-0.5*w;dw<=0.5*w;dw+=0.5)
{
if(dk<=0.5*w)
dw=dk;
else {
dw=dk-0.5*w;
dw=(-1)*dw;
}
//dw=0.5*w;
//going through old polyline
vals=newArray(l);
selectImage(origID);
for(i=0;i<(l-1);i++)
{
x=x2[i+1]-x2[i];
y=y2[i+1]-y2[i];
lv=sqrt(x*x+y*y);
x=x/lv; y=y/lv;
//rotate 90 degrees
xp=-y; yp=x;
x=xp*dw;
y=yp*dw;
xv=x2[i]+x;
yv=y2[i]+y;
vals[i]=getPixel(xv, yv);
}
//last point
x=x2[l-2]-x2[l-1];
y=y2[l-2]-y2[l-1];
lv=sqrt(x*x+y*y);
x=x/lv; y=y/lv;
xp=y; yp=-x;
x=xp*dw; y=yp*dw;
xv=x2[l-1]+x;
yv=y2[l-1]+y;
vals[l-1]=getPixel(xv, yv);
//going through new polyline
selectImage(anim);
for(i=0;i<(l-1);i++)
{
x=xn[i+1]-xn[i];
y=yn[i+1]-yn[i];
lv=sqrt(x*x+y*y);
x=x/lv; y=y/lv;
//rotate 90 degrees
xp=-y; yp=x;
x=xp*dw;
y=yp*dw;
xt=xn[i]+x;
yt=yn[i]+y;
setPixel(xt,yt,vals[i]);
}
//last point
x=xn[l-2]-xn[l-1];
y=yn[l-2]-yn[l-1];
lv=sqrt(x*x+y*y);
x=x/lv; y=y/lv;
xp=y; yp=-x;
x=xp*dw; y=yp*dw;
xt=xn[l-1]+x;
yt=yn[l-1]+y;
setPixel(xt,yt,vals[l-1]);
if(!bBatch)
updateDisplay();
}
showProgress(s/steps);
}
showStatus("Making straightening animation...Done.");
if(bBatch)
{
selectImage(anim);
setBatchMode(false);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment