Passing individual varargin arguments from one function to another

I'd like to make a wrapper around regionprops and am having trouble passing the arguments along.
This isn't a problem specific to regionprops but is more about trying to wrap a function that has varargin for input and retaining the flexibility.
regionprops has varargin for input: regionprops(varargin) One possible input is a labeled matrix.
I'd like to write a wrapper where I can modify that label matrix and then pass everything along to regionprops - essentially substituting my new matrix for varargin{1} but keeping everything else the same.
The rationale is that if the biggest label is really big but there are a lot of missing labels, regionprops is really slow.
If the labeled objects are not connected (mine aren't) then I can make it much faster by relabeling the objects with 1:#objects, calling regionprops on this labeled matrix, and then reconstructing the statistics for the original labels. I can do this by adding a few lines in a copy of the regionprops function itself, but I'd prefer to leave it alone and just wrap it.
But the problem is:
-----
rps=myWrapper(L,'Area','FilledImage','Centroid');
function modifiedStatsOut=myWrapper(varargin)
...
varargin{1}=modifiedLabelMatrix;
statsOut=regionprops(varargin);
-----
this fails because instead of varargin being a 1x4 cell as it is when passed into myWrapper, it is a 1x1 cell when it gets into regionprops
Thanks for any help, Scott

 Accepted Answer

You messed up the assignments. It should be like this:
rps=myWrapper(L,'Area','FilledImage','Centroid'); % Call from the main program.
function modifiedStatsOut = myWrapper(varargin)
% Extract the incoming labeled matrix.
originalLabeledImage = varargin{1};
% Now extract the measurements you want to make.
measurements = varargin(2:end);
% Now somehow you create modifiedLabelMatrix based on the incoming version.
% Combine blobs or whatever...
modifiedLabelMatrix = ...some code that uses originalLabeledImage....
% Now call regionprops() with new labeled matrix
statsOut = regionprops(modifiedLabelMatrix, measurements);

8 Comments

Exactly what I needed - thanks.
Won't that fail if you use the regionprops(L, I, properties) syntax? Passing measurements as a comma-separated list would cover that case as well, I think.
I don't believe it will fail. All of these are valid ways of calling it
stats = regionprops(L, I, 'area', 'Centroid');
stats = regionprops(L, I, {'Area', 'Centroid'});
stats = regionprops(L, 'Area', 'Centroid');
stats = regionprops(L, {'area', 'Centroid'});
To double check, I just tried them all, and they all work. The gray scale image is an option and the parameters option can be a cell array of strings or several arguments that are all individual strings. I usually use the first way I showed.
But if you try to use myWrapper thus:
stats = myWrapper(L, I, 'Area' 'Centroid');
won't it try unsuccessfully to call
regionprops(L, {I, 'Area' 'Centroid'})
In this particular situation with regionprops when L is logical, I just want to pass it along to regionprops unmodified. I tried passing varargin(1:end), but that failed and looking at Image Analyst's comments above I see why.
regionprops(modifiedL, varargin(2:end))
is like regionprops(modifiedL, {'Area','Centroid'}) above. But then
regionprops(varargin(1:end))
doesn't work because it makes it all a cell like I was doing incorrectly above.
However, David's solution of {:} seems to work in both cases.
Well you have to have some guidelines in what you pass in. If you're going to pass in the original grayscale image (which is usually not done), then you should extract it:
originalGrayImage = varargin{2};
measurements = varargin(3:end);
If, for some reason, you don't know what to expect to be passed in, then you can use isa() to see whether varargin{2} is a numerical array or a string or cell array and call or don't call the line above as appropriate.
Yes, using varargin{:} would work after you've modified it but the reason I added my answer was that David simply passed through varargin (with the labeled image unaltered) to regionprops, not modifying it to produce a new labeled image where some blobs were reassigned labels like you asked for, for example if you wanted to modify it so that some disconnected blobs would be considered all part of the same region (something I've done on occasion).
My answer was intended as a correction to the final line of code in the original question - hence I assumed that varargin{1} had been updated.
It's really a rather trivial point I wanted to make, and maybe not worth labouring. It was this: you can make a wrapper that is robust, in that it accepts all the same input patterns as regionprops, as easily as making one that fails if the original image is the second argument.
To achieve generality, either use the original code from the question, with the final line modified as in my answer, or use Image Analyst's code, with the final line modified to
statsOut = regionprops(modifiedLabelMatrix, measurements{:});
It's then not necessary to do any additional checking or extraction of the second argument.

Sign in to comment.

More Answers (1)

You need
statsOut=regionprops(varargin{:});
which passes the contents of varargin as a comma-separated list.

1 Comment

Thanks - I had forgotten about this easy way to burst apart a cell array.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!