Passing parameters to function handle in bagOfFeatures function - matlab

Lets say we have a custom extractor function
[features,featureMetrics] = exampleBagOfFeaturesExtractor(img,param1, param2)
I want to call bagOfFeatures function and pass custom extractor function:
extractorFcn = #exampleBagOfFeaturesExtractor;
bag = bagOfFeatures(imgSets,'CustomExtractor',extractorFcn)
In exampleBagOfFeaturesExtractor function I want to use different local descriptors extractor depending on param1.
How do I pass param1 to exampleBagOfFeaturesExtractor?
What is the best way to use different local descriptors in my custom extractor function?
Thank you for your help!
Edit
This is the custom extractor function I am currently using:
function [features,featureMetrics] = exampleBagOfFeaturesExtractor(img,param1,param2)
keypoint_detector = cv.FeatureDetector(param1);
descriptor_extractor = cv.DescriptorExtractor(param2);
kpts = keypoint_detector.detect(img);
[ features, kpts ] = descriptor_extractor.compute(img, kpts);
featureMetrics=ones(1,size(features,1))/size(features,1);
end

The expected kind of functions that the bagOfFeatures function requires can only be a single input, namely the input image. Therefore, if you want to create a custom feature extractor where you can vary the parameters, you will need to first create the parameters, then create an anonymous function that captures these parameters via lexical closure. This means that when you create the anonymous function, make sure the parameters are created so that when you reference them in your anonymous function, they capture the most up to date version of the parameters prior to creating the function.
Therefore, assuming param1 and param2 already exist in your workspace, create a function like so:
% Create param1 and param2 here
param1 = ...;
param2 = ...;
extractorFcn = #(img) exampleBagOfFeaturesExtractor(img, param1, param2);
This creates an anonymous function that takes in a single input - your image. param1 and param2 are thus captured in your function, so the state of the variables is recorded and are made available within the anonymous function. Also note that the function doesn't take in additional inputs, only the input image. You can then call bagOfFeatures as normal. However, should you want to change param1 or param2, not only will you have to change these parameters, but you must re-declare the anonymous function again so that the latest stage of the variables is recaptured.
As a quick example, suppose I've created an anonymous function like so:
x = 5;
y = #(t) t + x;
This function y takes the current state of x and adds it with a variable t. For now, this acts like how we expect it:
>> x = 5;
>> y = #(t) t + x;
>> y(6)
ans =
11
We put in the value 6 and we get 11. If we try and change x then call y, it will not change this in the function as it captured the state of the variable before you created the function:
>> x = 10;
>> y(6)
ans =
11
Therefore, if you want to change the parameters, you must also re-declare the function again before calling bagOfFeatures, so:
param1 = ...; % Change this to something new
param2 = ...; % Change this if you like as well
extractorFcn = #(img) exampleBagOfFeaturesExtractor(img, param1, param2);
In MATLAB terms, these variables persist in the anonymous function. You can read more about it here: https://www.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html#f4-71621

Related

Difference between matlab function 'handle' and python function 'object'

