Why is MATLAB changing the RGB values of some of my images?

15 views (last 30 days)
I have a fairly simple code (attached) that I am using to change certain pixel intensities to max values (65535) over 141 greyscale .tif images that are 614 x 614 pixels in size. The change is based on whether the original pixel intensity is <= a specified "threshold".
For some reason, when I run the code, MATLAB is also changing the RGB values to [1 1 1], but only for some images, not all. I do not want the RGB values changed at all.
For example, when the "threshold" is specified as 7000, images 10-26 have the pixel intensities changed properly, but also the RGB values are changed to [1 1 1] everywhere in the image, so they appear completely white. Images 1-9 turn out just fine, as does images 27-37, 55-58, etc. (it appears as if totally random subsets of images are working). I've attached Image 10 to this post.
I am using R2021a and importing my 141 images as a .tif stack. I've tried only importing image 10 and processing it (even as a .png and not as a .tif), but it still ends up with all RGB = [1 1 1]. I've also tried different threshold values, but that does not solve the problem. It just causes different subsets of images to have the RGB values changed to [1 1 1].
Does anyone have an idea of what is going on? Is this a bug in MATLAB? Or do I not have my code set up properly?
Thanks,
Brandon
  3 Comments
Brandon Hilliard
Brandon Hilliard on 3 Oct 2022
Hi Jan,
Thanks for the tip. I've replaced the code with the more elegant method, in both this script and others that I have written.
I am confused about your last comment in which the loops are not needed at all. When I run those two lines of code instead of the loops, I'm just given a logical array of all ones. I'm not sure I was totally clear in my original posting - any pixel intensity less than the specified threshold should be set to 65535 (16-bit), but if the pixel intensity is greater than the specified threshold, I want to keep the grey-scale intensity, not make it 0 (I do not want binary images).
Brandon Hilliard
Brandon Hilliard on 4 Oct 2022
Hi Jan,
With Image Analyst's answer, I now understand your last comment. Instead of this:
Images{b}(mask) <= 65535
I think you meant to write this?
Images{b}(mask) = 65535
Because if I use just = instead of <=, the code works exactly how I want it to!

Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 3 Oct 2022
Edited: Image Analyst on 3 Oct 2022
What is the class of those images it doesn't work on? Probably uint8 instead of uint16. But I don't know why it's changing it to 1. If it want to change a uint8 to 65535, it would clip to 255, not 1. Is the one image you attached one for which it changes the whole image to [1,1,1]? Can you attach one of the original tif images (needs to be less than 5 MB)?
Try this:
%%% Brandon Hilliard
%%% ME600 - Research
%%% Sept 27th, 2022
%%% Benchtop QPLIF Bed Architecture - Making grains white
clc
clear
close all
%% README
% This code imports the raw bed architecture (Set 04) from the Benchtop
% QPLIF Reruns. It is designed to change only the intensity of the pixels
% within grains to be totally white, based on a user-specified threshold.
%% DECLARE CONSTANT PROCESSING PARAMETERS AND READ .jpg FILES
tic
Drive = 'D';
inputImageFolder = fullfile(Drive,':\Grad School Projects\Benchtop QPLIF\Reruns\Raw Data\QPLIF Bed Architecture Set 04\');
%inputImageFolder = pwd;
if ~isfolder(inputImageFolder)
errorMessage = sprintf('Error: input image folder does not exist:\n%s', inputImageFolder)
uiwait(errordlg(errorMessage))
return;
end
% Get a list of all image files in this folder.
ImFileName = 'Raw Images with 2 Artificial Objects for RS - 16bit';
ImExt = '.tif';
filePattern = sprintf('%s*%s', ImFileName, ImExt)
%filePattern = fullfile(inputImageFolder, 'image*.png')
fileList = dir(filePattern);
allInputFileNames = fullfile({fileList.name})';
NumImages = numel(fileList);
Threshold = 7000;
% originalImages = cell(NumImages, 1);
% fullFileName = fullfile(inputImageFolder,ImFileName,ImExt)
% if ~isfile(fullFileName)
% errorMessage = sprintf('Error: input image file does not exist:\n%s', fullFileName)
% uiwait(errordlg(errorMessage))
% return;
% end
% READ IN IMAGES AND MAKE DARK GRAINS (LESS THAN THE THRESHOLD) WHITE.
originalImages = cell(NumImages, 1);
ProcImages = cell(NumImages, 1);
for a = 1:NumImages
fullFileName = allInputFileNames{a}
% Images{a,1} = imread(fullFileName,a);
thisImage = imread(fullFileName);
originalImages{a} = thisImage; % Not really needed.
% Find pixels that are less than the threshold
mask = thisImage <= Threshold;
% Replace those pixels with 65535.
thisImage(mask) = intmax("uint16");
% Save into a different cell array (for some reason).
ProcImages{a} = thisImage;
end
%% SHOW EXAMPLE IMAGES
Plane = 1;
figure;
subplot(1, 2, 1);
imshow(originalImages{Plane}, [])
subplot(1, 2, 2);
imshow(ProcImages{Plane}, [])
%% SAVE PROCESSED IMAGES
Savedir = fullfile(inputImageFolder,'White grains with 2 Artificial Objects for RS\',num2str(Threshold),' Threshold\');
SaveExt = '.png';
for e = 1:length(ProcImages)
baseFileName = sprintf('Buffer%3.3d%s', e, SaveExt);
fullOutputFileName = fullfile(Savedir, baseFileName);
imwrite(ProcImages{e}, fullOutputFileName);
end
toc
  4 Comments
Brandon Hilliard
Brandon Hilliard on 4 Oct 2022
Yes, but that is what's so strange. I did acquire these images with the same camera, and they are all the same type. Originally, they were uint8. But I changed the format of all images to uint16 (for better pixel intensity resolution) using a free application called ImageJ, developed by the National Institute of Health (NIH). So when I initially read them into MATLAB, they were all uint16. For some reason, some of them got changed back to uint8 after processing the way I originally did it. I know MATLAB can change the format of images as such, but I was not specifying it to.
Image Analyst
Image Analyst on 5 Oct 2022
You don't need imageJ. You can read them in to MATLAB with imread() and cast them to uint16. However, not matter where you do it, your original gray levels will be the same. You can scale them if you want but you're not creating any gray levels, just multiplying them by 256, which it seems you did because you are using a threshold of 7000. There is no need to scale them. It won't really help. If you process the image and want fractional, in-between gray levels then cast it to double.
If you just cast to 16 bit without scaling you can use the same threshold you did for uint8. However if you scale your image by multiplying it by 256 then you'll have to get a threshold for uing 8 images by dividing the 7000 by 256.

Sign in to comment.

More Answers (0)

Products


Release

R2021a

Community Treasure Hunt

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

Start Hunting!