3D Counter Java is slower than Macro

I am applying a 3D Counter on a stack of 20 images, it is too slow compared to the same steps I do on FIJI. FIJI for two consecutive stacks took 3.4 minutes while the code took 5.7 minutes with difference in counting 1034 more for FIJI

The only difference that I know of is the way images are opened. I am sending this to know if there are any notices what could be the cause that lead to that difference. I also noticed from a previous post that 3D counter is slow generally but still I would be glad for any advises that would increase the speed.

FIJI Macro:

run("Image Sequence...", "open=[D:/My Folder/red channel/] sort");
run("Image Sequence...", "open=[D:/My Folder/green channel/] sort");
run("Merge Channels...", "c1=[red channel] c2=[green channel] create");

run("Duplicate...", "duplicate");
run("Median...", "radius=20 stack");
imageCalculator("Subtract create stack", "Composite","Composite-1");

selectWindow("Result of Composite");
run("Make Binary", "method=Default background=Dark calculate");
run("Dilate", "stack");
run("Erode", "stack");

run("Split Channels");
selectWindow("C1-Result of Composite");
start = getTime();
run("3D Objects Counter", "threshold=128 slice=30 min.=5 max.=62914560 objects"); 

selectWindow("C2-Result of Composite");
start = getTime();
run("3D Objects Counter", "threshold=128 slice=30 min.=5 max.=62914560 objects"); 

Java Code:

DirectoryChooser directoryChooser = new DirectoryChooser();
File selectedDirectory = directoryChooser.showDialog(dialog);

File[] files = selectedDirectory.listFiles(fileFilter);
for (int i = 0; i < files.length; i++) {
	imp = IJ.openImage( files[i].getPath() );
	IJ.run(imp, "RGB Stack", "");

ImagePlus imagePlus = new ImagePlus("temp", stack);
imagePlus = HyperStackConverter.toHyperStack(imagePlus, channels-1, nSlices, 1, "xyzct", "color");
ImagePlus imagePlusDuplicate = new Duplicator().run(imagePlus);

IJ.run(imagePlusDuplicate,"Median...", "radius=15 stack");
ImageCalculator imageCalculator = new ImageCalculator();
ImagePlus imagePlusfiltered = imageCalculator.run("Subtract create stack", imagePlus, imagePlusDuplicate);

ImagePlus threeDCount = new Duplicator().run(imagePlusfiltered);
IJ.run(threeDCount, "Make Binary", "method=Default background=Default calculate");

ImagePlus[] channelImages = ChannelSplitter.split(threeDCount);

final long startTime = System.nanoTime();
Counter3D counter;
for (int ch=1 ; ch <= threeDCount.getNChannels(); ch++) {
    counter = new Counter3D(channelImages[ch-1], 128, 5, 2097152, false, false);
long seconds = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime);

the most important step in region analysis is “region label”, I did not know if you use the java code in the right way, But as I know, the “system.out.print” cost much time, try to remove this line?

1 Like

some label function of different libs, and their cost:

import numpy as np
import scipy.ndimage as ndimg
from skimage.measure import label as skimage_label
from scipy.ndimage import label as scipy_label
from skimage.io import imread, imsave
from time import time
from cv2 import connectedComponents as cv_label

''' generate a random mask image (2d)
img = np.zeros((2048, 2048), dtype=np.float32) 
img.ravel()[np.random.randint(0, 2048**2, 3000)] = 1
msk = ndimg.gaussian_filter(img, 5) > 0.001
imsave('msk.png', msk*255)

# read the generated image
img = imread('msk.png')

start = time()
# 0.052 s

start = time()
# 0.025 s

start = time()
# 0.009 s

So OpenCV is the fastest

My result: OpenCV > Scipy > scikit-image
but OpenCV support only 2D
So you can compair (imagej, cv, scipy, skimage) in 2D
And compair (imagej, scipy, skimage) in 3D

1 Like