imagej / imagej-ops

ImageJ Ops: "Write once, run anywhere" image processing
https://imagej.net/libs/imagej-ops
BSD 2-Clause "Simplified" License
88 stars 42 forks source link

Frangi Vesselness spacing #608

Closed carshadi closed 5 years ago

carshadi commented 5 years ago

I am having an issue running the "frangiVesselness" OP on a 2D image with 3 color channels. The image is "FluorescentCells.tif" found in the Fiji samples. Since the image has 2 spatial dimensions, i would expect that the spacing parameter would only require the pixel width and height. However, inputting just these two values for spacing produces an error when running the Frangi OP (which is absolved by adding a third value to the spacing array):

Traceback (most recent call last):
  File "C:\Users\arshadic\Desktop\issue_repor.py", line 29, in <module>
java.lang.ArrayIndexOutOfBoundsException
java.lang.ArrayIndexOutOfBoundsException: java.lang.ArrayIndexOutOfBoundsException

    at org.python.core.Py.JavaError(Py.java:552)
    at org.python.core.Py.JavaError(Py.java:543)
    at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
    at org.python.core.PyObject.__call__(PyObject.java:438)
    at org.python.core.PyMethod.instancemethod___call__(PyMethod.java:237)
    at org.python.core.PyMethod.__call__(PyMethod.java:228)
    at org.python.core.PyMethod.__call__(PyMethod.java:218)
    at org.python.pycode._pyx37.f$0(C:/Users/arshadic/Desktop/issue_repor.py:29)
    at org.python.pycode._pyx37.call_function(C:/Users/arshadic/Desktop/issue_repor.py)
    at org.python.core.PyTableCode.call(PyTableCode.java:171)
    at org.python.core.PyCode.call(PyCode.java:18)
    at org.python.core.Py.runCode(Py.java:1614)
    at org.python.core.__builtin__.eval(__builtin__.java:497)
    at org.python.core.__builtin__.eval(__builtin__.java:501)
    at org.python.util.PythonInterpreter.eval(PythonInterpreter.java:259)
    at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:57)
    at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:31)
    at javax.script.AbstractScriptEngine.eval(Unknown Source)
    at org.scijava.script.ScriptModule.run(ScriptModule.java:160)
    at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
    at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
    at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
    at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ArrayIndexOutOfBoundsException

Steps to reproduce:

# @ImageJ ij

# Load the input image
input_image = ij.io().open('FluorescentCells.tif')

# Convert input image to float, since we are dealing with derivatives
float_input = ij.op().run("convert.float32", input_image)

# Get dimensions of image (2D with 3 color channels)
dimensions = input_image.numDimensions()
print(dimensions) # output: 3

# scale parameter
scale = 1

# Obtain X and Y spatial calibration
x_spacing = float_input.averageScale(0)
y_spacing = float_input.averageScale(1)
spacing = [x_spacing, y_spacing]

# However, since this image is a 2D image with multiple color channels,
# the 3rd dimension is channel
print(float_input.axis(0).type()) # output: X 
print(float_input.axis(1).type()) # output: Y
print(float_input.axis(2).type()) # output: Channel

# Create placeholder image for the output then run the Frangi op
output = ij.op().run("create.img", float_input)
ij.op().run("frangiVesselness", output, float_input, spacing, scale) # fails due to not enough values in spacing array

Adding a third value to spacing avoids this error and the plugin runs successfully. My question is: what should this third value be for an image with 2 spatial dimensions? The average "scale" of the channel dimension? print(float_input.axis(2).scale()) #output: 1.0 I am somewhat confused since the plugin page https://imagej.net/Frangi implies that this value should be pixel depth, which i would think is absent in a 2D image.

carshadi commented 5 years ago

As an addendum, running this op on Blobs.gif (2D single channel) runs as expected with only pixel width and height as the 2 elements of the spacing array.

ctrueden commented 5 years ago

@gselzer Can you please investigate this?

gselzer commented 5 years ago

Hi @ctrueden and @carshadi,

I'm sorry that you are having trouble with the filter. Unfortunately this particular filter only works on grayscale images (See this javadoc) (@ctrueden is there somewhere else that we should be putting this information?) Within ImageJ-Ops there is no way to specify that the input only has two spatial dimensions, and because of this the Op assumes that if you pass through an image with three dimensions, all three of those dimensions are spatial. Furthermore, even if the Op knew it was an RGB image, the colors would mean little since there is really no standardized meaning to color as far as vessel analysis goes (i.e. different imaging techniques will show different colors) Thus I cannot recommend a spacing value for you. You can, however, collapse the third dimension of your image down through some grayscaling process, which would allow the filter to work as expected. You can find help doing this on the image.sc forum. Let me know if you have any other questions!

Best,

Gabe

carshadi commented 5 years ago

I see, makes sense.

Thanks for your help!