Finding contiguous regions of interest in a mask and calculating the mean values of those regions when the mask is applied to an array

13 vues (au cours des 30 derniers jours)
I have a 2-d logical array (1024 rows, 1280 columns) that contains 12 "islands" of 1s in a sea of 0s. I can label the islands using L=bwlabel(myLogical).
I want to apply myLogical as a mask to a 16-bit monochrome image that is 1024 x 1280. The image was converted to an array using myImage=double(imread('myImage.tif')). myImage has some NaN values (e.g. representing saturated pixels).
For island 1, I want to analyse the corresponding pixels in myImage row by row. Starting at the first row of island 1, I want to count 64 elements and find their average (omitting NaNs in the calculation). Then continue, counting the next 64 elements and find their average, and so on. For example, if island 1 has 10 rows x 65 columns, I will end up with 10 average values and 10 pixels left over. The remaining pixels can be ignored.
Then I want to move on to island 2, then island 3 and so on until I have 12 sets of average values (one set per island).
Is there an efficient way to do this? I wondered about using bwconncomp (I don't really need to label the island) but its output PixelIdxList seems to index column-by-column rather than row-by-row.

Réponse acceptée

Matt J
Matt J le 13 Nov 2024
myImage=myImage';
L=L';
Lmax=max(L(:));
result=cell(1,Lmax);
for i=1:Lmax
result{i}=rasterMean(myImage(L==i));
end
function m=rasterMean(x)
N=numel(x);
N=ceil(N/64)*N;
x(end+1:N)=nan;
x=reshape(x,64,[]);
m=mean(x,1,'omitnans');
end

Plus de réponses (1)

DGM
DGM le 13 Nov 2024
Modifié(e) : DGM le 13 Nov 2024
You have a mask and a (assumed) grayscale image. Here are three ways:
% a grayscale image and a logical mask of the same geometry
inpict = imread('cameraman.tif');
mask = imread('cmanpolyblobs.png')>128;
% use a label array and address the image based on it
[L nblobs] = bwlabel(mask);
meangray1 = zeros(1,nblobs);
for k = 1:nblobs
mk = L == k;
meangray1(k) = mean(inpict(mk));
end
meangray1
meangray1 = 1×4
166.3752 13.6526 98.8650 119.5946
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% use bwconncomp() in a similar manner
CC = bwconncomp(mask);
meangray2 = zeros(1,CC.NumObjects);
for k = 1:CC.NumObjects
meangray2(k) = mean(inpict(CC.PixelIdxList{k}));
end
meangray2
meangray2 = 1×4
166.3752 13.6526 98.8650 119.5946
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
% use regionprops() directly on the mask, label array, or CC struct
S = regionprops(mask,inpict,'meanintensity');
meangray3 = horzcat(S.MeanIntensity)
meangray3 = 1×4
166.3752 13.6526 98.8650 119.5946
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
IPT regionprops() can return many different properties, so it often obviates the need to explicitly use bwlabel() or bwconncomp(). In case you're wondering, the blob ordering will be the same.
If you have a color image, it gets a little bit more complicated.
  1 commentaire
Steve Francis
Steve Francis le 13 Nov 2024
Modifié(e) : Steve Francis le 13 Nov 2024
Thank you @DGM. I appreciate your time and advice. You're correct, my image is monochrome.
To get a vector of values for each island I assume that I can use something like:
ROI(k) = inpict(CC.PixelIdxList{k})
but this concatenates values column-by-column for the corresponding image. Is there a way to get a vector for row-by-row?

Connectez-vous pour commenter.

Produits


Version

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by