1.C++项目引用HALCON依赖
1.1C++项目引用HALCON依赖
pro添加
# HALCON#include
INCLUDEPATH += $$(HALCONROOT)/includeINCLUDEPATH += $$(HALCONROOT)/include/halconcppINCLUDEPATH += $$(HALCONROOT)/include/hdevengine#libs
LIBS += -L$$(HALCONROOT)/lib/$$(HALCONARCH) -lhalcon -lhalconcpp -lhdevenginecp
1.2添加HALCON头文件、命名空间
设置路径
#include "HalconCpp.h" #include "HDevEngineCpp.h" using namespace HalconCpp; using namespace HDevEngineCpp; |
2.流程介绍
2.1引擎命名空间
主要用得到的类:HDevEngine、HDevProgram、HDevProgramCall、HDevProcedure、HDevProcedureCall、HDevOpMultiWindowImpl、HDevEngineException。
HDevEngine类是管理全局设置。如设置或获取全局变量的值、设置脚本路径、启动停止调试模式等。
HDevProgram类加载.hdev格式文件以及获取文件内部参数一般信息。
HDevProgramCall类执行.hdev文件格式脚本,并获取变量的值。
HDevProcedure类加载.hdvp格式外部函数以及内部函数。
HDevProcedureCall类执行.hdvp外部函数和内部函数。并且可以设置或获取外部函数、内部函数参数。
HDevOpMultiWindowImpl类主要是与显示结果相关,在脚本中执行的结果可以显示在C#中。
HDevEngineException类是引擎相关的异常类。
本文档以.hdvp为例子
2.1.1准备.hdvp函数
try *输入 Param1:=Param1 Param2:=Param2 Param3:=Param3 Param4:=Param4 if(Param1='查找模板OK' and Param2='测量成功' and Param3='测量成功' and Param4='测量成功') Result:=0 Result1:='OK' else Result:=1 Result1:='NG' endif catch (Exception) Result:=-1 ErrorString:=Exception endtry return () |
函数接口如下:5个输入,2个输出。同时添加参数文档说明(包含多种语言,需要设置需要的语言文档)。
2.1.2QT中调用该程序
全局变量
HDevEngine* MyEngine;//引擎
HDevProcedure *Program ;//函数
HDevProcedureCall* ProcCall;//函数回调
首先初始化引擎,需要设置语言和引擎文件的路径,路径设置不正确,找不到外部函数;同时可以获取该目录下的函数
MyEngine = new HDevEngine(); //设置文档语言,因为使用的中文需要设置,默认英文,语言不对应拿不到参数说明 MyEngine->SetEngineAttribute("docu_language","zh_CN"); QString hdevPath="C:/Users/DH/Desktop/"; QByteArray ba = hdevPath.toLatin1(); resource_path=ba.data(); MyEngine->AddProcedurePath(resource_path); HTuple procedurenames=MyEngine->GetProcedureNames(); QList<QString > nameList; int length= procedurenames.Length(); for (int var = 0; var < length; ++var) { QString name=procedurenames[var].S().ToUtf8(); nameList.append(name); } |
然后设置函数和函数回调指针,“test”为引擎文件名称,设置后会加载该引擎函数,后续可以使用回调执行。
try { Program = new HDevProcedure("test"); ProcCall = new HDevProcedureCall(*Program); }catch (HDevEngineException Ex) { ui->lineEdit_4->setText( "HDevEngine Exception"); return; } |
执行之前调用函数接口,可以查看函数的输入输出参数个数、名称、类型、以及参数说明等等。本例子参数都没htuple,图形参数使用SetInputIconicParamObject,具体接口查看"HDevEngineCpp.h"文件中HDevProcedureCall;值得注意的是输入输出都可以使用序号(从1开始)或者ParamName.
//输入个数 int num_input=Program->GetInputCtrlParamCount(); ui->textEdit->append("num_input :"+QString::number(num_input)); //输出个数 int num_output=Program->GetOutputCtrlParamCount(); ui->textEdit->append("num_output :"+QString::number(num_output)); //输入的参数名字 auto input_name= Program->GetInputCtrlParamNames(); ui->textEdit->append("input_name :"); ui->textEdit->append(input_name.ToString().Text()); //输出参数的名字 auto ouput_name=Program->GetOutputCtrlParamNames(); ui->textEdit->append("ouput_name :"); ui->textEdit->append(ouput_name.ToString().Text()); //引擎信息--没有使用到 auto QueryInfo= Program->QueryInfo(); ui->textEdit->append("QueryInfo :"); ui->textEdit->append(QueryInfo.ToString().Text()); //查询参数的信息,也就是关键字, auto QueryParamInfo= Program->QueryParamInfo(); ui->textEdit->append("QueryParamInfo :"); ui->textEdit->append(QueryParamInfo.ToString().Text()); //获取参数描述,其他字段如下 // ["assertion", "default_type", "default_value", "description", // "file_ext", "file_ext_descr", "mixed_type", "multichannel", // "multivalue", "sem_type", "stepmin", "steprec", "type_list", // "valuefunction", "value_list", "valuemax", "valuemin", "valuenumber", // "values"] ui->lineEdit_5->setText("description"); for(int k=1;k<=num_input;k++) { std::string str = ui->lineEdit_5->text().toStdString(); const char* slot=str.c_str(); auto abb=Program->GetInputCtrlParamName(k); auto a=Program->GetParamInfo(abb,slot); ui->textEdit->append(a.ToString().Text()); // auto bb=Program->GetInputCtrlParamInfo(k,slot); // ui->textEdit->append(bb.ToString().Text()); } QString a="查找模板OK"; QString b="测量成功"; HTuple Param1,Param2,Param3,Param4,Result,Result1,Exception,ErrorString,path; Param1=a.toStdString().data(); Param2=b.toStdString().data(); Param3=b.toStdString().data(); Param4=b.toStdString().data(); ProcCall->SetInputCtrlParamTuple(1,Param1); ProcCall->SetInputCtrlParamTuple(2,Param2); ProcCall->SetInputCtrlParamTuple(3,Param3); ProcCall->SetInputCtrlParamTuple(4,Param4); ProcCall->SetInputCtrlParamTuple(5,path); ProcCall->Execute();//执行函数 // auto out1 = ProcCall->GetOutputCtrlParamTuple("Result"); // auto out2 = ProcCall->GetOutputCtrlParamTuple("Result1"); // ui->textEdit->append(out1.ToString().Text()); // ui->textEdit->append(out2.ToString().Text()); for (int j=1;j<=num_output;j++) { HTuple out; ProcCall->GetOutputCtrlParamTuple(j,&out); ui->textEdit->append(out.ToString().Text()); } |
2.1.3重载
通过以上三步,引擎函数可以被调用;但是如果程序运行期间引擎进行更改,程序中不会更改;必须主动重新加载,有了这一步我们就不需要重复的启动关闭应用程序了。
分为两个步骤:SetProcedurePath会清空当前所有的路径;
然后AddProcedurePath重新添加路径
注意:如果文件改动更新的话需要使用
//获取程序名
HTuple procedurenames=MyEngine->GetProcedureNames();
//卸载程序
MyEngine->UnloadProcedure()
MyEngine->SetProcedurePath(""); QString hdevPath="C:/Users/DH/Desktop/"; QByteArray ba = hdevPath.toLatin1(); resource_path=ba.data(); MyEngine->AddProcedurePath(resource_path); |
2.2调用hdev文件
2.2.1设置文件路径以及读取内部函数
QString hdevPath = ui->lineEdit->text(); HDevProgram hDevProgram(hdevPath.toStdString().c_str()); if(!hDevProgram.IsLoaded()) { int a=1; } HTuple hv_UsedProcedureNames = hDevProgram.GetUsedProcedureNames(); QList<QString> lstUsedProcedureName; for(Hlong index = 0; index < hv_UsedProcedureNames.Length(); ++index) { lstUsedProcedureName.push_back(hv_UsedProcedureNames[index].S().Text()); ui->textEdit->append(hv_UsedProcedureNames[index].S().Text()); } ui->textEdit->append("加载完成"); |
2.2.2执行hdev内部函数以及获取内部函数的信息;执行以及函数信息获取和hdvp一样;
QString hdevPath = ui->lineEdit->text(); HDevEngineCpp::HDevEngine().SetEngineAttribute("docu_language", "zh_CN"); HDevProcedure* program = new HDevProcedure(hdevPath.toStdString().c_str(),"abcd"); ui->textEdit->append(" -----"); //输入个数 int num_input=program->GetInputCtrlParamCount(); ui->textEdit->append("输入个数 :"+QString::number(num_input)); //输出个数 int num_output=program->GetOutputCtrlParamCount(); ui->textEdit->append("输出个数 :"+QString::number(num_output)); //输入的参数名字 auto input_name= program->GetInputCtrlParamNames(); ui->textEdit->append("输入名字 :"); ui->textEdit->append(input_name.ToString().Text()); //输出参数的名字 auto ouput_name=program->GetOutputCtrlParamNames(); ui->textEdit->append("输出名字 :"); ui->textEdit->append(ouput_name.ToString().Text()); //查询参数的信息,也就是关键字, auto QueryParamInfo= program->QueryParamInfo(); ui->textEdit->append("QueryParamInfo :"); ui->textEdit->append(QueryParamInfo.ToString().Text()); HDevEngineCpp::HDevProcedureCall call = *program; call.Execute(); for (int j=1;j<=program->GetOutputCtrlParamCount();j++) { HTuple out; call.GetOutputCtrlParamTuple(j,&out); //out=m_pProcCall->GetOutputCtrlParamTuple("Result"); ui->textEdit->append(out.ToString().Text()); } |
注:如果hdev修改后需要重新加载,只需要重新设置HDevProgram(文件路径包含文件名)即可;
2.3C++掉库函数
2.3.1多个hdvp函数生成.hdpl库函数
首先建立空白库函数,点击“函数”---“管理函数”---“管理库函数”
新建的库函数目录如果不在外部函数目录,会提醒添加,建好后右上角选中新建的函数,然后右上角添加函数,即可选择hdev文件;点击选中的库右击保存库(所有的函数就会保存到一个文件中,方便迁移,迁移添加库函数即可使用)。
2.3.2QT调用库函数
同上述调用外部函数步骤一样,
注意:第二步的函数名称需要变更为库函数中所调用的函数名,并非库函数文件名,如下图的右侧
3.HALCON导出库工程
3.1主函数
如图3.1为示例主程序。
图 3.1 主函数
3.2函数封装
图3.2为封装的接口函数内容。
图 3.2 接口函数
3.3导出库工程
导出,选择文件--导出库工程
图 3.3 导出C++库工程
3.4C++项目引用HALCON依赖
pro添加
# HALCON #include INCLUDEPATH += $$(HALCONROOT)/include INCLUDEPATH += $$(HALCONROOT)/include/halconcpp INCLUDEPATH += $$(HALCONROOT)/include/hdevengine #libs LIBS += -L$$(HALCONROOT)/lib/$$(HALCONARCH) -lhalcon -lhalconcpp -lhdevenginecpp |
3.5导入HALCON库工程.h、.cpp文件
将生成的工程文件添加到C++项目(除了直接复制还可以使用cmake编译生成工程,生成lib使用)
图3.4添加文件
3.6添加引用调用函数
设置路径
const char* resource_path="D:/Desktop/库工程/blob/res_blob/"; SetResourcePath(resource_path); |
调用函数传入变量
QString Path="C:/Users/Public/Documents/MVTec/HALCON-18.11-Progress/examples/images/diedie/die_03.png"; HalconCpp::HTuple picPath=Path.toStdString().c_str(); HalconCpp::HObject Bond; HalconCpp::HObject FinalBalls; blob::ball(&Bond,&FinalBalls,picPath); |
4.调试
4.1开启调试以及设置端口
在程序中添加该代码
HDevEngine* MyEngine = new HDevEngine();
MyEngine->StartDebugServer();//默认端口57786
程序添加函数后,必须使用HDevProcedure指定函数名称后才可以调试,打开halcon—>执行—>附加到进程。
5.执行本地hdev文件
5.1设置本地文件
QString hdevPath="C:/Users/DH/Desktop/test.hdev"; QByteArray ba = hdevPath.toLatin1(); resource_path=ba.data(); m_pProgram = new HDevProgram(resource_path); m_pProgramCall = new HDevProgramCall(*m_pProgram); |
5.2执行以及取值
m_pProgramCall->Execute();
QString name="c";//变量名字
auto aa=name.toLatin1();
const char * var=aa.data();
auto a = m_pProgramCall->GetCtrlVarTuple(var);//使用该函数内部传要取的参数名字