主要内容

代码生成与PackNGo的人脸跟踪

这个例子展示了如何从基于KLT算法的人脸检测与跟踪packNGo函数的例子。的packNGo(MATLAB编码器)函数将所有相关文件打包在一个压缩的zip文件中,这样您就可以在没有MATLAB的情况下在另一个开发环境中重新定位、解包和重建项目。本例还展示了如何为packNGo内容创建makefile,重新构建源文件,并最终在MATLAB环境之外运行独立的可执行文件。

本例需要MATLAB®Coder™许可证。

这个例子是一个函数,其主体位于顶部,辅助例程的形式为嵌套函数在下面。

函数FaceTrackingKLTpackNGoExample ()

设置你的c++编译器

要运行这个示例,您必须能够访问c++编译器,并且必须使用'mex -setup c++'命令对其进行配置。有关更多信息,请参见选择一个c++编译器.如果将应用程序部署在MATLAB主机上,请使用与用于构建OpenCV库的编译器兼容的c++编译器。有关更多信息,请参见可移植的C代码生成函数使用OpenCV库

将算法的计算部分分解为一个单独的MATLAB函数

MATLAB Coder要求MATLAB代码以函数的形式生成C代码。本例中主要算法的代码驻留在一个名为FaceTrackingKLTpackNGo_kernel.m.该文件派生自基于KLT算法的人脸检测与跟踪.要了解如何修改MATLAB代码以使其与代码生成兼容,您可以查看示例使用特征匹配和注册的代码生成介绍

文件名=“FaceTrackingKLTpackNGo_kernel.m”;Visiondemo_dir = pwd;currentDir = pwd;保存当前目录fileName = fullfile(visiondemo_dir, fileName);

配置代码生成参数packNGo

在邮政代码生成阶段使用packNGo函数调用创建EXE输出的代码生成配置对象。

codegenArgs = createCodegenArgs(visiondemo_dir);

设置代码生成环境

更改输出目录名称。

codegenOutDir = fullfile(visiondemo_dir,“codegen”);mkdir (codegenOutDir);

向现有目录添加路径以访问必要的文件。

currentPath = addpath(visiondemo_dir);pathCleanup = onCleanup(@()path(currentPath));cd (codegenOutDir);dirChange = onCleanup(@()cd(currentDir));

创建打包的zip文件

使用packNGo函数调用调用代码原命令。

流('->生成代码(可能需要几分钟)....\n');codegen (codegenArgs{:},文件名);
->生成代码(可能需要几分钟)....代码生成成功。

请注意,您可以使用codegen命令打开对话框并启动代码生成项目,而不是使用codegen(MATLAB编码器).使用邮政编码生成命令和packNGo功能来创建一个zip文件。

构建独立可执行文件

将zip文件解压缩到一个新文件夹中。注意,zip文件包含源文件、头文件、库、包含构建信息对象的mat文件、数据文件。unzipPackageContents和其他辅助函数都包含在附录中。

zipFileLocation = codegenOutDir;流('->解压文件....\n');unzipFolderLocation = unzipppackagcontents (zipFileLocation);
->解压缩文件....

从模板生成文件创建平台相关的生成文件。

