%% Feature Matching
% This example shows how to generate CUDA(R) MEX from MATLAB(R) code and 
% perform feature matching between two images. This example uses the 
% <docid:vision_ref#bsvbhh1-1 matchFeatures> function from the Image 
% Processing Toolbox(TM) to match the feature descriptors between two 
% images that are rotated and scaled with respect to each other. The 
% feature descriptors of the two images are detected and extracted by 
% using the Speeded-Up Robust Features (SURF) algorithm.

%Copyright 2010-2019 The MathWorks, Inc.

%% Prerequisites
% * CUDA enabled NVIDIA(R) GPU with compute capability 3.2 or higher.
% * NVIDIA CUDA toolkit and driver.
% * Computer Vision Toolbox(TM) for the video reader and viewer 
% used in the example.
% * Image Processing Toolbox for reading and displaying images.
% * Environment variables for the compilers and libraries. For information 
% on the supported versions of the compilers and libraries, see 
% <docid:gpucoder_gs#mw_aa8b0a39-45ea-4295-b244-52d6e6907bff
% Third-Party Products>. For setting up the environment variables, see 
% <docid:gpucoder_gs#mw_453fbbd7-fd08-44a8-9113-a132ed383275
% Environment Variables>.

%% Create a Folder and Copy Relevant Files
% The following line of code creates a folder in your current working 
% folder (pwd) and copies all the relevant files into this folder. If you 
% do not want to perform this operation or if you cannot generate files in 
% this folder, change your current working folder.
gpucoderdemo_setup('gpucoderdemo_feature_matching');


%% Verify GPU Environment
% To verify that the compilers and libraries necessary for running this example
% are set up correctly, use the <docid:gpucoder_ref#mw_0957d820-192f-400a-8045-0bb746a75278 coder.checkGpuInstall>
% function.
envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

%% Feature Detection and Extraction
% For this example, feature matching is performed on two images that are 
% rotated and scaled with respect to each other.
% Before the two images can be matched, feature points for each image must 
% be detected and extracted. The following 
% <matlab:edit(fullfile(matlabroot,'toolbox','gpucoder','gpucoderdemos','gpucoderdemo_feature_matching','featureDetectionAndExtraction.m')) featureDetectionAndExtraction>
% function uses SURF (<docid:vision_ref#bs39_qf-1 detectSURFFeatures>) 
% local feature detector to detect the feature points and <docid:vision_ref#bsxmas0 extractFeatures> 
% to extract the features.
%
% The function |featureDetectionAndExtraction| returns |refPoints|, which
% contains the feature coordinates of the reference image, |qryPoints|,
% containing feature coordinates of query image, |refDesc| matrix
% containing reference image feature descriptors and |qryDesc| matrix
% containing query image feature descriptors.
%
% refPoints = Reference image feature coordinates.
% qryPoints = Query image feature coordinates.
% refDescFeat = Reference image feature descriptors.
% qryDescFeat = Query image feature descriptors.

% Read Image
K = imread('cameraman.tif'); % Reference image
refImage = imresize(K,3);

scale = 0.7;  % Scaling the image.
J = imresize(refImage, scale);
theta = 30.0;   % Rotating the image
qryImage = imrotate(J,theta); % Query image

[refPoints,refDescFeat,qryPoints,qryDescFeat] = featureDetectionAndExtraction(refImage, qryImage);

%% The |feature_matching| Entry-Point Function
% The <matlab:edit(fullfile(matlabroot,'toolbox','gpucoder','gpucoderdemos','gpucoderdemo_feature_matching','feature_matching.m')) feature_matching>
% function takes feature points and feature descriptors extracted from two
% images and finds a match between them.
type feature_matching

%% Feature Matching Code Generation
% Because the example runs on the host system, create a MEX-call configuration
% object with default parameters. To avoid abnormal termination of MATLAB 
% if there are run-time errors in the generated code, select the safe-build 
% option.
cfg = coder.gpuConfig;
cfg.GpuConfig.SafeBuild = 1;
codegen -config cfg -args {refPoints,refDescFeat,qryPoints,qryDescFeat} feature_matching -o feature_matching_gpu_mex
[matchedRefPoints_gpu,matchedQryPoints_gpu] = feature_matching_gpu_mex(refPoints,refDescFeat,qryPoints,qryDescFeat);

%% Display Feature Matches
figure;
showMatchedFeatures(refImage, qryImage, matchedRefPoints_gpu, matchedQryPoints_gpu);
title('Putatively Matched Points (Including Outliers)');

%% Cleanup
% Remove the temporary files and return to the original folder.
cleanup

displayEndOfDemoMessage(mfilename)
