Merging Channels

I have been trying for some time to find a solution for reading a first group of images as 1 channel and another group as the second channel and both would be viewed in one stack.

I can do that as a user for ImageJ by using,

  1. File > import > Image Sequence… twice for each channel stack image
  2. Image > Color > Make Composite image
  3. Image > Color > Channel Tools and I would change Color Model from Composite to Color image

Now I need to do this using Java,
I have created my own code to read what is in the folder of images and read in a list of datasets or images. Still I couldn’t put them in a stack and so I am using OpenFolder class and it works.

I have been trying several solutions for merging the channels and nothing worked.
a. I tried IJ.run("Merge Channels...", "c1=red channel c2=green channel"); didn’t give any results
b. Using RGBStackMerge Class it raises an exception.

ImagePlus[] in = new ImagePlus[2];
in[0] = redImg; in[1] = greenImg;
ImagePlus out;
img = RGBStackMerge.mergeChannels(in, False)
1 Like

Hi @Mourka,

merging stacks works a bit weird, I agree. I recently programmed this:

You need to collect all the processors in an ImageStack and use the HyperstackConerter to give it the right number of channels…

I hope it helps!

Cheers,
Robert

1 Like

Hi Mourka,

I run a short test:

Stack I
Size W x H x 2
Title RED
2 planes

Stack II
Size W x H x 2
Title GREEN
2 planes

Execution of Java command in plugin:
IJ.run(“Merge Channels…”, “c1=RED c2=GREEN create”);

Result:
Image stack
Size W x H x 2 x 2
Title Composite
(2 channels with 2 Z slices)

Test is working for 8bit or 16bit or 32bit images.

I assume the problem is that the title of your stacks contains a space.
See your command:
IJ.run(“Merge Channels…”, “c1=red channel c2=green channel”)

Regards
Peter

1 Like

Thank you so much for the reply it is so clear but still I am having an exception applying these lines,

ImageStack stack = new ImageStack(green.getWidth(),green.getHeight(),green.getNSlices());

stack.addSlice(green.getProcessor());
int channels = 1;

stack.addSlice(red.getProcessor());
channels ++;

ImagePlus tempImp = new ImagePlus("temp",stack); //exception
tempImp = HyperStackConverter.toHyperStack(tempImp,channels,green.getNSlices(),green.getNFrames());

Hey @Mourka,

that error message sounds like the original green image was kind of empty. Could you point us to your whole code? Is it on github?

Cheers,
Robert

It seems to be correct still I can’t use because I am not showing the API and so no images are opened.

No I am not having it on github but this is in the beginning of the code and so nothing at all happened other than reading the images.

image

ImagePlus green = new ImagePlus();
ImagePlus red = new ImagePlus();

for (int ch=1; ch <= 2 ; ch++) {
    DirectoryChooser directoryChooser = new DirectoryChooser();
    FolderOpener op = new FolderOpener();
    ImgOpener imgOpener = new ImgOpener();


    if (ch==1){
        directoryChooser.setTitle("Choose Red Images Folder");
		} else if (ch==2){
        directoryChooser.setTitle("Choose Green Images Folder");
		}

    File selectedDirectory = directoryChooser.showDialog(dialog);

    if (ch==1) {
		green = op.openFolder(selectedDirectory.getPath());
		green.setTitle("green");
		} else if(ch==2) {
			red = op.openFolder(selectedDirectory.getPath());
			red.setTitle("red");
			}
}

ImageStack stack = new ImageStack(green.getWidth(),green.getHeight(),green.getNSlices());

stack.addSlice(green.getProcessor());
int channels = 1;

stack.addSlice(red.getProcessor());
channels ++;

ImagePlus tempImp = new ImagePlus("temp",stack);
tempImp = HyperStackConverter.toHyperStack(tempImp,channels,green.getNSlices(),green.getNFrames());

The line

ImagePlus green = new ImagePlus();

Looks suspicious. This is creating an empty image and that goes in line with the error message you receive. But I’m not sure. Could you for example call

green.show();
new WaitForUserDialog("JustChecking").show();

after

green = op.openFolder(selectedDirectory.getPath());

Just to check that green is a valid image?

1 Like

Oh and wait!

If your folder contains 1000 files, this will create a stack with 1000 planes:

But you only call addSlice two times. That might be it. The other 998 slices stay null and that might cause the error.

Please go through all slices in green and add them to the stack:

for (int z = 1; z <= green.getNSlices(); z++) {
    green.setZ(z);
    stack.addSlice(green.getProcessor());
} 
1 Like

I ran it twice once selecting the red folder first time and then in the second selecting the green folder first and both runs. image

 if (ch==1) {
    green = op.openFolder(selectedDirectory.getPath());
	} else if(ch==2) {
		red = op.openFolder(selectedDirectory.getPath());
		}
		green.show();
		new WaitForUserDialog("JustChecking").show();

The following simplified version is working for me.
Maybe it helps:

