mat2gray implementation affecting output

Hi everyone,
I am using a program called Multem to generate simulated TEM nanoparticle images. I have adapted the program to produce images that reflect detector influence on the images. I include the modulation transfer function (MTF) as well as the noise transfer function (NTF) of the detector. These two properties describe how the signal and noise are influenced by the detector respectively. The noise I am primarily focusing on is shot noise, which I include using poissrnd(A), where A is the electron dose per image. The values of A vary from 2.6e6 to 8.07e7.
The code structure is as follows:
img1 = noiseless image (output from Multem)
%including the MTF
img2 = fft(img1).*(MTF) ----(1)
img3= ifft(img2) ----(2)
%including noise
t= total dose per image
img4 = poissrand(t); ----(3)
img5 = fft(img4).*(NPS) ----(4)
img6 = iff(img5); ----(5)
%multiplying MTF attenuated signal by noise attenuated by the NPS
img7= img3.*img6 ----(6)
%saving image as tiff
imwrite(mat2gray(img7),...'.tif') ----(7)
I run into the following issues when I use mat2gray;
When I do use it on steps (2,3,5, 6 and 7);
  • the noise standard deviation is the same for all A values and the noise appears exaggerated even for high A values
When I exclude it on step 5;
  • the noise standard deviation is the same for all A values and the noise appears low even for low A values
When I use it only in writing the final images the outcome is almost no noise at all;
Also, when I don't use it at all steps images I retrieve white images with no information.
I have attempted several other combinations but the outcomes have remained the same either there is too much or too little or no noise at all. When is it appropriate to use mat2gray and when is it not? Typically the data are meant to reflect dose dependence but in this case I am not getting that.
Any advice and pointers are welcome,
Thank you

1 Comment

mat2gray(A) is going to normalize the data to the range of its extrema. Any offset information is lost. The minimum (e.g. 2E6) gets mapped to 0. The maxima gets mapped to 1. If this is going to mess up subsequent calculations, you may try specifying the range which mat2gray() uses when normalizing. Given the extreme offset though, you might run into precision issues with the numeric class used when writing to tiff. I'm not sure of what to recommend, and I'm not even sure this information is helpful to you.

Sign in to comment.

 Accepted Answer

When you use imwrite of double precision data,
"If A is a grayscale or RGB color image of data type double or single, then imwrite assumes that the dynamic range is [0,1] and automatically scales the data by 255 before writing it to the file as 8-bit values. If the data in A is single, convert A to double before writing to a GIF or TIFF file."
imwrite() never outputs Tiff in floating-point format.
There is a file exchange contribution that uses the Tiff class to write tiff in single or double precision.
This is the reason why you get white if you do not use mat2gray: your values are floating point greater than 1, and floating point values greater than 1 are treated as 1 (maximum intensity)

13 Comments

Oh hey, I went looking and you beat me to it. Is this the same one you were thinking of?
@Walter Roberson and @DGM, thank you for responding. The data is double precision and it certainly has floating point values above 1. I have tried specifying the range using mat2gray(A, [min(A,[],'all') max(A,[],'all']) and the output range becomes [0 1] either way as you have rightly suspected @DGM. I have thought of using imwrite2tif() but have failed to make it append to create a stack of tiffs from a for loop. I have tried to include the ('WriteMode','a') command but it doesn't recognise it as a valid tag input. I have just used ('a') afterwhich it complains that the number of arguments is invalid. I have contacted Zhang and he hasn't responded yet to my question. It would be great if any of you are aware of a way around this.
Kind regards,
Arthur
I don't think imwrite2tif has any way of adding images to an existing file. If you have imagemagick installed, you can use that to assemble the image. I suspect there may even be a way to avoid normalizing the data at all, but I can't seem to figure it out. It may be something that's unsupported in the version I have. If normalization is acceptable, this worked for me:
A = im2double(imread('cameraman.tif'))*1000 + 1000; % large data range + offset
A = mat2gray(A); % normalized
% write normalized DPFP frames
imwrite2tif(A,[],'iwtif1.tif','double');
imwrite2tif(fliplr(A),[],'iwtif2.tif','double');
imwrite2tif(flipud(A),[],'iwtif3.tif','double');
% combine the frames into one tif file
system('convert "iwtif1.tif" "iwtif2.tif" "iwtif3.tif" -define quantum:format=floating-point -depth 64 -adjoin "iwtif.tif"');
% read the frames
B1 = imread('iwtif.tif','index',1);
B2 = imread('iwtif.tif','index',2);
B3 = imread('iwtif.tif','index',3);
% denormalize if necessary
Hi @DGM, I have attempted to adapt your code for my situation as below:
I have added the following line at the end of a for loop that produces images I have called 'Full_add_Poiss_Noise.tiff'. If this is incorrect please help me understand how I could adapt it appropriately.
imwrite2tif(ig_noisy4,[],['Full_Add_Poiss_Noise.tiff'],'double','Compression',1);
system('convert "Full_Add_Poiss_Noise.tif" -define quantum:format=floating-point -depth 64 -adjoin "Full_Add_Poiss_Noise.tiff"');
If it is correct then version 19b doesn't recognise the - define parameter and it gives me the following error:
Invalid Parameter - -define
Thank you and kind regards,
Arthur
You can use the hints from imwrite2tiff() to work with the Tiff class yourself, appending images as you go. The important parts are:
SampleFormat = 3;
and setting the bits per sample to 64, and setting the photometric.
Note: ImageJ does its "stacks" a bit differently than most other programs; you have to know the right magic tag that gives it information about the 3D positioning.
DGM
DGM on 28 Apr 2021
Edited: DGM on 28 Apr 2021
Oh, I'm going to guess that's probably a conflict.
You'll probably have to include the full path
Thank you.
I get the error below when I use the solution suggested above i.e. both to use the full file path and adding magick before convert.
convert: D:\..Full file path...\Full_Add_Poiss_Noise.tiff: Unknown tag 317. `TIFFSetField' @ error/tiff.c/TIFFErrors/595.
Do you have an idea what might be causing this?
I find a posting in which someone had problems with tag 317, but the real problem was that they did not have samples per pixel set.
Thank you both for your help,
After careful inspection of the imwrite2tif() function it became apparent to me that there is an option to change from writemode to append within it. So I didn't have to specify it when calling the function on the editor.
The option within the function is below the
%checking for errors section
% create a Tiff object
t = Tiff(imfile,'w'); % changing 'w' to 'a' here appends and creates a stack of double images with appropriate pixel values.
At the moment both of you have directed me to the imwrite2tif() function and so I am not sure whose answer to accept.
Arthur
I have a follow up question on this. I am now able to save my images as double floating point data. However, I am actually studying noise properties in these images and I have realised that if I mat2gray() when saving I get a slightly higher noise level whereas when I don't implement mat2gray the noise is significantly less. The odd thing is, the slightly higher noise approximates my true experimental noise much better. I would suspect, despite this, that the most appropriate way to save this is to save them without mat2graying.
Am I making the correct judgement here?
Thank you again.
Arthur
If you can save as double precision, then you should probably avoid mat2gray()
Thank you@Walter Roberson. I think I get it now.
Regards,
Arthur

Sign in to comment.

More Answers (0)

Products

Release

R2019b

Tags

Community Treasure Hunt

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

Start Hunting!