It was suggested in this comment that there is a difference between how Matlab and Python pass around functions. From what I can tell by looking and using the two, there is no difference between the two, but maybe I'm missing something?
In Matlab, you would create a quick function handle like this:
fun = #(x) x.^2 + 1;
In Python, using a lambda function, you could create a similar function like this:
def fun(x):
return x^2
In both languages, it's possible to send the term 'fun' to another function as an argument - but the commenter I linked to insinuated that they are not the same and/or need to be used differently.
What am I missing?
The first comment seems to simply reiterate the idea that you can pass a MATLAB function handle as an argument (although the answer didn't state anything that would make me think otherwise). The second comment seemed to interpret this to mean that the first commenter thought that you couldn't do this in Python and responded to state that you can use either a lambda or pass the function directly.
Regardless, assuming that you use them correctly, a function handle in MATLAB is functionally equivalent to using either a lambda or function object as an input argument in Python.
In python, if you don't append the () to the end of the function, it doesn't execute the function and instead yields the function object which can then be passed to another function.
# Function which accepts a function as an input
def evalute(func, val)
# Execute the function that's passed in
return func(val)
# Standard function definition
def square_and_add(x):
return x**2 + 1
# Create a lambda function which does the same thing.
lambda_square_and_add = lambda x: x**2 + 1
# Now pass the function to another function directly
evaluate(square_and_add, 2)
# Or pass a lambda function to the other function
evaluate(lambda_square_and_add, 2)
In MATLAB, you have to use a function handle because MATLAB attempts to execute a function even if you omit the ().
function res = evaluate(func, val)
res = func(val)
end
function y = square_and_add(x)
y = x^2 + 1;
end
%// Will try to execute square_and_add with no inputs resulting in an error
evaluate(square_and_add)
%// Must use a function handle
evaluate(#square_and_add, 2)

Retrieve name of output arguments within a function

It is possible to use the function inputname to retrieve the workspace variable name passed in the call to the currently executing function. However, is there any equivalent function to obtain the name of the output arguments specified in the call to the currently executing function?
Imagine I have the following function:
function [a,b,c] = test(x)
disp([ouputname(1),ouputname(2),ouputname(3)])
end
When running this function:
[my,name,is] = test(x)
The expected result should be:
mynameis
Simply: no there isn't.
Complicated: Matlab code is "compiled" on run-time, and there is no way, that it knows [my,name,is] before it returns the result of test(x).
Workaround: if you want to ensure, that the strings used within the function are equal to the variables returned to the workspace, you can do the following using assignin:
function test(x, varnames)
a = 1;
outputname{1} = varnames{1};
assigin('base', outputname{1}, a)
...
c = 3;
outputname{3} = varnames{3};
assigin('base', outputname{3}, c)
disp([outputname{:}])
end
and call your function like:
text(x,{'my','name','is'})
and you will have exactly this variables in your workspace afterwards and your function output:
"mynameis"

Call a function with several properties of an object

For (MEX) function calls it would be really nice to pass several properties of one object at once. Instead of foo(myObj.propA, myObj.propB) I want something like foo(myObj.[propA,propB].
Is this even possible?
With structs it is possible to use the getfield() function to get the data from more than one field, e.g.:
getfield(myStruct, {index}, {'fieldA', 'fieldB'})
But unfortunately, the following attempt to get more than one property from an object results in an error (Index exceeds matrix dimensions):
getfield(myObj, {index}, {'propA', 'propB'})
Maybe the only possibility is to write a function which returns several output arguments:
[varargout] = getProps(object,propnames)
for p=1:numel(propnames)
varargout{p} = object.(propnames{p});
end
But if I call another function with that function as input, e.g. sum(getProps(myObj,propnames)) only the first output argument of getProps is passed and I fall into despair. Is there any other way?
For an object, you'd use get, not getfield (or dynamic access in a loop like you showed).
>> h = figure;
>> get(h,{'Position','Renderer'})
ans =
[1x4 double] 'opengl'
This doesn't work for all objects, but for MATLAB graphics objects it does work. To deal with any class, you can use your function, but with a custom cell output instead of varargout:
function C = getProps(object,propnames)
for p = 1:numel(propnames),
C{p} = object.(propnames{p});
end
Then inside whatever function you write, you can get a comma-separated list of all properties with C{:}, which will be suitable for a function that expects each property name input as a separate argument (e.g. C = getProps(myObj,propnames); x = myFun(h,C{:}).

MATLAB: Function Handle of Nested Function

Is there a way to create a function handle to a nested function that includes the parent function in the function handle?
As an example, say I have:
function myP = myParent()
myP.My_Method = myMethod;
function myMethod()
disp "hello world"
end
end
In another file, I could call the method by doing something like:
myP = myParent();
myP.My_Method();
But, if I have another function that takes function handles as a parameter and then calls the function, how do I pass in the function handle to myMethod in this case, since this new function can't create a myParent variable.
The following seems to work:
function myP = myParent()
myP.My_Method = #myMethod;
function myMethod()
s=dbstack;
fprintf('Hello from %s!\n',s(1).name);
end
end
Running it as follows:
>> myP = myParent()
myP =
My_Method: #myParent/myMethod
>> feval(myP.My_Method)
Hello from myParent/myMethod!
>> myP.My_Method()
Hello from myParent/myMethod!
It is also fine to run it from another function:
% newfun.m
function newfun(hfun)
feval(hfun)
Test:
>> newfun(myP.My_Method)
Hello from myParent/myMethod!
Depending on what you are doing, this should be enough. Note that each handle you create is unique since it contains information about externally scoped variables (variables pulled in the parent):
When you create a function handle for a nested function, that handle stores not only the name of the function, but also the values of externally scoped variables.

MATLAB- passing a function handle parameter into another function as a handle

Working on an assignment involving Genetic Algorithms (loads of headaches, loads of fun). I need to be able to test differing crossover methods and differing mutation methods, to compare their results (part of the paper I have to write for the course). As such, I want to just pass the function names into the Repopulate method, as function handles.
function newpop = Repopulate(population, crossOverMethod, mutationMethod)
...
child = crossOverMethod(parent1, parent2, #mutationMethod);
...
function child = crossOverMethod(parent1, parent2, mutationMethod)
...
if (mutateThisChild == true)
child = mutationMethod(child);
end
...
The key point here is like 3, parameter 3: how do I pass mutationMethod down another level? If I use the # symbol, I get told:
"mutationMethod" was previously used as a variable,
conflicting with its use here as the name of a function or command.
If I don't use the # symbol, then mutationMethod gets called, with no parameters, and is quite unhappy.
While I am aware that yes, I could just rewrite my code to make it work differently, I'm now curious as to how to make it actually work.
Any help is greatly appreciated.
Actually just dont use the # symbol, use it when you call the Repopulate function instead.
Example:
function x = fun1(a,m)
x = fun2(a,m);
end
function y = fun2(b,n)
y = n(b);
end
which we call as:
> fun1([1 2 3], #sum)
6
Refer to the documentation for Passing Function Handle Arguments
Note you can check if the argument is a function handle by: isa(m,'function_handle'). Therefore you can make your function Repopulate more flexible by accepting both a function handle and a function name as a string:
function x = fun(a,m)
if ischar(m)
f = str2func(m);
elseif isa(m,'function_handle')
f = m;
else
error('expecting a function')
end
x = fun2(a,f);
end
which now can be called both ways:
fun1([1 2 3], #sum)
fun1([1 2 3], 'sum')