Analysis of binarized images to discriminate elements expressing other elements

Hi there,

I am trying to to tell whether a binarized profile element (in blue in the attached image) has any elements from another channel (green) or both (green and red) within that same profile. I have been thinking about it, but I don’t know how I could tell the macro to count elements in one image that has any number of dots of each other channel.
Please have a look to the image to get a better idea of what I mean. So the final question is how many blue elements have both green and red dots (any number of, but if that could also be quantified it would be good too).
example

Thanks a lot in advance!

1 Like

Welcome to the forum, @rguiradoguillen!

You could do some scripting with nested loops over ROIs to count objects in one channel that overlap with other objects in another channel, but this is currently a bit cumbersome to do in ImageJ.

For this task I’d recommend using KNIME, as it has excellent functionality to deal with overlapping labels (actually, it is ImgLib2 that provides this functionality, but it’s currently more easily accessible in KNIME than in ImageJ).

Here’s a workflow that illustrates how to count the red and green spots overlapping with your blue objects (download the knwf file and drag it to your local KNIME installation to try):

Label analysis.knwf (83.7 KB)


The result looks like this (where question marks ? mean no overlapping objects):

7 Likes

Hi @rguiradoguillen,

One solution to your question could be using the Binary Feature Extractor from the BioVoxxel Toolbox. Installation instructions can be found here.

This will give you the objects (in your case the nuclei) which contain other objects (your spots). Therefore, both images you want to compare need to be binary. Unfortunately, so far the tool only compares 2 images. So, you need to run it for the red and the green sports separately and finally can even run it on the extracted nuclei from the first two comparisons to get only those nuclei which contain both (red and green spots).

By using the macro recorder (Plugins ► Macros ► Record…) you can combine these tasks.

Another solution would be to use the Speckle Inspector from the toolbox.

Hopefully, in not so far future, this might be combinable with KNIME.

5 Likes

Hi biovoxxel,
I have tried the approach you suggested using your plugin and I got good results. However, I am now trying to set up a macro for batch analysis, and got a problem, in imageJ macro language I always use a getImage command to get the active image as for example: id
Then I use id+1, id+2 and so on for the rest of the channels opened after splitting channels, so I wonder if it is possible to give such commands to the plugin. I have tried to use this line:

run("Binary Feature Extractor", "objects=[id] selector=[id+1] object_overlap=0 count");

Basically changing the long name of the original image name for id and id+1 so it can run then in batch mode, but I get a java exception. Any suggestions how could I work around this problem?

Thanks a lot!

Hi Jan,

Thanks for your suggestion of using KNIME, I registered and installed it to give it a try, but definitely I still need to read more and or watch some tutorials (I have seen there are some around), I was able to open the workflow, but I don’t know how to feed the images to it yet.
I will give it a try!

Thanks a lot!

1 Like

You can add the images in the recorded plugin by calling their image names with getTitle();.
If you include a split channels command generally the images are named according to a consistent principle. This depends on if the starting image is a composite with separate channels or an RGB. In composites it adds the prefix “C1-” “C2-” etc. and in RGB images it adds the suffixes (red), (green) or (blue).

In the latter case the following snippet should do the job.

originalImage = getTitle();
run("Split Channels");
run(“Binary Feature Extractor”, “objects=["+originalImage+" (blue)] selector=["+originalImage+" (green)] object_overlap=0 count”);

make sure that your variables are always excluded from quoted text to ensure their proper usage.

3 Likes

Hi biovoxxel,

Thank you for your feedback, now I’m quite sure the code is right, but the java exception is still appearing and no results returned, I feel maybe I have messed up when updating Fiji (I didn’t de-select anything when updating as it wasn’t very clear on the instructions) to add the biovoxxel plugin.

I paste here the exception and if you think it can be the code I can post it too

