Calling ByteProcessor.skeletonize removes 1px border from image, while using the menu doesn't

I was trying to skeletonize an image from some java code and I found the edge of the skeletonized image was being removed.

import ij.ImageJ;
import ij.process.ImageProcessor;
import ij.process.ByteProcessor;
import ij.ImagePlus;

public class Example{

    public static void main(String[] args){
        new ImageJ();
        ImagePlus plus = new ImagePlus("./generated.tif");
        plus.show();
        ImageProcessor proc = plus.getProcessor();
        ByteProcessor bp = proc.duplicate().convertToByteProcessor();
        bp.threshold(0);
        bp.invert();
        bp.skeletonize();
        new ImagePlus("skeletonized", bp).show();
    }

}

generated.tif (9.6 KB)

That would produce an image with a 1px border removed from the image. If on the other hand I use the menu, adjust & apply the threshold, then select from the menu process->binary->skeletonize. The image is skeletonized to the edges of the image.

How can I get the skeleton to the edge of the image from java?

After reading through the source code. The menu item actually expands the image by 1px and then performs the the skeletonization, then reduces the image by 1px.

This bug is fixed in the latest ImageJ daily build (1.52v5). There is also a new ImageProcessor.skeletonize(foreground) method that you can use to skeletonsize an image with a black background without inverting it. Here is a JavaScript example:

  size = 20;
  foreground = 255;
  img = IJ.createImage("original", "8-bit black", size, size, 1);
  ip = img.getProcessor().duplicate();
  ip.setColor(foreground);
  ip.drawRect(0,0,size,size);
  new ImagePlus("original",ip.duplicate()).show();
  IJ.run("Set... ", "zoom=1200");
  ip.skeletonize(foreground);
  new ImagePlus("skeletonized",ip).show();
  IJ.run("Set... ", "zoom=1200");
2 Likes