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文件)的主要内容,如果未能解决你的问题,请参考以下文章

halcon学习和实践(工业视觉套路)

halcon学习和实践(从halcon转化为opencv)

MFC调用halcon生成的cpp内容

halcon学习和实践(hdev脚本学习技巧)

halcon导出的代码为啥没有runhalcon

halcon学习和实践(ocr识别)