halcon学习和实践(导出cpp文件)
Posted 嵌入式-老费
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了halcon学习和实践(导出cpp文件)相关的知识,希望对你有一定的参考价值。
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
halcon除了编写脚本文件之外,还可以导出cpp文件。因为,最终的功能总是要给客户使用的,相关的软件也要部署到客户的机器上的,总不能把hdevelop软件安装在客户的电脑上吧。这也不是很合适。
还是以上次的脚本为例,看一下如何导出cpp代码。导出cpp的方法也很简单,选择文件-》导出即可,
格式选择cpp,然后单击导出就可以了,
目前来说,总共支持4种格式的导出方式,分别是c文件、cpp文件、vb文件、c#文件。因为c#编写上位机比较方便,所以需要的同学可以导出为c#文件。当然对c和cpp比较熟悉的朋友,可以导出为对应的文件,界面部分用mfc或者qt编写效果也是一样的。
我们可以阅读一下这个生成的cpp文件,源代码如下所示,
///
// File generated by HDevelop for HALCON/C++ Version 13.0.2
///
#ifndef __APPLE__
# include "HalconCpp.h"
# include "HDevThread.h"
# if defined(__linux__) && !defined(__arm__) && !defined(NO_EXPORT_APP_MAIN)
# include <X11/Xlib.h>
# endif
#else
# ifndef HC_LARGE_IMAGES
# include <HALCONCpp/HalconCpp.h>
# include <HALCONCpp/HDevThread.h>
# else
# include <HALCONCppxl/HalconCpp.h>
# include <HALCONCppxl/HDevThread.h>
# endif
# include <stdio.h>
# include <HALCON/HpThread.h>
# include <CoreFoundation/CFRunLoop.h>
#endif
using namespace HalconCpp;
#ifndef NO_EXPORT_MAIN
// Main procedure
void action()
// Local iconic variables
HObject ho_Audi2, ho_ImageFilled, ho_Region;
HObject ho_ConnectedRegions, ho_SelectedRegions, ho_Letters;
ReadImage(&ho_Audi2, "audi2");
FillInterlace(ho_Audi2, &ho_ImageFilled, "odd");
Threshold(ho_ImageFilled, &ho_Region, 0, 90);
Connection(ho_Region, &ho_ConnectedRegions);
SelectShape(ho_ConnectedRegions, &ho_SelectedRegions, "width", "and", 30, 70);
SelectShape(ho_SelectedRegions, &ho_Letters, "height", "and", 60, 110);
if (HDevWindowStack::IsOpen())
ClearWindow(HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
SetColored(HDevWindowStack::GetActive(),12);
if (HDevWindowStack::IsOpen())
DispObj(ho_ImageFilled, HDevWindowStack::GetActive());
if (HDevWindowStack::IsOpen())
DispObj(ho_Letters, HDevWindowStack::GetActive());
#ifndef NO_EXPORT_APP_MAIN
#ifdef __APPLE__
// On OS X systems, we must have a CFRunLoop running on the main thread in
// order for the HALCON graphics operators to work correctly, and run the
// action function in a separate thread. A CFRunLoopTimer is used to make sure
// the action function is not called before the CFRunLoop is running.
// Note that starting with macOS 10.12, the run loop may be stopped when a
// window is closed, so we need to put the call to CFRunLoopRun() into a loop
// of its own.
HTuple gStartMutex;
H_pthread_t gActionThread;
HBOOL gTerminate = FALSE;
static void timer_callback(CFRunLoopTimerRef timer, void *info)
UnlockMutex(gStartMutex);
static Herror apple_action(void **parameters)
// Wait until the timer has fired to start processing.
LockMutex(gStartMutex);
UnlockMutex(gStartMutex);
try
action();
catch (HException &exception)
fprintf(stderr," Error #%u in %s: %s\\n", exception.ErrorCode(),
(const char *)exception.ProcName(),
(const char *)exception.ErrorMessage());
// Tell the main thread to terminate itself.
LockMutex(gStartMutex);
gTerminate = TRUE;
UnlockMutex(gStartMutex);
CFRunLoopStop(CFRunLoopGetMain());
return H_MSG_OK;
static int apple_main(int argc, char *argv[])
Herror error;
CFRunLoopTimerRef Timer;
CFRunLoopTimerContext TimerContext = 0, 0, 0, 0, 0 ;
CreateMutex("type","sleep",&gStartMutex);
LockMutex(gStartMutex);
error = HpThreadHandleAlloc(&gActionThread);
if (H_MSG_OK != error)
fprintf(stderr,"HpThreadHandleAlloc failed: %d\\n", error);
exit(1);
error = HpThreadCreate(gActionThread,0,apple_action);
if (H_MSG_OK != error)
fprintf(stderr,"HpThreadCreate failed: %d\\n", error);
exit(1);
Timer = CFRunLoopTimerCreate(kCFAllocatorDefault,
CFAbsoluteTimeGetCurrent(),0,0,0,
timer_callback,&TimerContext);
if (!Timer)
fprintf(stderr,"CFRunLoopTimerCreate failed\\n");
exit(1);
CFRunLoopAddTimer(CFRunLoopGetCurrent(),Timer,kCFRunLoopCommonModes);
for (;;)
HBOOL terminate;
CFRunLoopRun();
LockMutex(gStartMutex);
terminate = gTerminate;
UnlockMutex(gStartMutex);
if (terminate)
break;
CFRunLoopRemoveTimer(CFRunLoopGetCurrent(),Timer,kCFRunLoopCommonModes);
CFRelease(Timer);
error = HpThreadHandleFree(gActionThread);
if (H_MSG_OK != error)
fprintf(stderr,"HpThreadHandleFree failed: %d\\n", error);
exit(1);
ClearMutex(gStartMutex);
return 0;
#endif
int main(int argc, char *argv[])
int ret = 0;
try
#if defined(_WIN32)
SetSystem("use_window_thread", "true");
#elif defined(__linux__) && !defined(__arm__)
XInitThreads();
#endif
// Default settings used in HDevelop (can be omitted)
SetSystem("width", 512);
SetSystem("height", 512);
#ifndef __APPLE__
action();
#else
ret = apple_main(argc,argv);
#endif
catch (HException &exception)
fprintf(stderr," Error #%u in %s: %s\\n", exception.ErrorCode(),
(const char *)exception.ProcName(),
(const char *)exception.ErrorMessage());
ret = 1;
return ret;
#endif
#endif
整个代码的长度大约200行,不算很长,在可以接受的范围内。通过观察发现,主要的图像操作代码都被翻译到了action这个函数里面。
代码从main函数开始。分成两种情况,一种是没有定义__APPLE__宏,也就是mac电脑的宏;一种是定义了__APPLE__宏。如果没有定义这个宏,那么使用就比较简单,main函数直接调用action函数即可。
如果定义了__APPLE__宏,那么流程稍微复杂一点,首先它会调用apple_main函数,在apple_main函数里面会创建一个入口是apple_action函数的线程。这个线程没有立即开始执行,直到apple_main创建一个Timer的定时器,并且timer_callback回调函数中释放gStartMutex之后,apple_action才开始执行。在apple_action中会继续调用action函数,调用结束后,会设置g_Terminate为true,这样app_main函数就可以跳出循环等待,整个操作也就这样完成了。
一般编译c、cpp代码都需要include目录、lib目录和dll目录,这部分和平台有关,相差不大,剩下来的工作就是把这段代码集成到自己的上位机软件中即可。
1)include目录位置
C:\\Program Files\\MVTec\\HALCON-13.0\\include
2)lib目录位置
C:\\Program Files\\MVTec\\HALCON-13.0\\lib\\x64-win64
3)dll位置
C:\\Program Files\\MVTec\\HALCON-13.0\\bin\\x64-win64
以上是关于halcon学习和实践(导出cpp文件)的主要内容,如果未能解决你的问题,请参考以下文章