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']; %#okend 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