Display/highlight specific pixels of in image

7 vues (au cours des 30 derniers jours)
Amit Ifrach
Amit Ifrach le 1 Août 2024
Modifié(e) : DGM le 2 Août 2024
לק"י
Hello guys,
A short code was written to allow me to gather data about cells masks that were clicked on in a figure.
I want to simoultaneously show all previous chosen cells with a color or other distinctive way to avoid picking twice the same cell.
Haven't managed to find or think about easy and quick way to make it happen.
The cells masks are from time series stack that is being iterated for the amount of frames in the stack. All of this process is being iterated for the amount of cells I want to pick, which I specify in a variable before running the code.
the code:
stackfilename = '17.07.2024 aHER2 carrier W.T cd45low+cd4+lstrckr001 cellpose stack.tif'; %get the name of the
% time series stack of masks. These cellpose stacks are handing each cell a unique grayscale value
%ranging from 1 to the total amount of cells detected by cellpose. background (non-mask undetected cell pixels)
% is set to 0.
info = imfinfo(stackfilename); %Info function gets information of every single image of the image stack.
numberOfImages = length(info); %counting the length of info will give the amount of images in the stack.
cellnumber= 6; %Enter the desired amount of cells to be analysed.
pixelindexes={}; %Create a cell array that will hold each mouse click (mask choose) indexes.
pixelvalues={}; %Create a cell array that will hold each mask grayscale value.
for i = 1:cellnumber %The number of cells (number of main loops).
for j=1:numberOfImages %For each cell (main loop), a secondary loop will initiate for the amount...
%of frames in the cells masks stack ('numberOfImages').
crntimg = imread(stackfilename, j); % Read the current image
figure(1) %Create a figure
old = double(crntimg); %Turn the image from uint to double for later mathematical manipulation.
crntimgmax=double((max(max(crntimg)))); %Find the max grayscael value of the current frame...
%,equals total cell masks in the frame.
new = 10+(10*(old./crntimgmax)); %Manipulate the image matrix to allow dark tones
% (low values) to be shown with imshow command.
new(new==10)=0; %Set background values to 0 for the dark tones to be seen brighter.
imshow(new,[]) %Display image.
if i~=1 %If previous cells were chosen, start a loop that will...
%plot/show them on the new image that was created to avoid choosing the same cell twice.
hold on %Hold the image.
for k=1:(i-1)
imshow(crntimg==(pixelvalues{j,k}(1)),[]) %|||***This is where
% I can't figure out how to SIMOULTANEOUSLY SHOW *ALL* OF THE PREVIOUSLY CHOSEN cell masks with
%a DISTINCTIVE COLOR or other way that will set them apart from the other yet unchosen cell masks.***|||
end
end
pixelindexes{j,i}= ginput(1); %Store pixel indexes.
pixelvalues{j,i}=impixel(crntimg,pixelindexes{j,i}(1,1),pixelindexes{j,i}(1,2)); %Store pixel values.
end
close (figure (1))
end
%Save the data
save(append(stackfilename, append...
( append(' ', strrep(string(datetime(now,'ConvertFrom','datenum')),':','-')),' Worksapce data')));
The part that I can't seem to over come is the last for loop which should simoultaneously show all previous chosen masks with a distinctive color or any other way that will show the previously chosen cells distinctively. I tried my best to explain my self and provide with sufficient info. If anything else is needed or needs to be more clear please tell me.
Thanks,
Amit.

Réponses (2)

