main content

code generation for face tracking with packngo -凯发k8网页登录

this example shows how to generate code from example with packngo function. the (matlab coder) function packages all relevant files in a compressed zip file so you can relocate, unpack, and rebuild your project in another development environment without matlab present. this example also shows how to create a makefile for the packngo content, rebuild the source files and finally run the standalone executable outside matlab environment.

this example requires a matlab® coder™ license.

this example is a function with the main body at the top and helper routines in the form of below.

function facetrackingkltpackngoexample()

set up your c compiler

to run this example, you must have access to a c compiler and you must configure it using 'mex -setup c ' command. for more information, see . if you deploy the application on matlab host, use a c compiler that is compatible with the compiler used to build opencv libraries. for more information, see .

break out the computational part of the algorithm into a separate matlab function

matlab coder requires matlab code to be in the form of a function in order to generate c code. the code for the main algorithm of this example resides in a function called . this file is derived from . to learn how to modify the matlab code to make it compatible for code generation, you can look at example .

filename = 'facetrackingkltpackngo_kernel.m';
visiondemo_dir = pwd;
currentdir = pwd; % store the current directory
filename = fullfile(visiondemo_dir, filename);

configure code generation arguments for packngo

create a code generation configuration object for exe output with packngo function call in post code generation stage.

codegenargs = createcodegenargs(visiondemo_dir);

setup code generation environment

change output directory name.

codegenoutdir = fullfile(visiondemo_dir, 'codegen');
mkdir(codegenoutdir);

add path to the existing directory to have access to necessary files.

currentpath = addpath(visiondemo_dir);
pathcleanup = oncleanup(@()path(currentpath));
cd(codegenoutdir);
dirchange = oncleanup(@()cd(currentdir));

create the packaged zip-file

invoke codegen command with packngo function call.

fprintf('-> generating code (it may take a few minutes) ....\n');
codegen(codegenargs{:}, filename);
-> generating code (it may take a few minutes) ....
code generation successful.

note that, instead of using codegen command, you can open a dialog and launch a code generation project using codegen (matlab coder). use the post code generation command with packngo function to create a zip file.

build standalone executable

unzip the zip file into a new folder. note that the zip file contains source files, header files, libraries, mat-file containing the build information object, data files. unzippackagecontents and other helper functions are included in the appendix.

zipfilelocation  = codegenoutdir;
fprintf('-> unzipping files ....\n');
unzipfolderlocation       = unzippackagecontents(zipfilelocation);
-> unzipping files ....

create platform dependent makefile from a template makefile.

fprintf('-> creating makefile ....\n');
[~, fname, ~] = fileparts(filename);
makefilename = createmakefile(visiondemo_dir, unzipfolderlocation, fname);
-> creating makefile ....

create the commands required to build the project and to run it.

fprintf('-> creating ''build command'' and ''run command'' ....\n');
[buildcommand, runcommand] = createbuildandruncommands(zipfilelocation,...
    unzipfolderlocation,makefilename,fname);
-> creating 'build command' and 'run command' ....

build the project using build command.

fprintf('-> building executable....\n');
buildexecutable(unzipfolderlocation, buildcommand);
-> building executable....

run the executable and deploy

run the executable and verify that it works.

cd(unzipfolderlocation);
system(runcommand);

the application can be deployed in another machine by copying the executable and the library files.

ispublishing = ~isempty(snapnow('get'));
if ~ispublishing % skip printing out directory to html page
  fprintf('executable and library files are located in the following folder:\n%s\n', unzipfolderlocation);
  fprintf('to re-execute run the following commands:\n');
  fprintf('1. cd(''%s'')\n', unzipfolderlocation);
  fprintf('2. system(''%s'')\n', runcommand);
end

