You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: feature_homography_demo.m
    path of file: ./repos/mexopencv/samples
    
    the code of the file until where you have to start completion: %% Feature Matching + Homography to find a known object
% In this sample, you will use features2d and calib3d to detect an object in a
% scene.
%
% You will learn how to:
%
% * Use the function <matlab:doc('cv.findHomography') cv.findHomography> to
%   find the transform between matched keypoints.
% * Use the function
%   <matlab:doc('cv.perspectiveTransform') cv.perspectiveTransform> to map the
%   points.
%
% Sources:
%
% * <https://docs.opencv.org/3.2.0/d7/dff/tutorial_feature_homography.html>
% * <https://docs.opencv.org/3.2.0/dd/dd4/tutorial_detection_of_planar_objects.html>
% * <https://docs.opencv.org/3.2.0/d1/de0/tutorial_py_feature_homography.html>
% * <https://github.com/opencv/opencv/blob/3.2.0/samples/python/find_obj.py>
%

%%
% In a previous demo, we used a |queryImage|, found some feature points in it,
% we took another |trainImage|, found the features in that image too and we
% found the best matches among them. In short, we found locations of some
% parts of an object in another cluttered image. This information is
% sufficient to find the object exactly on the |trainImage|.
%
% For that, we can use a function from _calib3d_ module, |cv.findHomography|.
% If we pass the set of points from both the images, it will f
    
function <matlab:doc('cv.findHomography') cv.findHomography> to
%   find the transform between matched keypoints.
% * Use the function
%   <matlab:doc('cv.perspectiveTransform') cv.perspectiveTransform> to map the
%   points.
%
% Sources:
%
% * <https://docs.opencv.org/3.2.0/d7/dff/tutorial_feature_homography.html>
% * <https://docs.opencv.org/3.2.0/dd/dd4/tutorial_detection_of_planar_objects.html>
% * <https://docs.opencv.org/3.2.0/d1/de0/tutorial_py_feature_homography.html>
% * <https://github.com/opencv/opencv/blob/3.2.0/samples/python/find_obj.py>
%

%%
% In a previous demo, we used a |queryImage|, found some feature points in it,
% we took another |trainImage|, found the features in that image too and we
% found the best matches among them. In short, we found locations of some
% parts of an object in another cluttered image. This information is
% sufficient to find the object exactly on the |trainImage|.
%
% For that, we can use a function from _calib3d_ module, |cv.findHomography|.
% If we pass the set of points from both the images, it will find the
% perpective transformation of that object. Then we can use
% |cv.perspectiveTransform| to find the object. It needs atleast four correct
% points to find the transformation.
%
% We have seen that there can be some possible errors while matching which may
% affect the result. To solve this problem, algorithm uses |Ransac| or |LMedS|
% (which can be specificed in the |Method| option). So good matches which
% provide correct estimation are called inliers and remaining are called
% outliers. |cv.findHomography| returns a mask which specifies the inlier and
% outlier points.
%

%% Options
OPTS_FEATURE = 'SURF';   % detector: ORB, BRISK, AKAZE, KAZE, SIFT, SURF
OPTS_FLANN = true;       % matcher: FLANN or Brute Force
OPTS_KNN_MATCH = false;  % matcher method: match or knnMatch (k=2)

%% Input images
imgObj = cv.imread(fullfile(mexopencv.root(),'test','box.png'), 'Grayscale',true);
imgScene = cv.imread(fullfile(mexopencv.root(),'test','box_in_scene.png'), 'Grayscale',true);
subplot(1,3,1), imshow(imgObj), title('object')
subplot(1,3,[2 3]), imshow(imgScene), title('scene')

%% Step 1: Detect the keypoints and extract descriptors using SURF
switch upper(OPTS_FEATURE)
    case 'SURF'
        detector = cv.SURF('HessianThreshold',400);
    case 'SIFT'
        detector = cv.SIFT();
    case 'ORB'
        detector = cv.ORB();
    case 'BRISK'
        detector = cv.BRISK();
    case 'AKAZE'
        detector = cv.AKAZE();
    case 'KAZE'
        detector = cv.KAZE();
    otherwise
        error('unrecognized feature: %s', OPTS_FEATURE)
end
display(detector)

%%
[keyObj,featObj] = detector.detectAndCompute(imgObj);
[keyScene,featScene] = detector.detectAndCompute(imgScene);
fprintf('object: %d keypoints\n', numel(keyObj));
fprintf('scene: %d keypoints\n', numel(keyScene));
whos featObj featScene

%% Step 2: Matching descriptor vectors using FLANN matcher
if OPTS_FLANN
    if ~isempty(strfind(detector.defaultNorm(), 'Hamming'))
        opts = {'LSH', 'TableNumber',6, 'KeySize',12, 'MultiProbeLevel',1};
    else
        opts = {'KDTree', 'Trees',5};
    end
    matcher = cv.DescriptorMatcher('FlannBasedMatcher', 'Index',opts);
else
    matcher = cv.DescriptorMatcher('BFMatcher', ...
        'NormType',detector.defaultNorm());
end
display(matcher)

%%
if OPTS_KNN_MATCH
    matches = matcher.knnMatch(featObj, featScene, 2);
else
    matches = matcher.match(featObj, featScene);
end
fprintf('%d matches\n', numel(matches));

%%
% Filter matches and keep only "good" ones
if OPTS_KNN_MATCH
    % ratio test
    dists = cellfun(@(m) m(1).distance, matches);
    idx = cellfun(@(m) (numel(m) == 2) && ...
        (m(1).distance < 0.75 * m(2).distance), matches);
    matches = cellfun(@(m) m(1), matches(idx));
else
    % distance less than k*min_dist
    dists = [matches.distance];
    cutoff = 3 * min(dists);
    matches = matches(dists <= cutoff);
    fprintf('Min dist = %f\nMax dist = %f\nCutoff = %f\n', ...
        min(dists), max(dists), cutoff);
end