I am trying to certain points of data from structs which are in a cell

1 view (last 30 days)
I have used bwconncomp to count the number of objects in successive frames of a video. There are 99 frames, and therefore I have a 1x99 cell. Each struct in the cell contains 4 pieces of data, the third of which is number of objects. I am trying to see how the number of objects changes throughout the frames, so I essentially need to plot the number of objects from the structs in the cell array against the frames from 1 to 99. I'm aware I can't plot data directly from a cell, however I have tried to extract the data from the cell, but am struggling to plot any data at all. I have attached the whole code below for relevance, however the majority of it is just subtracting backgrounds and changing the images so the objects can be found. Any ideas on how I can extract the number of objects in each struct in the cell, and therefore plot it vs the frame it relates to?
folder = fullfile('Folder1\Folder1\Frames');
filePattern = fullfile(folder, '*.jpg');
fileList = dir(filePattern);
numberOfFiles = numel(fileList);
subtractionFileName = 'subtract.jpg';
if ~isfile(subtractionFileName)
errorMessage = sprintf('Subtraction image not found:\n%s', subtractionFileName);
uiwait(errordlg(errorMessage));
return;
end
backgroundImage = imread(subtractionFileName);
for k = 1:numberOfFiles
baseFileName = fileList(k).name;
if contains(baseFileName, 'subtract', 'IgnoreCase', true)
continue;
end
fullFileName = fullfile(fileList(k).folder, baseFileName);
fprintf(1, 'Now reading %s\n', fullFileName);
thisImage = imread(fullFileName);
subtractionImage{k} = backgroundImage - thisImage;
imshow(subtractionImage{k}, [])
caption = sprintf('Image #%d of %d : %s', k, numberOfFiles, baseFileName);
title(caption, 'Interpreter', 'none');
drawnow;
end
for k = 1:numberOfFiles
graySubtractedImage{k}=rgb2gray(subtractionImage{k});
binaryImage{k} = graySubtractedImage{k}>114;
binaryImage{k} = imclearborder(binaryImage{k});
BW1{k} = bwareaopen(binaryImage{k},75);
BW2{k} = bwconncomp(BW1{k});
end

Accepted Answer

Image Analyst
Image Analyst on 15 Aug 2022
No need to store binary images or connected components in a cell array.
for k = 1:numberOfFiles
graySubtractedImage =rgb2gray(subtractionImage{k});
binaryImage = graySubtractedImage > 114;
binaryImage = imclearborder(binaryImage);
binaryImage = bwareaopen(binaryImage,75);
cc = bwconncomp(binaryImage);
blobCountsPerFrame(k) = cc.NumObjects;
end

More Answers (1)

dpb
dpb on 15 Aug 2022
It's an array of struct, use arrayfun to iterate over the collection of objects...
BW2{k} = bwconncomp(BW1{k});
N{k}=arrayfun(@(s)s.NumObjects,BW2{k});
  3 Comments
dpb
dpb on 15 Aug 2022
That's exact code -- put it in line where I show it as I wrote it and you'll save the number in each of the files -- that is, of course presuming that there's more than one object in each call so that each BW{k} is an array. Of course, it will work for an array size of one, too, then there would be no need for it but one also wouldn't handle the case where there is more than one.
I don't have Image TB so I can't explore; what I can do is make up a dummy array of what the struct returned looks like --
>> CC=struct('Connectivity',8,'ImageSize',[256 256],'NumObjects',88); CC=repmat(CC,3,1)
CC =
3×1 struct array with fields:
Connectivity
ImageSize
NumObjects
>>
I ignored the last/fourth field as being of no interest and I simply copied over the same data into all three members, but
>> N=arrayfun(@(s)s.NumObjects,CC)
N =
88
88
88
>>
returns the expected results since
's' is just a dummy array argument, "s" standing for "struct" as the variable name; the anonymous function just references the NumObjects field of the passed-in struct, s. arrayfun passes each member of the input array to the function in turn; it's just a one-line for...end loop construct for such purposes as this.
Let's see; I don't use struct all that much because they can be a pain to dereference -- on reflection you don't need to do that; you can use the comma-separated list feature directly
>> Nobj=[CC.NumObjects]
Nobj =
88 88 88
>>
which is far better solution.
Andrew Palmer
Andrew Palmer on 16 Aug 2022
Thank you very much for your help, this worked exactly how I wanted it to as well

Sign in to comment.

Products


Release

R2022a

Community Treasure Hunt

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

Start Hunting!