Robert Daly
Robert Daly le 2 Août 2024
Modifié(e) : Robert Daly le 2 Août 2024
I am thinking you can't use imshow to plot individual pixels on top of an existing image. You need a full raster matrix.
Here are some suggestions in order of complexity...
My suggestion would be to just use plot(i,j,'x') to put an "x" at the i,j coordinates you have already picked. That would seem the simplest solution, but maybe not the best. Maybe scatter could be a similar alternative with more options for the size and shape of the "marker".
An alternative suggestion would be to create a "working copy" of your image file that is only used for display and then set the pixels you choose in that copy to the minimum or maximim value so they stand out from the surrounding pixels.
Yet another alternative could be to use pcolor to plot your images since that allows transparancy. You could create an overlay matrix the same size as your image with nan values in all of the cells. In pcolor the nan values will be transparent. Then as you pick cells you can replace the nan value for that cell with some other value so that it shows up. This may have some issues due to the way pcolor fills in the "pixels", the right most column and bottom row might not be shown as pixels. This may or may not be a problem for you depending on your image.
In a similar (and maybe better) way you could create an overlay image the same size as your image that is all one colour (the colour you want to use as the distinctive colour). Then create another matrix that sets the transparancy value of each pixel. That way you could use imshow to plot the highlighted pixels on top of your image. Then the trick is to set the transparancy of only the pixels you picked to be not transparent (value = 1) and all the others to be transparent (value = 0). That will let you see through to your image underneath.
Something along the lines of...
figure
imshow(image)%plot your image
hold on
highlight_mask=ones(size(image));% make this number to suit what ever colour you want
alpha = zeros(size(image)) % make an alpha map that is all transparent (i.e. 0)
alpha(j,i) = 1 % set the pixels you selected as not transparent (i.e. 1)
h=imageshow(highlight_mask) % plot the mask image on top of your image
set(h, 'AlphaData', alpha); % set the transparancy of this image to the alpha map you created
Here is an explanation of the transparancy code...
The highlight_mask might need to have 3 layers with red, green, blue vaues to set the colour.
i.e. the size of the matrix would be N x M x 3
The alpha only needs to be an N x M x 1 matrix

DGM
DGM le 2 Août 2024
Modifié(e) : DGM le 2 Août 2024
I can think of a few ways to create a composite grayscale + color labeled image, but it's not really clear to me what the actual workflow is supposed to be. You're looping through frames, then through counts, which doesn't make sense to me. This is my interpretation, but maybe I'm not thinking of the same thing.
% get the name of the time series stack of masks.
% These cellpose stacks are handing each cell a unique grayscale value
% ranging from 1 to the total amount of cells detected by cellpose.
% background (non-mask undetected cell pixels) is set to 0.
stackfilename = 'test.tif';
% parameters
cellnumber = 6; % number of labels to pick
darklift = 0.1; % amount to raise small counts away from zero (relative, [0 1] scale)
% you'll need a color table for the label overlay
CT = lines(cellnumber); % lines() has only 7 colors, so watch it
% setup & preallocation
info = imfinfo(stackfilename); %Info function gets information of every single image of the image stack.
numberOfImages = length(info); %counting the length of info will give the amount of images in the stack.
pixelindexes = cell(numberOfImages,cellnumber);
pixelvalues = cell(numberOfImages,cellnumber);
hf = figure(1); % Create a figure
% do the display/picking routine
for f = 1:numberOfImages
% Read the current image
crntimg = imread(stackfilename, f);
% adjust image contrast for viewing
% this image is in standard unit-scale
% so there's no need to try to mess with implicit scaling
viewimg = rescale(crntimg,[1 max(crntimg(:))],[darklift 1]);
viewimg(viewimg < darklift) = 0;
% allocate a new label image
L = zeros(size(crntimg));
% start picking
for c = 1:cellnumber
if c == 1
% if this is the first selection, just display the image
imshow(viewimg)
else
% otherwise, display a composite image
clf(hf) % clear figure (not really necessary)
L(crntimg == pixelvalues{f,c-1}(1)) = c; % update label image
overlayimg = labeloverlay(viewimg,L,'colormap',CT,'transparency',0); % composite
imshow(overlayimg)
end
% get pixel data
pixelindexes{f,c} = ginput(1);
pixelvalues{f,c} = impixel(crntimg,pixelindexes{f,c}(1),pixelindexes{f,c}(2));
end
end
% i'm using this because the built-in rescale() bothers me
function outpict = rescale(inpict,inrg,outrg)
inpict = double(inpict);
inrg = double(inrg);
outrg = double(outrg);
outpict = (outrg(2)-outrg(1))*(inpict-inrg(1))/(inrg(2)-inrg(1))+outrg(1);
end

Community Treasure Hunt

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

Start Hunting!

Translated by