(Fiji Is Just) ImageJ 2.0.0-rc-61/1.51n; Java 1.8.0_66 [64-bit]; Mac OS X 10.12.6; 173MB of 8808MB (1%)
java.lang.NullPointerException
	at Binary_Feature_Extractor.run(Binary_Feature_Extractor.java:94)
	at ij.plugin.filter.PlugInFilterRunner.processOneImage(PlugInFilterRunner.java:265)
	at ij.plugin.filter.PlugInFilterRunner.<init>(PlugInFilterRunner.java:114)
	at ij.IJ.runUserPlugIn(IJ.java:219)
	at ij.IJ.runPlugIn(IJ.java:181)
	at ij.Executer.runCommand(Executer.java:137)
	at ij.Executer.run(Executer.java:66)
	at ij.IJ.run(IJ.java:297)
	at ij.macro.Functions.doRun(Functions.java:601)
	at ij.macro.Functions.doFunction(Functions.java:96)
	at ij.macro.Interpreter.doStatement(Interpreter.java:230)
	at ij.macro.Interpreter.doBlock(Interpreter.java:608)
	at ij.macro.Interpreter.doStatement(Interpreter.java:272)
	at ij.macro.Interpreter.doFor(Interpreter.java:530)
	at ij.macro.Interpreter.doStatement(Interpreter.java:254)
	at ij.macro.Interpreter.doStatements(Interpreter.java:218)
	at ij.macro.Interpreter.run(Interpreter.java:115)
	at ij.macro.Interpreter.run(Interpreter.java:85)
	at ij.macro.Interpreter.run(Interpreter.java:96)
	at ij.plugin.Macro_Runner.runMacro(Macro_Runner.java:155)
	at ij.IJ.runMacro(IJ.java:134)
	at ij.IJ.runMacro(IJ.java:123)
	at net.imagej.legacy.IJ1Helper$3.call(IJ1Helper.java:1052)
	at net.imagej.legacy.IJ1Helper$3.call(IJ1Helper.java:1048)
	at net.imagej.legacy.IJ1Helper.runMacroFriendly(IJ1Helper.java:999)
	at net.imagej.legacy.IJ1Helper.runMacro(IJ1Helper.java:1048)
	at net.imagej.legacy.plugin.IJ1MacroEngine.eval(IJ1MacroEngine.java:136)
	at org.scijava.script.ScriptModule.run(ScriptModule.java:159)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:167)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:126)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:65)
	at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:237)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

Hi @rguiradoguillen,

that looks to me like as if you gave the plugin only a single image to process while it needs two. It cannot handle image slices in a stack but rather needs each image in its own frame. Potentially you can past your macro code or a part of it here to be able to better troubleshoot.

Hi @biovoxxel,

Thanks a lot, I have already a functioning macro. I think the problem was that the getTitle was after, not before the split channels. I also still need the getImageID to play around (in this case, inverting the black/white, as well as with the result image after the extraction)
I did try with the “binarized” image I started this thread with, to keep it simple and it worked nicely, now I have just added those to the long and messed macro I use for automatically binarizing images and given % of histograms and it works good too. Here the simple code for the example image:

origen = getDirectory("Images to process");
lista = getFileList(origen);
setBatchMode(true);
for (j=0; j<lista.length; j++) { 
       showProgress(j+1, lista.length);
       open(origen+lista[j]);
       nombre = lista[j];
       originalImage = getTitle();
       run("Split Channels");
       id = getImageID();
       selectImage(id);
       run("Invert");
       selectImage(id+1);
       run("Invert");
       selectImage(id+2);
       run("Invert");
       run("Binary Feature Extractor", "objects=["+originalImage+" (blue)] selector=["+originalImage+" (green)] object_overlap=0 count");
       originalImage2 = getTitle();
       run("Invert");
       run("Binary Feature Extractor", "objects=["+originalImage2+"] selector=["+originalImage+" (red)] object_overlap=0 count");
       }
2 Likes

glad that it works :slight_smile:

1 Like