Effacer les filtres
Effacer les filtres

convert tiff to only one image and to RGB

26 vues (au cours des 30 derniers jours)
Maria Penas Leonor
Maria Penas Leonor le 4 Juin 2020
Modifié(e) : DGM le 31 Juil 2024 à 22:42
Hello!
I have the following tiff (https://files.fm/u/k646knpn) which is a stack that contains 81 slices. I really do not know much about the tiff, the channels it has or anything. When I open the tiff with ImageJ and I overlap the stack I get the following image:
That´s exactly what I would like to do with matlab. Transform the tiff into only one picture that is the overlapping of all the slices and in RGB. Any idea of how to do it?
Thank you very much

Réponses (1)

Harsh
Harsh le 31 Juil 2024 à 11:29
Modifié(e) : Walter Roberson le 31 Juil 2024 à 22:35
Hey,
From what I can gather, you are trying to convert a "tif" file into one picture with all slices of it overlapping and in RGB. Here’s a MATLAB to do the same:
% Specify the file name
filename = 'at3_1m4_01.tif';
% Get the information about the TIFF file
info = imfinfo(filename);
num_slices = numel(info);
% Preallocate a 3D array to store the slices
slice = imread(filename, 1);
[height, width] = size(slice);
stack = zeros(height, width, num_slices, 'uint16');
% Read each slice into the stack
for k = 1:num_slices
stack(:, :, k) = imread(filename, k);
end
% Normalize the stack to the range [0, 1]
stack = double(stack);
stack = stack / max(stack(:));
% Create an RGB image by averaging the slices
rgbImage = zeros(height, width, 3);
% Assuming the stack is grayscale, convert to RGB by averaging
for k = 1:num_slices
rgbImage(:, :, 1) = rgbImage(:, :, 1) + stack(:, :, k) / num_slices;
rgbImage(:, :, 2) = rgbImage(:, :, 2) + stack(:, :, k) / num_slices;
rgbImage(:, :, 3) = rgbImage(:, :, 3) + stack(:, :, k) / num_slices;
end
% Normalize the RGB image to the range [0, 1]
rgbImage = rgbImage / max(rgbImage(:));
% Display the RGB image
imshow(rgbImage);
% Optionally, save the RGB image to a file
imwrite(rgbImage, 'output_image.png');
Here’s the output that I was able to get using a sample "tif" file,
Here, I have attached a MathWorks documentation which talks about how you can read, write and query image files, feel free to check it out:
I hope this helps, thanks!
  1 commentaire
DGM
DGM le 31 Juil 2024 à 22:22
Modifié(e) : DGM le 31 Juil 2024 à 22:42
From the question, we know that the output is RGB. From the image, we might guess that the source image is probably some sort of pseudocolor image. OP never mentioned any sort of colormapping process which would have otherwise explained the presence of color content in the output.
So we have some sort of multiframe color image, and we need to somehow flatten it. Taking the frame average is a reasonable guess of what's intended, but this example doesn't work on color inputs, and there are other issues. This example is an overcomplicated demonstration of how to repeatedly rescale a single-frame grayscale image and replicate it to have three channels.
% Specify the file name
% the filename is case-sensitive
% it would make sense to pick an example with more than one frame
filename = 'AT3_1m4_01.tif'; % a single-frame image
% Get the information about the TIFF file
info = imfinfo(filename);
num_slices = numel(info);
% Preallocate a 3D array to store the slices
slice = imread(filename, 1);
[height, width] = size(slice); % this will be wrong if the image is RGB
stack = zeros(height, width, num_slices, 'uint16'); % why presume uint16?
% Read each slice into the stack
% this will also fail if the input is RGB
for k = 1:num_slices
stack(:, :, k) = imread(filename, k);
end
% Normalize the stack to the range [0, 1]
% this doesn't normalize to the data extrema
% unless the data actually extends to exactly 0
% it's not clear why we're normalizing at all anyway
stack = double(stack);
stack = stack / max(stack(:));
% Create an RGB image by averaging the slices
rgbImage = zeros(height, width, 3);
% Assuming the stack is grayscale, convert to RGB by averaging
% this is all redundant
for k = 1:num_slices
rgbImage(:, :, 1) = rgbImage(:, :, 1) + stack(:, :, k) / num_slices;
rgbImage(:, :, 2) = rgbImage(:, :, 2) + stack(:, :, k) / num_slices;
rgbImage(:, :, 3) = rgbImage(:, :, 3) + stack(:, :, k) / num_slices;
end
% Normalize the RGB image to the range [0, 1]
% same issues as before.
rgbImage = rgbImage / max(rgbImage(:));
% Display the RGB image
imshow(rgbImage);
Consider the following multiframe image:
While that's a GIF (indexed color), the same image is attached as a multiframe RGB TIFF.
% TIFF files can't be attached directly on the forum
unzip bballpcolor.tif.zip
% Specify the file name
filename = 'bballpcolor.tif';
% Get the information about the TIFF file
info = imfinfo(filename);
num_slices = numel(info);
% Preallocate a 3D array to store the slices
slice = imread(filename, 1);
[h,w,ch,~] = size(slice); % get the actual array size
stack = zeros([h w ch num_slices],class(slice)); % use the actual source class
% Read each slice into the stack
for k = 1:num_slices
stack(:, :, :, k) = imread(filename, k);
end
% unless there's an explicit need to normalize to data extrema, then don't.
% put the data in proper unit-scale float
stack = im2double(stack); % normalize wrt class range
% take the frame average
frameavg = mean(stack,4);
% Display the RGB image
% it's low contrast due to the distribution of object content
imshow(frameavg);
% if you want to normalize the output for visualization purposes (contrast)
frameavg = mat2gray(frameavg); % normalize wrt data extrema
% Display the RGB image
imshow(frameavg);
Is it appropriate to misrepresent the actual mean by changing the data scale after the fact? That depends on the intent. If it's just for visualization, the exact values may matter less than the relative prominence of features.
Is it meaningful to average a multiframe color image? Not necessarily. If the image is represented in scaled pseudocolor, then the average of two pixels produces a new color whose implied value is meaningless (or simply wrong). Say we had an image using the hsv() map used above, and the color scale is [0 1]. Two pixels representing 0 and 0.5 respectively would average to be ([1 0 0] + [0 1 1])/2 = [0.5 0.5 0.5], which isn't remotely close to any color in the map. Likewise, two pixels representing 0.5 and 1 (or 1/6 and 2/3) would produce the same exact meaningless color. It might make more sense to convert the data back to grayscale -- which might not be possible without the original map.
Again, that's based on the assumption that the original image is pseudocolor. A lot of the original requirements are unknown, but this is a start.

Connectez-vous pour commenter.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by