public void run(String arg) {

FolderOpener op = new FolderOpener();

ImagePlus green = op.openFolder("C:\\Temp\\test\\g");
green.setTitle("green");
green.show();

ImagePlus red = op.openFolder("C:\\Temp\\test\\r");
red.setTitle("red");
red.show();

IJ.run("Merge Channels...", "c1=red c2=green create keep");

}
1 Like

I found the problem for this case

stack.addSlice(green.getProcessor());
adds only one image while I have 20 images in green and 20 images in red so what happened is the following,

ImageStack stack = new ImageStack(green.getWidth(),green.getHeight(),green.getNSlices()); // reserved 20 images from 0 to 19 (all are empty)
stack.addSlice(green.getProcessor()); // reserved 1 (#20) (first green image)
stack.addSlice(green.getProcessor()); // reserved 1 (#21) (first red image)
Object[] arrays = stack.getImageArray(); // The array already knew that it 
// should be of 40 arrays with first 20 to #19 are nulls and filled #20 and #21 
// and the rest are nulls to the #40

So I changed the code to,

ImageStack stack = new ImageStack(green.getWidth(),green.getHeight());

int channels = 1;
for (int i=1; i < red.getNSlices()+1 ; i++) {
    stack.addSlice(red.getStack().getProcessor(i));
}

channels ++;
for (int i=1; i < green.getNSlices()+1 ; i++) {
    stack.addSlice(green.getStack().getProcessor(i));
	}
                
ImagePlus tempImp = new ImagePlus("temp",stack);
tempImp = HyperStackConverter.toHyperStack(tempImp,channels,green.getNSlices(),green.getNFrames());

the images are filling the first 40 in the array but somehow the array became of size 50 which I don’t know why but I will add up once I find something.

1 Like

I don’t see a solution for this as the default value added for creating a stack is 25
ImageStack(green.getWidth(),green.getHeight());
and so I use addSlide filling all but I have extra 5 for each red and green and so I have extra 10 nulls in the array at its end.

When I set the size as 20
ImageStack stack = new ImageStack(green.getWidth(),green.getHeight(),green.getNSlices());
The sum is 80, 40 filled and 40 empty. I don’t know how to solve that.

1 Like

Could you please share your whole code again? That makes it easier for us to help you as we cannot look at your screen :wink:

I am having another exception in the last line in the code.
I can see the images of red and green in consequence which is a step forward.
But I have the stack array with 10 Nulls at the end and I am not sure if this is causing the problem.

The exception that I am having now I am showing it in the images below,

ImagePlus green = new ImagePlus();
ImagePlus red = new ImagePlus();

for (int ch=1; ch <= 2 ; ch++) {
    DirectoryChooser directoryChooser = new DirectoryChooser();
    FolderOpener op = new FolderOpener();
    ImgOpener imgOpener = new ImgOpener();


    if (ch==1){
        directoryChooser.setTitle("Choose Red Images Folder");
		} else if (ch==2){
        directoryChooser.setTitle("Choose Green Images Folder");
		}

    File selectedDirectory = directoryChooser.showDialog(dialog);

    if (ch==1) {
		green = op.openFolder(selectedDirectory.getPath());
		green.setTitle("green");
		} else if(ch==2) {
			red = op.openFolder(selectedDirectory.getPath());
			red.setTitle("red");
			}
}

ImageStack stack = new ImageStack(green.getWidth(),green.getHeight());

int channels = 1;
for (int i=1; i < red.getNSlices()+1 ; i++) {
    stack.addSlice(red.getStack().getProcessor(i));
    }

channels ++;
for (int i=1; i < green.getNSlices()+1 ; i++) {
    stack.addSlice(green.getStack().getProcessor(i));
    }

Object[] arrays = stack.getImageArray();

ImagePlus tempImp = new ImagePlus("temp",stack);
tempImp.show();
tempImp = HyperStackConverter.toHyperStack(tempImp,channels,green.getNSlices(),green.getNFrames()); // Exception


Hey @Mourka,

this error message tells you that the individual images (which are supposed to be green or red only) are in fact 3-channel RGB images. You need to convert them to 8, 16 or 32 bit (or crop out a channel). Before I now give a wrong hint how to do that, would you mind sharing an example image?

Thanks!

Cheers,
Robert

1 Like

I sent you a private message and I was actually expecting to meet this problem sooner or later. When I use ImageJ as a user, I see that it gets the channel color and show me only one channel but when I open with different opener or apply a filer after it was opened as dataset then I see that

1 Like

Then I would suggest you navigate with a loop through the folder and open the images one by one with ImagePlus imp = IJ.openImage(filename); and add its processor to the stack. Then you avoid the conversion issue :wink:

1 Like

I created the code but I still see using ImagePlus imp = IJ.openImage(filename); open the images in RGB, Is there something I am missing?

Ok, I just checked your images. They are indeed RGB as you can see here:
image

You can convert them to a three-channel image by calling

IJ.run(imp, "RGB stack", "");

Afterwards, you can set the current channel and get the corresponding channel processor:

imp.setC(1); // red
stack.addSlice(imp.getProcessor());

Does that help?

Cheers,
Robert

1 Like