appendix - helper functions

    % configure coder to create executable. use packngo at post code
    % generation stage.
    function codegenargs = createcodegenargs(folderformainc)
        % create arguments required for code generation.
        % for standalone executable a main c function is required. the main.c
        % created for this example is compatible with the content of the file
        % visionfacetrackingkltpackngo_kernel.m
        maincfile = fullfile(folderformainc,'main.c');
        % handle path with space
        if contains(maincfile, ' ')
            maincfile = ['"' maincfile '"'];
        end
        cfg                               = coder.config('exe');
        cfg.postcodegencommand            = 'packngo(buildinfo,''packtype'',''hierarchical'');';
        cfg.customsource                  = maincfile;
        cfg.custominclude                 = folderformainc;
        cfg.enableopenmp                  = false;
        codegenargs = {'-config', cfg};
    end
    % create a folder and unzip the packngo content into it.
    function unzipfolderlocation   = unzippackagecontents(zipfilelocation)
        % unzip the packaged zip file.
        unzipfolderlocationname = 'unzippackngo';
        mkdir(unzipfolderlocationname);
        % get the name of the zip file generated by packngo.
        zipfile = dir('*.zip');
        assert(numel(zipfile)==1);
        unzip(zipfile.name,unzipfolderlocationname);
        % unzip internal zip files created in hierarchical packngo.
        zipfileinternal = dir(fullfile(unzipfolderlocationname,'*.zip'));
        assert(numel(zipfileinternal)==3);
        for i=1:numel(zipfileinternal)
            unzip(fullfile(unzipfolderlocationname,zipfileinternal(i).name), ...
                unzipfolderlocationname);
        end
        unzipfolderlocation = fullfile(zipfilelocation,unzipfolderlocationname);
    end
    % create platform dependent makefile from template makefile. use
    % buildinfo to get info about toolchain.
    function makefilename = createmakefile(visiondemo_dir, unzipfolderlocation, fname)
        % create makefile from buildinfo.
        binfo = load(fullfile(pwd, 'codegen', 'exe', fname, 'buildinfo.mat'));
        lastdir    = cd(unzipfolderlocation);
        dircleanup = oncleanup(@()cd(lastdir));
        % get the root directory that contains toolbox/vision sub-directories
        matlabdirname = getrootdirname(unzipfolderlocation);
        % get defines
        horzcat_with_space = @(cellval)sprintf('%s ',cellval{:});
        defs   = horzcat_with_space(getdefines(binfo.buildinfo));
        % get source file list
        if ispc
            [~, cfiles] = system(['dir /s/b ' '*.c']);
            [~, cppfiles] = system(['dir /s/b ' '*.cpp']);
        else
            [~, cfiles] = system(['find ./ ' '-name ' '''*.c''']);
            [~, cppfiles] = system(['find ./ ' '-name ' '''*.cpp''']);
        end
        cindx = strfind(cfiles, '.c');
        cppindx = strfind(cppfiles, '.cpp');
        srcfilesc = [];
        srcfilescpp = [];
        for i = 1:length(cindx)
            if i == 1
                startidx = 1;
                endidx = cindx(i);
            else
                startidx = cindx(i-1) 1;
                endidx = cindx(i);
            end
            [~, b, ~] = fileparts(cfiles(startidx:endidx));
            srcfilesc = [srcfilesc ' ' b '.c']; %#ok
        end
        for i = 1:length(cppindx)
            if i == 1
                startidx = 1;
                endidx = cppindx(i);
            else
                startidx = cppindx(i-1) 1;
                endidx = cppindx(i);
            end
            [~, b, ~] = fileparts(cppfiles(startidx:endidx));
            srcfilescpp = [srcfilescpp ' ' b '.cpp']; %#ok
        end
        srcfiles = [srcfilesc ' ' srcfilescpp];
        % get platform dependent names
        if isunix % both mac and linux
            tmf = 'templatemakefilepackngo_unix';
            if ismac
                archdir = 'maci64';
                dllext  = 'dylib';
            else
                archdir = 'glnxa64';
                dllext  = 'so';
            end
        else
            tmf = 'templatemakefilepackngo_win';
            archdir = 'win64';
            dllext  = 'dll';
        end
        % now that we have defines, lets create a platform dependent makefile
        % from template.
        fid = fopen(fullfile(visiondemo_dir,tmf));
        filecontent = char(fread(fid)');
        fclose(fid);
        newfilecontent = regexprep(filecontent,...
                {'paste_arch','paste_ext','paste_defines','paste_srcfiles', 'paste_matlab'},...
                { archdir,     dllext,      defs,           srcfiles,         matlabdirname});
        makefilename = 'makefile';
        mk_name = fullfile(unzipfolderlocation,makefilename);
        if isunix
            if( ismac )
                [status,sysheaderpath] = system( 'xcode-select -print-path' );
                assert(status==0, ['could not obtain a path to the system ' ...
                           'header files using ''xcode-select -print-path''' '']);
                [status,sdkpaths] = system( 'xcrun -sdk macosx --show-sdk-path' );
                assert(status==0, 'could not find macosx sdk' );
               % there might be multiple sdk's
                sdkpathcell = strsplit(sdkpaths,'\n');
                for idx = 1:numel(sdkpathcell)
                   if ~isempty(sdkpathcell{idx})
                       % pick the first one that's not empty.
                       sdkpath = sdkpathcell{idx};
                       fprintf('choosing sdk in %s\n',sdkpath);
                       break;
                   end
                end
                assert(~isempty(sdkpath), ...
                  sprintf('there is no sdk available in %s. please check system environment.\n',sysheaderpath));
                cccmd = [ 'xcrun clang -isysroot ' deblank( sdkpath ) ];
                cppcmd = [ 'xcrun clang   -isysroot ' deblank( sdkpath ) ];
            else
                cccmd  = 'gcc';
                cppcmd = 'g  ';
            end
            newfilecontent = regexprep(newfilecontent,'paste_cc',cccmd);
            newfilecontent = regexprep(newfilecontent,'paste_cpp',cppcmd);
        end
        fid = fopen(mk_name,'w ');
        fprintf(fid,'%s',newfilecontent);
        fclose(fid);
    end
    % create platform specific commands needed to build the executable and
    % to run it.
    function [buildcommand, runcommand] = createbuildandruncommands( ...
        packagelocation,unzipfolderlocation,makefilename,filename)
        % create the build and run command.
        if ismac
            buildcommand = [' xcrun make -f ' makefilename];
            runcommand   = ['./' filename ' "' filename '"'];
        elseif isunix
            buildcommand = [' make -f ' makefilename];
            runcommand   = ['./' filename ' "' filename '"'];
        else
            % on pc we use the generated bat files (there should be 2) to help
            % build the generated code.  these files are copied to the
            % unzipfolderlocation where we can use them to build.
            batfilename       = [filename '_rtw.bat'];
            batfilelocation   = fullfile(packagelocation,'codegen', ...
                                         filesep,'exe',filesep,filename);
            batfiledestination = unzipfolderlocation;
            % for msvc, also copy 'setup_msvc.bat'
            fid = fopen(fullfile(batfilelocation, batfilename));
            batfilecontent = fread(fid, '*char');
            fclose(fid);
            if ~isempty(regexp(convertcharstostrings(batfilecontent), 'setup_msvc.bat', 'once'))
                setup_msvc_batfile = fullfile(batfilelocation, 'setup_msvc.bat');
                copyfile(setup_msvc_batfile, batfiledestination);
            end
            % copy it to packngo output directory.
            copyfile(fullfile(batfilelocation,batfilename),batfiledestination);
            % the makefile we created is named 'makefile', whereas the batch
            % file refers to _rtw.mk. hence we rename the file.
            newmakefilename = [filename '_rtw.mk'];
            oldmakefilename = makefilename;
            copyfile(fullfile(batfiledestination,oldmakefilename),...
                fullfile(batfiledestination,newmakefilename));
            buildcommand = batfilename;
            runcommand   = [filename '.exe' ' "' filename '"'];
        end
    end
    % build the executable with the build command.
    function buildexecutable(unzipfolderlocation, buildcommand)
        % call system command to build the executable.
        lastdir    = cd(unzipfolderlocation);
        dircleanup = oncleanup(@()cd(lastdir));
        [haderror, sysresults] = system(buildcommand);
        if haderror
            error (sysresults);
        end
    end
    % get the root directory that contains toolbox/vision sub-directories
    function matlabdirname = getrootdirname(unzipfoldername)
        dirlists = dir(unzipfoldername);
        dirlists = dirlists(~ismember({dirlists.name},{'.','..'}));
        matlabdirname='';
        for ij=1:length(dirlists)
            thisdirname = dirlists(ij).name;
            if (isfolder(thisdirname))
                % subdirectory will have toolbox/vision
                [subdir1, hassubdir1]  = hassubdirectory(thisdirname, 'toolbox');
                if hassubdir1
                    [~, hassubdir2]  = hassubdirectory(subdir1, 'vision');
                    if hassubdir2
                        matlabdirname = thisdirname;
                        break;
                    end
                end
            end
        end
    end
    % find the directory that contains the specified sub-directory
    function [subdir, hassubdir]  = hassubdirectory(dirname, subdirname)
        dirlists = dir(dirname);
        dirlists = dirlists(~ismember({dirlists.name},{'.','..'}));
        subdir = '';
        hassubdir = false;
        for ij=1:length(dirlists)
            thisdirname = dirlists(ij).name;
            thisdir = fullfile(dirname,thisdirname);
            if (isfolder(thisdir) && strcmp(thisdirname, subdirname))
                hassubdir = true;
                subdir = thisdir;
                break;
            end
        end
    end
end
网站地图