Blockproc, appdesigner, mutliple outputs (combined to one) returning empty

1 view (last 30 days)
Is there a reason why blockproc isn't returning anything:
ax=app.UIAxes;
IM=getimage(ax);
border_size = [10 10];
block_size=[100 100];
%these are user supplied via editboxes
guess=app.FWHMguesspixelsEditField.Value;
[template]=255*getTemplateFromGuess(app,guess); %My own function
thresh=app.NXCThreshEditField.Value;
%Use blockproc to break up my large image into smaller ROI's
myfun = @(block_struct) app.myFindSpots(thresh,block_struct.data,template);
Centroids = blockproc(IM,block_size,myfun,"BorderSize",border_size)
returns with:
Centroids =
[]
where:
function [centroids] = myFindSpots(app,thresh,IM,template)
IM=im2double(IM);
try
c=normxcorr2(template,IM);
%Use regionpropos on c to get single representation (using weighted
%centroid. This prevents multiple representations of same object
GreaterThanThreshold = c > thresh;
s = regionprops(GreaterThanThreshold,c, 'WeightedCentroid');
centroids = cat(1, s.WeightedCentroid);
xpeak=centroids(:,1); ypeak=centroids(:,2);
%Account for padding
yoffSet = round((size(c,1)-size(IM,1))/2);
xoffSet = round((size(c,2)-size(IM,2))/2);
x1=xpeak-xoffSet; %now undo effect of padding as plotting on raw image
y1=ypeak-yoffSet;
catch
% Theres an error with finding spots
x1=NaN; y1=NaN;
end
centroids=[x1,y1]; %If I uncomment this, I see all the values are O.K
end

Accepted Answer

Avadhoot
Avadhoot on 20 Mar 2024
Hi @Jason,
The reason "blockproc" is not returning anything is because it expects the function that it applies to each block to return an array that matches the block size. But your "myFindSpots" function returns a variable sized array which does not match the block size. That is why "blockproc" returns an empty array.
The correct approach to solve this is to accumulate all the centroids in a cell array. You can refer to the below code to get an idea of the approach:
% Initialize a cell array to store centroids from each block
centroidsCell = cell(size(IM, 1) / block_size(1), size(IM, 2) / block_size(2));
% Modify the function to store centroids in the cell array
myfun = @(block_struct) setCentroidsCell(block_struct, app, thresh, template);
% Placeholder function to replace myFindSpots in blockproc
function out = setCentroidsCell(block_struct, app, thresh, template)
centroids = app.myFindSpots(thresh, block_struct.data, template);
% Since blockproc expects an output matching the block size, return a dummy value
out = zeros(size(block_struct.data, 1), size(block_struct.data, 2));
% Calculate block index
blockIdx = block_struct.location;
% Store centroids in the corresponding cell
centroidsCell{blockIdx(1), blockIdx(2)} = centroids;
end
% Now run blockproc (note that the actual output is not used)
blockproc(IM, block_size, myfun, "BorderSize", border_size);
% After running blockproc, concatenate all centroids from the cell array
allCentroids = vertcat(centroidsCell{:});
The following changes are implemented in the above code:
  1. Firstly a cell array of the correct block dimensions is created to store the centroids.
  2. "myfun" is slightly modified to include a wrapper function over "myFindSpots" which accumulates the centroids.
  3. The centroids are all collected in the cell array and stored at their corresponding block index.
  4. After running "blockproc", all the centroids from the cell array are concatenated using "vertcat".
Note: Ensure that the case when no centroids are found is handled appropriately in the "myFindSpots" function as it can also cause "blockproc" to return an empty array. Also verify the values of "thresh" and "template" as wrong values can lead to no centroids being found.
For more information on "blockproc" go through the following documentation:
I hope it helps

More Answers (0)

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!