流(->创建makefile ....\n');[~, fname, ~] = fileparts(fileName);makefileName = createMakeFile(visiondemo_dir, unzipFolderLocation, fname);
->创建makefile ....

创建构建项目和运行项目所需的命令。

流(->创建“构建命令”和“运行命令”....\n”);[buildCommand, runCommand] = createBuildAndRunCommands(zipFileLocation,...unzipFolderLocation, makefileName、帧);
->创建“构建命令”和“运行命令”....

使用Build命令构建项目。

流('->构建可执行文件....\n');buildExecutable (unzipFolderLocation buildCommand);
->构建可执行文件....

运行可执行文件并部署

运行可执行文件并验证它是否正常工作。

cd (unzipFolderLocation);系统(runCommand);

通过复制可执行文件和库文件,应用程序可以部署在另一台机器上。

isPublishing = ~isempty(snapnow(“得到”));如果~ isPublishing跳过将目录打印到HTML页面流('可执行文件和库文件位于以下文件夹:\n%s\n', unzipFolderLocation);流(要重新执行,请执行以下命令:\n');流(“1。cd(“% s”)\ n ', unzipFolderLocation);流(“2。系统(“% s”)\ n”runCommand);结束

附录- Helper函数

配置编码器创建可执行文件。在邮政编码处使用packNGo%生成阶段。函数codegenArgs = createCodegenArgs(folderForMainC)创建代码生成所需的参数。对于独立可执行文件,需要一个主C函数。c的为本例创建的%与文件的内容兼容% visionFaceTrackingKLTpackNGo_kernel.mmainCFile = fullfile(folderForMainC,“c”);用空格处理路径如果包含(mainCFile' 'mainCFile = [“””mainCFile“””];结束CFG = code .config(exe”);cfg。PostCodeGenCommand =“packNGo (buildInfo,“packType”,“分层”);“;cfg。CustomSource = mainCFile;cfg。CustomInclude = folderForMainC;cfg。EnableOpenMP = false;codegenArgs = {“配置”cfg};结束创建一个文件夹并将packNGo内容解压缩到其中。函数unzipFolderLocation = unzipppackagecontents (zipFileLocation)解压缩打包的zip文件。unzipFolderLocationName =“unzipPackNGo”;mkdir (unzipFolderLocationName);获取packNGo生成的zip文件的名称。zipFile = dir(‘* . zip”);断言(元素个数(zipFile) = = 1);解压缩(zipFile.name unzipFolderLocationName);解压缩在分层packNGo中创建的内部zip文件。zipFileInternal = dir(fullfile(unzipFolderLocationName)‘* . zip”));断言(元素个数(zipFileInternal) = = 3);i = 1:元素个数(zipFileInternal)解压缩(fullfile (unzipFolderLocationName, zipFileInternal (i) . name),...unzipFolderLocationName);结束unzipFolderLocation = fullfile(zipFileLocation,unzipFolderLocationName);结束从模板创建平台依赖的makefile。使用% buildInfo获取有关工具链的信息。函数makefileName = createMakeFile(visiondemo_dir, unzipFolderLocation, fname)从buildInfo创建Makefile。Binfo = load(fullfile(pwd,“codegen”exe”、帧,“buildInfo.mat”));lastDir = cd(unzipFolderLocation);dirCleanup = onCleanup(@()cd(lastDir));获取包含工具箱/视觉子目录的根目录matlabDirName = getRootDirName(unzipFolderLocation);% Get定义Horzcat_with_space = @(cellval)' % s ', cellval {:});defs = horzcat_with_space(getdefinitions (binfo.buildInfo));获取源文件列表如果ispc [~, cFiles] = system(['dir /s/b '‘* . c”]);[~, cppFiles] = system(['dir /s/b '‘* . cpp‘]);其他的[~, cFiles] = system(['find ./ '“- name”“* . c”]);[~, cppFiles] = system(['find ./ '“- name”“* . cpp”]);结束cIndx = strfind(cFiles,“c”);cppIndx = strfind(cppFiles,. cpp的);srcFilesC = [];srcFilesCPP = [];i = 1:长度(cIndx)如果i == 1 startIdx = 1;endIdx = cIndx(i);其他的startIdx = cIndx(i-1)+1;endIdx = cIndx(i);结束[~, b, ~] = fileparts(cFiles(startIdx:endIdx));srcFilesC = [srcFilesC .' 'b“c”];% #好< AGROW >结束i = 1:length(cppIndx)如果i == 1 startIdx = 1;endIdx = cppIndx(i);其他的startIdx = cppIndx(i-1)+1;endIdx = cppIndx(i);结束[~, b, ~] = fileparts(cppFiles(startIdx:endIdx));srcFilesCPP = [srcFilesCPP .' 'b. cpp的];% #好< AGROW >结束srcFiles = [srcFilesC .' 'srcFilesCPP];获取平台相关的名称如果isunix% MAC和Linuxtmf =“TemplateMakefilePackNGo_unix”如果ismac archDir =“maci64”;dllExt =“dylib”其他的archDir =“glnxa64”;dllExt =“所以”结束其他的tmf =“TemplateMakefilePackNGo_win”;archDir =“win64”;dllExt =“dll”结束现在我们有了定义,让我们创建一个平台相关的makefile%从模板。Fid = fopen(fullfile(visiondemo_dir,tmf));Filecontent = char(fread(fid)');文件关闭(fid);Newfilecontent = regexprep(文件内容,...“PASTE_ARCH”“PASTE_EXT”“PASTE_DEFINES”“PASTE_SRCFILES”“PASTE_MATLAB”},...{archDir, dllExt, defs, srcFiles, matlabDirName});makefileName =“Makefile”;mk_name = fullfile(unzipFolderLocation,makefileName);如果isunix如果(ismac) [status,sysHeaderPath] = system(“xcode-select -print-path”);断言(状态= = 0,(“无法获取系统的路径”...使用" xcode-select -print-path "的头文件]);[status,sdkPaths] = system(xrun -sdk macosx——show-sdk-path);断言(状态= = 0,“无法找到MacOSX sdk”);可能有多个SDKsdkPathCell = strsplit(sdkPaths,' \ n ');idx = 1:数字(sdkPathCell)如果~ isempty (sdkPathCell {idx})选择第一个不是空的。sdkPath = sdkPathCell{idx};流(在%s\n中选择SDK, sdkPath);打破结束结束断言(~ isempty (sdkPath),...sprintf (' %s中没有可用的sdk。请检查系统环境sysHeaderPath));ccCMD = [“xrun clang -isysroot”deblank(sdkPath)];cppCMD = [“xrun clang++ -isysroot”deblank(sdkPath)];其他的ccCMD =“海合会”;cppCMD =“g++”结束Newfilecontent = regexp (Newfilecontent,“PASTE_CC”, ccCMD);Newfilecontent = regexp (Newfilecontent,“PASTE_CPP”, cppCMD);结束Fid = fopen(mk_name,“w +”);流(fid检测器,' % s ', newfilecontent);文件关闭(fid);结束创建构建可执行文件和所需的平台特定命令%来运行它。函数[buildCommand, runCommand] = createBuildAndRunCommands(...packageLocation、unzipFolderLocation makefileName文件名)创建生成并运行命令。如果ismac buildCommand = [' xrun make -f 'makefileName];runCommand = [“。/”文件名“””文件名“””];elseifisunix buildCommand = [' make -f 'makefileName];runCommand = [“。/”文件名“””文件名“””];其他的在PC上,我们使用生成的BAT文件(应该有2个)来帮助构建生成的代码。这些文件被复制到% unzipFolderLocation,我们可以使用它们来构建。batFilename = [fileName .“_rtw.bat”];batFilelocation = fullfile(packageLocation,“codegen”...filesep,exe”filesep,文件名);batFileDestination = unzipFolderLocation;%对于MSVC,也复制'setup_msvc.bat'fid = fopen(fullfile(batFilelocation, batFilename));batFileContent = fread(fid,“*字符”);文件关闭(fid);如果~ isempty(正则表达式(convertCharsToStrings (batFileContent),“setup_msvc.bat”“一次”)) setup_msvc_batFile = fullfile(batFilelocation,“setup_msvc.bat”);拷贝文件(setup_msvc_batFile batFileDestination);结束拷贝到packNGo输出目录。拷贝文件(fullfile (batFilelocation batFilename) batFileDestination);我们创建的Makefile被命名为“Makefile”,而Batch% file指_rtw.mk。因此,我们重命名文件。newMakefileName = [fileName .“_rtw.mk”];oldMakefilename = makefileName;拷贝文件(fullfile (batFileDestination oldMakefilename),...fullfile (batFileDestination newMakefileName));buildCommand = batFilename;runCommand =[文件名。. exe”“””文件名“””];结束结束使用Build命令构建可执行文件。函数buildExecutable (unzipFolderLocation buildCommand)调用系统命令构建可执行文件。lastDir = cd(unzipFolderLocation);dirCleanup = onCleanup(@()cd(lastDir));[hadError, sysResults] = system(buildCommand);如果hadError错误(sysResults);结束结束获取包含工具箱/视觉子目录的根目录函数matlabDirName = getRootDirName(unzipFolderName) dirLists = dir(unzipFolderName);dirLists = dirLists(~ismember({dirLists.name},{“。”“. .”}));matlabDirName =ij=1:长度(dirLists) thisDirName = dirLists(ij).name;如果(isfolder (thisDirName))%子目录将包含toolbox/vision[subDir1, hasSubDir1] = hasSubdirectory(thisDirName,“工具箱”);如果hasSubDir1 [~, hasSubDir2] = hasSubdirectory(subDir1,“愿景”);如果hasSubDir2 matlabDirName = thisDirName;打破结束结束结束结束结束查找包含指定子目录的目录函数[subDir, hasSubDir] = hasSubdirectory(dirName, subDirName) dirLists = dir(dirName);dirLists = dirLists(~ismember({dirLists.name},{“。”“. .”}));子目录=;hasSubDir = false;ij=1:长度(dirLists) thisDirName = dirLists(ij).name;thisDir = fullfile(dirName,thisDirName);如果(isfolder(thisDir) && strcmp(thisDirName, subDirName)) hasSubDir = true;subDir = thisDir;打破结束结束结束
结束