While doing image analysis, how can I auto detect which rows of pixels to analyze?

3 views (last 30 days)
I have a series of images that look like this:
I need to generate plot profiles for every bright rectangle. I can do it with line cuts across the entire image, they don't have to all be individual.
I have been doing this in imageJ, exporting to Excel, and analyzing from there, but manually doing all of this is really time consuming and introduces more potential for human error.
So far, I have this code:
Mean = mean(ImgMatrix,2) %ImgMatrix is a matrix with all the pixel values of the image
[Maxima,MaxIdx] = findpeaks(Mean,'MinPeakHeight',112);
% I was attempting to take the average pixel value for each row and select the rows with the
% highest local maximum average, but still above the value for the "black"
% background (which is around 112)
Output = ImgMatrix(MaxIdx,:) %creating a new matrix that only includes the rows identified as higher pixel value rows
TROutput = Output.' %transposing the matrix so I can use the Signal Analyzer app
But it's bringing back more than just one line cut per row of lines.
Ideally, it would be line cuts at the following (approximate) locations, near the center of each row of rectangles (lines are thicker than 1 px to make them easier to see for illustrative purposes):
But the exact position of the rectangles isn't consistent from image to image, they might be slightly lower or higher in the frame.
However, they are always the same distance away from each other... so if I could use some kind of script to identify the position of the first line cut/row, I know the pixel distance between that line and where the next line should be.
Is there a better way to make this happen?

Accepted Answer

DGM
DGM on 19 Oct 2022
Edited: DGM on 19 Oct 2022
There's probably a bunch of different ways to approach this. If we can assume that the objects in the image are roughly grid-aligned and that the rows of blobs are well-separated from each other, then this might be one way:
A = imread('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1162358/image.png');
% there isn't any color information here
% all channels are identical to within 1 LSB, so we can reduce
A = A(:,:,1);
% assuming rows of blobs are roughly grid-aligned
% find vertical center of each row of blobs
rowmask = any(imbinarize(A),2); % binarize the image, reduce to a column vector
S = regionprops(rowmask,'centroid'); % find centroids of each blob
rowcenters = round(vertcat(S.Centroid)); % just the numbers
rowcenters = rowcenters(:,2); % shaking off more unnecessary numbers
% get profiles
numblobrows = numel(rowcenters);
profiles = zeros(numblobrows,size(A,2));
for br = 1:numblobrows
profiles(br,:) = A(rowcenters(br),:);
end
profiles = profiles'; % transpose as in given example
% plot all the profiles in a giant pile
% this isn't really readable, but it's just to demonstrate that they're there.
plot(profiles)
While I just selected row vectors from the image to create each profile, improfile() could also be used if the needs are more complex. If the image might be rotated or skewed, using improfile() might be preferred, though getting the coordinates for a path through each row of blobs would be more involved than the given example.

More Answers (0)

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!