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

31 views (last 30 days)
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.

Answers (2)

DGM
DGM on 13 Nov 2024 at 1:36
Edited: DGM on 13 Nov 2024 at 1:42
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 Comment
Steve Francis
Steve Francis on 13 Nov 2024 at 16:34
Edited: Steve Francis on 13 Nov 2024 at 16:35
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?

Sign in to comment.


Matt J
Matt J on 13 Nov 2024 at 16:29
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

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!