ImageCalculator acting weird in java macro

imagej
java
qupath

#1

I am trying to do color threshold using a java macro, but I am getting some strange results.
In the following code, imps is a list of three ImagePlus objects, each representing a different color (I’ve checked). I do two consecutive AND operations to get the intersection of all three colors, but instead of getting a Black/White image of the intersection, I am getting a black/Maroon/Red image that looks like a weird mix of some of the structures I removed with the AND operations.

    for (c= 0; c < 3; c++) {
        min[c] = rgbcolor[c] + 0
        max[c] = rgbcolor[c] + 0
        filter[c] = "pass"
    }
    for (i=0;i<3;i++){
        ip = imps[i].getProcessor()
        ip.setThreshold(min[i], max[i], 1)
    }
    ImageCalculator ic = new ImageCalculator()
    redgreen = ic.run("AND create", imps[0], imps[1])
    redgreenblue = ic.run("AND create", redgreen, imps[2])
    return redgreenblue

Does anyone have any idea what is going on? I tested it manually and it worked as expected, so I have no idea where the error lies.


#2

Is it possible that your imps[0], imps[1], etc. each are RGB type images (and thus return a ColorProcessor instead of a ByteProcessor or ShortProcessor)?


#3

I’m not completely sure, but I believe I tried to use converttobyteprocessor before, just to rule that one out. Is there an easy way to tell? Like a command that gives the type?


#4

When running imps[0].getProcessor().getCurrentColorModel() (for example) I get the follwing line: IndexColorModel: #pixelBits = 8 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@4958ead8 transparency = 1 transIndex = -1 has alpha = false isAlphaPre = false
Does that mean, as I suspect, that I somehow have RGB values in my images, even though they have been converted to ByteProcessor? And if so, how do I convert them to grayscale?

Sorry, I’m asking so many (probably) simple questions!


#5

Okay, so I managed to get the images converted to black and white using ImageConverter() and then I hit a new wall because the threshold was set but not applied. I got around this by copying the code from the protected method applyThreshold, because it appears the the Thresholder().run(arg) cannot be directed at a specific image, but just grabs the most recently active image, and I’m not sure how to control that behavior. Nonetheless I now have a working threshold mechanic, but now I’m back with a weird behavior of ImageCalculator: It looks like using redgreen = ic.run("AND create", imps[0], imps[1]) is actually resulting in the UNION of the two images rather than the INTERSECTION of the two images. I have attached an example to better explain.


The leftmost image is my original. The following three images are the individual channels with a threshold applied (imps[0], imps[1] and imps[2]). As you can see, I am trying to isolate the black color (I set blackBackground = false).
The second image from the right is the result of executing the line
redgreen = ic.run("AND create", imps[0], imps[1]),
while the rightmost image is the result of executing
redgreenblue = ic.run("AND create", redgreen, imps[2])
To me, it looks a whole lot like ImageCalculator is actually performing an OR operation rather than an AND operation. Any insights to what the solution might be?


#6

I figured it out now. Its because ImageCalulator is comparing White rather than Black and so regions that are not white in both images become black. The solution would be either to invert the images before the operation or, as I have now done, use Or rather than AND, which gives the intended result. The reason for this being (if anyone is interested) that now if pixel is white in either image, it will be white in the result. Since I am trying to find the regions that are only black, this works exactly as I would like it to.