ImageJ HyperStacks have a data type (8-32 bit), a width, a height, a number of channels, a number of slices and a number of frames. They represent 5D (XYCZT) data sets. ImageJ stores them as multipage tiff files where number of channels times number of slices times number of frames 2D (XY) images are stored. The first image seems to have two custom tags with IDs 50838 and 50839.
I want to create tif files containing 5D data from Matlab that can be read by ImageJ as a valid 5D HyperStack.
I can store a number of 2D images in a multipage tiff file in Matlab using imwrite(matrix, file, 'WriteMode','append') but ImageJ will read that as 3D (XYZ) image stack only. The information about the channels, slices and frames is not contained.
I guess I could look at the ImageJ sources to find out where they store this missing information, then use Matlab's wrapper of LibTIFF to recreate the meta information of ImageJ. If you, however, already know what to do or if there is an alternative, I would like to hear it.
I also thought that Bio-Fomats was the only way. But then I realized that Fiji's ImageJ-MATLAB allows you to pass MATLAB data to ImageJ. Then, you can save the image by ImageJ, so ImageJ can open it for sure.
The problem was that people (or just one guy?) created ImageJ-MATLAB did a great job in creating a route from MATLAB to ImageJ, but they didn't seem to bother optmizing the behaviour. ImageJ-MATLAB's IJM.show('name') had a lot of hidden or undocumented limitations (I massively changed the documentation, so it should be clearer now). Eventually, I enede up wriring a wrapper function
ijmshow
https://github.com/kouichi-c-nakamura/ijmshow
Example MATLAB code
You can do it with 4 lines.
addpath '/Applications/Fiji.app/scripts' % depends your Fiji installation
ImageJ
imp = ijmshow(I,'YXCZT') % I is 5D array of uint8 or uint16
% the second argument determines which dimension represents what
% imp is a 5D hyperstack
ij.IJ.saveAsTiff(imp, 'image1.tif');
You may want to set Display Range of each channel before saving.
Added on 5/7/2018
copytoImagePlus provides better solution than ijmshow above (you can use the same syntax), because copytoImagePlus does not rely on the IJM variable in the base workspace anymore.
https://github.com/kouichi-c-nakamura/copytoImagePlus
addpath '/Applications/Fiji.app/scripts' % depends your Fiji installation
ImageJ
imp = copytoImagePlus(I,'YXCZT') % I is 5D array of uint8 or uint16
% the second argument determines which dimension represents what
% imp is a 5D hyperstack
ij.IJ.saveAsTiff(imp, 'image1.tif');
Also see copytoImgPlus which create ImageJ2 ImgPlus object instead.
https://github.com/fiji/fiji/blob/master/scripts/copytoImgPlus.m
ImageJ uses the ImageDescription tag of the TIFF's first IFD to store its meta-information. Here is an example from the Mitosis sample dataset (File > Open Samples > Mitosis):
ImageJ=1.51d
images=510
channels=2
slices=5
frames=51
hyperstack=true
mode=composite
unit=\u00B5m
finterval=0.14285714285714285
loop=false
min=1582.0
max=6440.0
MATLAB's Tiff class might give you fine-grained enough control to write a custom ImageDescription to the first IFD; I am not sure.
Probably easier would be to use the Bio-Formats library's bfsave.m function to write OME-TIFF, which can be 5-dimensional; ImageJ can read this format via the Bio-Formats plugin. I recommend using the Fiji distribution of ImageJ, which comes with Bio-Formats pre-installed.
There was also this same question posted on MATLAB Central.
Using Matlab's Tiff class.
I can assemble an ImageDescription tag that I think looks fine and ImageJ reads it (File>Open) as a 5D Hyperstack but the data is partly corrupted. There seem to be offset problems (I can read the data just fine in again with Matlab).
However, if reading the tiff file with File>Import>Bio-Formats it becomes 5D (XYCZT) stack in ImageJ if view stack with Hyperstack is marked in the Bio-Formats import dialog. Thanks to ctrueden for his helpful comment.
d = ones(100, 200, 10, 2, 3, 'single') * 3.765;
hyperstack_write('test.tif', d);
function hyperstack_write(file, hyperstack)
% Writes an (up to) 5D stack into a (XYCZT) HyperStack Tiff file
% readable by ImageJ
%
% hyperstack must have class single
% simple checks
assert(nargin == 2, 'Not enough arguments');
assert(isa(hyperstack, 'single'), 'hyperstack must be single');
% get all five dimensions
d = zeros(5, 1);
for i = 1 : 5
d(i) = size(hyperstack, i);
end
% assemble image description
s = sprintf('ImageJ=1.51\nnimages=%d\nchannels=%d\nslices=%d\nframes=%d\nhyperstack=true\nmode=color\nloop=false\nmin=%.1f\nmax=%.1f\n', prod(d(3:5)), d(3), d(4), d(5), floor(min(hyperstack(:))*10)/10, ceil(max(hyperstack(:))*10)/10);
% open tif file for writing and set file tags
t = Tiff(file, 'w');
ts.ImageLength = d(1);
ts.ImageWidth = d(2);
ts.Photometric = Tiff.Photometric.MinIsBlack;
ts.Compression = Tiff.Compression.None;
ts.BitsPerSample = 32;
ts.SamplesPerPixel = 1;
ts.SampleFormat = Tiff.SampleFormat.IEEEFP;
ts.RowsPerStrip = 5;
ts.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
ts.Software = 'MATLAB';
ts.ImageDescription = s;
% loop over dimensions 3, 4, and 5
for k = 1 : d(5)
for j = 1 : d(4)
for i = 1 : d(3)
frame = hyperstack(:, :, i, j, k);
t.setTag(ts)
t.write(frame);
t.writeDirectory();
end
end
end
% close tif file
t.close();
end
It seems Bio-Formats is the only fully paved and available way to export >2D data from Matlab to ImageJ, although this solution here could be a lightweight alternative in cases where not much metadata is available and needs to be transferred.
Related
For exmaple,I have the following code.
% Generate random data from a uniform distribution
% and calculate the mean. Plot the data and the mean.
n = 50; % 50 data points
r = rand(n,1);
plot(r)
% Draw a line from (0,m) to (n,m)
m = mean(r);
hold on
plot([0,n],[m,m])
hold off
title('Mean of Random Uniform Data')
for v = 1.0:-0.2:0.0
disp(v)
end
I want to convert MATLAB code to an image.
For example, if you copy the MATLAB code into a software then it return the image like this:
How to do it?
If I use this code and publish it to PDF file,the code is not completely display.
sumLumi(x,y)=LLmap3(floor(x/4)+1,floor(y/4)+1)+LLmap3(floor(x/4)+2,floor(y/4)+1)+LLmap3(floor(x/4)+1,floor(y/4)+2)+LLmap3(floor(x/4)+2,floor(y/4)+2);
From the MATLAB editor you can Publish your document as a PDF (by changing the Output file format to pdf under publishing options). It will also evaluate the code unless you change the Publishing Options>Code Settings>Evaluate code to false.
The PDF can then can converted to an image (a quick google search gives an online PDF to JPG converter).
You can break a line and continue on the next with ..., for example
sumLumi(x,y)=LLmap3(floor(x/4)+1,floor(y/4)+1)+LLmap3(floor(x/4)+2,floor(y/4)+1)+LLmap3(floor(x/4)+1,floor(y/4)+2)+LLmap3(floor(x/4)+2,floor(y/4)+2);
can be written as
sumLumi(x,y) = LLmap3(floor(x/4)+1, floor(y/4)+1) ...
+ LLmap3(floor(x/4)+2, floor(y/4)+1) ...
+ LLmap3(floor(x/4)+1, floor(y/4)+2) ...
+ LLmap3(floor(x/4)+2, floor(y/4)+2);
If you want to use Matlab only you can use this workflow:
Make your code to be single .m file. Any text file will work.
Read this file in cell column vector Code;
Process the lines adding using TeX or LaTeX formatting commands;
Create white figure with text(x,y,Code);
Export the figure.
This might be good way to produce many figures with same style.
I'm using MATLAB_R2011a_student. I have some image stacks saved as 32 bit tiffs, some over 1000 frames. I would like to be able to pull out a specific frame from the stack and save it as a 32 bit tiff or some readable format where there would be no data loss from the original. Currently my code looks like this:
clear, clc;
k=163;
image=('/Users/me/Filename.tiff');
A = uint8(imread(image, k));
B=A(:,:,1);
J=imadjust(B,stretchlim(B),[]);
imwrite(J,'/Users/me/163.tif','tif');
(I'm assuming reading it as 8 bit, and the way I'm saving are not the best way to do this)
Either way this code works for a seemingly random number of frames (for example in one file.tiff the above code works for frames 1-165 but none of the frames after 165, for a different file.tiff the code works for frames 1-8 but none of the frames after 8) I'm also getting a strange horizontal line in the output image when this does work:
??? Error using ==> rtifc
Invalid TIFF image index specified.
Error in ==> readtif at 52
[X, map, details] = rtifc(args);
Error in ==> imread at 443
[X, map] = feval(fmt_s.read, filename, extraArgs{:});
Thanks!
The best way (in my opinion) to handle tiff stacks is to use the Tiff library available since a few years. I must admit that I don't know much about OOP but I managed to understand enough to load a tiff stack and manipulate it.That's the kind of simple demo I wish I had seen a year ago haha.
I the following example I load a single stack and store it all into a 3D array. I use imfinfo to fetch infos about the images, notably the number of images/stack and the actual image dimensions. If you want you can choose to load only one image using appropriate indices. Please try the code below and play around with it; you'll understand what I mean.
clear
clc
%// Get tiff files you wish to open
hFiles = dir('*.tif');
%// Here I only have 1 multi-tiff file containing 30 images. Hence hInfo is a 30x1 structure.
hInfo = imfinfo(hFiles(1).name);
%// Set parameters.
ImageHeight = hInfo(1).Height;
ImageWidth = hInfo(1).Width;
SliceNumber = numel(hInfo);
%// Open Tiff object
Stack_TiffObject = Tiff(hFiles.name,'r');
%// Initialize array containing your images.
ImageMatrix = zeros(ImageHeight,ImageWidth,SliceNumber,'uint32');
for k = 1:SliceNumber
%// Loop through each image
Stack_TiffObject.setDirectory(k)
%// Put it in the array
ImageMatrix(:,:,k) = Stack_TiffObject.read();
end
%// Close the Tiff object
Stack_TiffObject.close
Hope that helps.
I have some very large Tiff images that I am trying to use in a MATLAB GUI application. If I try to load the images using imshow, I get an out-of-memory error. (Yes, I know MATLAB is not the best choice for GUIs or loading large images, but there is good reason for using MATLAB in this case).
I can obviously create a reduced resolution data set (rset file) and use imtool to view the image, but this is not helpful as I want a user to be able to interact with the image by clicking on it to extract (x,y) coords into the application. Imshow does not seem to be directly compatible with rset files. Is there a way for me to load an rset'd image in a panable/zoomable figure, or any other way I can achieve the goal?
I looked at the code for imtool but it seems to be using undocumented classes to read rset files and I can't replicate its behaviour.
You can use low-level file I/O functions of MATLAB to read the entirety or parts of the TIFF image in order to avoid the OOM problem.
fileName = 'LargeTiff.tif';
info = imfinfo(fileName)
% Determine number of frames
nFramesStr= regexp(info.ImageDescription, 'images=(\d*)', 'tokens');
nFrames = str2double(nFramesStr{1}{1});
% Use low-level File I/O functions to read the file
fp = fopen(fileName , 'rb');
% The "StripOffsets" field provides the offset to the first strip.
fseek(fp, info.StripOffsets, 'bof');
% Assume that the image format is 16-bit per pixel and is big-endian
% Also assume that the images are stored one after the other
% For example, read the first 100 frames
frameNum = 100;
imData = cell(1, frameNum);
for cnt = 1 : frameNum
imData{cnt} = fread(fp, [info.Width info.Height], 'uint16', 0, 'ieee-be');
end
fclose(fp);
It looks like my problem is that I simply don't have enough memory to load the whole tiff, and that there is no public specification for the rset files format. So I am going to instead solve the problem by creating my own version of a reduced resolution data set. I should be able to load block sections of the image, resave them and then dynamically load and unload only the needed high-res blocks at zoom, and load a reduced resolution overview when zoomed out.
You can write a callback function to get the pixel co-ordinates (X,Y) from imtool then convert to a tile number and tile index using the code below. You can then utilise the readencodedtile function in matlab
function [tileidx,Tile_num] = getTileInfo(tiffile,X,Y)
A = Tiff(tiffile);
tile_width = A.getTag('TileWidth');
tile_length = A.getTag('TileLength');
SizeA = size(A);
tt = sub2ind(SizeA,X,Y);
% Example only
% X = repmat((1:10)',1,10);
% Y = repmat((1:10),10,1);
% A = reshape(1:100,10,10);
% SizeA = size(A);
% tile_width = 3;
% tile_length = 2;
tileidx = rem(tt-(Y-1)*SizeA(1)-1,tile_length)+1 ...
+ tile_length*rem(Y+tile_width-1,tile_width);
Tile_num = ceil(Y/tile_width)+ ...
(ceil(X/tile_length)-1)*ceil(SizeA(2)/tile_width);
I have problem on read and process multiple tiff file using MATLAB since I am beginner in MATLAM software. I have 300 of tiff images with same dimension. I want to loop the process, however, I cannot get it. Until now, I only change the file-name every time to read and process. I still don't get where should start. Can anyone help me. Here I attach my coding.
filename=('brd06330_s0239.tif');
fileinfo=imfinfo(filename);
Nfiles=numel(fileinfo);
Cloud=cell(Nfiles,1);
for n=1:Nfiles
A=imread(filename);
[rimg cimg]=size(A);
% Read by band (for this task only use band 1)
B1Channel = A(:, :, 1);
% A=imread(filename);
% [rimg cimg]=size(A);
%for channel 1
W_countB1 = sum(sum(B1Channel == 0)) % W= water
NW_countB1 = sum(sum(B1Channel > 0)) % NW= non water (cloud and land)
end
%save in text format(excel)
d=[W_countB1,NW_countB1]
colname={W_countB1,NW_countB1}
xlswrite('brd06330_s0239',d)
try dir('*.tif'), that will get you a list of all TIFFs in your directory, then you can loop the whole thing like you wanted.
it would look something like:
files=dir('*.tif');
for i=1:length(files)
A=imread(file(i).name);
%//... whatever you want to do with your TIFFs
end
hope that helps.
I have some calculation with matrices and have set my loop to run for (let's say) 50 times.
I also assigned a color to each value so I can get a picture in the end of these matrices based on their values.
What I don't know is - how to make an animation from this multiple images I get in each turn.
Is it possible?!
The following code is what I have used previously to produce an .avi file
n = 15;
p = randperm(n);
figure('Color','white');
fcount = 0;
for k = 1:n-1
% produce the plot
[idx,idx] = min(p(k:n));
p(idx+k-1) = p(k);
p(k) = k;
plot(p,'*')
% Make sure plot updates before we capture the contents
pause(0.1)
F(k) = getframe(gcf); %#ok
end
movie2avi(F,'so1.avi','fps',2,'quality',100);
However, there seems to be some issues with the avi codec now for use with Windows XP, for example see this thread.
http://www.mathworks.com/matlabcentral/newsreader/view_thread/271172
I had the same problem; the avi file produced with the default Indeo codec would not run in Windows Media Player. Using a different codec, such as
movie2avi(F,'so1.avi','fps',2,'quality',100,'compression','Cinepak');
solved the problem. You may need to experiment to find a working combination.
Hth, Darren
I'm not sure what you're trying to do. One option is to use the MS-GIF animator, although 50 images is a bit much. See http://en.wikipedia.org/wiki/Microsoft_GIF_Animator for info. Considering the number of images, you might want to create a powerpoint document.