机器视觉Qt联合Halcon编程之显示多图片

Posted 沧海一笑-dj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器视觉Qt联合Halcon编程之显示多图片相关的知识,希望对你有一定的参考价值。

00. 目录

01. 概述

QT与Halcon联合编程。将Halcon中代码集成到Qt程序中。

开发环境

Qt:Qt5.15.2

Halcon: Halcon 19.11

02. 编写Halcon程序

Halcon程序示例

* 从本地磁盘读取一张图片
read_image (Carb, 'E:/CarB.jpg')

* 获取图片大小
get_image_size (Carb, Width, Height)


* 关闭当前窗口
dev_close_window ()


* 打开新窗口
dev_open_window (0, 0, Width / 2, Height / 2, 'black', WindowHandle)


* 显示图片
dev_display (Carb)

Halcon中执行结果

03. Halcon程序导出C++文件

将上述Halcon程序导出为C++源程序

导出内容如下:

///
// File generated by HDevelop for HALCON/C++ Version 19.11.0.0
// Non-ASCII strings in this file are encoded in local-8-bit encoding (cp936).
// Ensure that the interface encoding is set to locale encoding by calling
// SetHcppInterfaceStringEncodingIsUtf8(false) at the beginning of the program.
// 
// Please note that non-ASCII characters in string constants are exported
// as octal codes in order to guarantee that the strings are correctly
// created on all systems, independent on any compiler settings.
// 
// Source files with different encoding should not be mixed in one project.
///



#ifndef __APPLE__
#  include "HalconCpp.h"
#  include "HDevThread.h"
#else
#  ifndef HC_LARGE_IMAGES
#    include <HALCONCpp/HalconCpp.h>
#    include <HALCONCpp/HDevThread.h>
#    include <HALCON/HpThread.h>
#  else
#    include <HALCONCppxl/HalconCpp.h>
#    include <HALCONCppxl/HDevThread.h>
#    include <HALCONxl/HpThread.h>
#  endif
#  include <stdio.h>
#  include <CoreFoundation/CFRunLoop.h>
#endif



using namespace HalconCpp;

// Procedure declarations 
// Local procedures 
void blobImage (HObject *ho_Image, HObject *ho_Region);

// Procedures 
// Local procedures 
void blobImage (HObject *ho_Image, HObject *ho_Region)
{

  ReadImage(&(*ho_Image), "E:/test.jpg.tif");

  Threshold((*ho_Image), &(*ho_Region), 128, 255);

  if (HDevWindowStack::IsOpen())
    DispObj((*ho_Image), HDevWindowStack::GetActive());

  if (HDevWindowStack::IsOpen())
    DispObj((*ho_Region), HDevWindowStack::GetActive());
  return;
}

#ifndef NO_EXPORT_MAIN
// Main procedure 
void action()
{

  // Local iconic variables
  HObject  ho_Carb;

  // Local control variables
  HTuple  hv_Width, hv_Height, hv_WindowHandle;

  //从本地磁盘读取一张图片
  ReadImage(&ho_Carb, "E:/CarB.jpg");

  //获取图片大小
  GetImageSize(ho_Carb, &hv_Width, &hv_Height);


  //关闭当前窗口
  if (HDevWindowStack::IsOpen())
    CloseWindow(HDevWindowStack::Pop());


  //打开新窗口
  SetWindowAttr("background_color","black");
  OpenWindow(0,0,hv_Width/2,hv_Height/2,0,"visible","",&hv_WindowHandle);
  HDevWindowStack::Push(hv_WindowHandle);


  //显示图片
  if (HDevWindowStack::IsOpen())
    DispObj(ho_Carb, 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");
#endif

    // file was stored with local-8-bit encoding
    //   -> set the interface encoding accordingly
    SetHcppInterfaceStringEncodingIsUtf8(false);

    // 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



04. 创建Qt图形界面项目

4.1 简单的GUI设计如下

集成halcon编译需要用msvc,如果用minGW,会出错,等有时间在去研究minGW编译情形。

05. Qt集成Halcon程序

5.1 在pro项目配置文件中添加一下Halcon相关配置

# MacOS specific settings. Note that while dyld will search under
# /Library/Frameworks by default, the preprocessor/compiler/linker will not
# and need to be told explicitly.
macx {
  QMAKE_CXXFLAGS += -F/Library/Frameworks
  QMAKE_LFLAGS   += -F/Library/Frameworks
  LIBS           += -framework HALCONCpp
}
else {
  #defines
  win32:DEFINES += WIN32

  #includes
  INCLUDEPATH   += "$$(HALCONROOT)/include"
  INCLUDEPATH   += "$$(HALCONROOT)/include/halconcpp"

  #libs
  QMAKE_LIBDIR  += "$$(HALCONROOT)/lib/$$(HALCONARCH)"
  unix:LIBS     += -lhalconcpp -lhalcon -lXext -lX11 -ldl -lpthread
  win32:LIBS    += "$$(HALCONROOT)/lib/$$(HALCONARCH)/halconcpp.lib" \\
                   "$$(HALCONROOT)/lib/$$(HALCONARCH)/halcon.lib"
}

5.2 在mainwindow.h文件中添加Halcon相关头文件

#ifndef __APPLE__
#  include "HalconCpp.h"
#  include "HDevThread.h"
#else
#  ifndef HC_LARGE_IMAGES
#    include <HALCONCpp/HalconCpp.h>
#    include <HALCONCpp/HDevThread.h>
#    include <HALCON/HpThread.h>
#  else
#    include <HALCONCppxl/HalconCpp.h>
#    include <HALCONCppxl/HDevThread.h>
#    include <HALCONxl/HpThread.h>
#  endif
#  include <stdio.h>
#  include <CoreFoundation/CFRunLoop.h>
#endif

using namespace HalconCpp;

5.3 在MainWindow添加halcon相关的变量

源程序如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#ifndef __APPLE__
#  include "HalconCpp.h"
#  include "HDevThread.h"
#else
#  ifndef HC_LARGE_IMAGES
#    include <HALCONCpp/HalconCpp.h>
#    include <HALCONCpp/HDevThread.h>
#    include <HALCON/HpThread.h>
#  else
#    include <HALCONCppxl/HalconCpp.h>
#    include <HALCONCppxl/HDevThread.h>
#    include <HALCONxl/HpThread.h>
#  endif
#  include <stdio.h>
#  include <CoreFoundation/CFRunLoop.h>
#endif

using namespace HalconCpp;




QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_3_clicked();

private:
    Ui::MainWindow *ui;

    // Local iconic variables
    HObject  ho_Carb;

    // Local control variables
    HTuple  hv_Width, hv_Height, hv_WindowHandle;


};
#endif // MAINWINDOW_H

5.4 实现采集图像槽函数

//采集图像
void MainWindow::on_pushButton_clicked()
{

        QString fileName = QFileDialog::getOpenFileName(this,
                  tr("打开图片"), "E://", tr("Image Files (*.png *.jpg *.bmp)"));

        qDebug() << fileName;
        //从本地磁盘读取一张图片

        //QString转HTuple要通过String
        ReadImage(&ho_Carb, fileName.toStdString().c_str());

        //获取图片大小
        GetImageSize(ho_Carb, &hv_Width, &hv_Height);

}

友情提示

//QString转HTuple要通过String
ReadImage(&ho_Carb, fileName.toStdString().c_str());

5.5 实现显示图像槽函数

//显示图像
void MainWindow::on_pushButton_3_clicked()
{
    //关闭当前窗口
    if (HDevWindowStack::IsOpen())
        CloseWindow(HDevWindowStack::Pop());


    //打开新窗口
    SetWindowAttr("background_color","black");
    OpenWindow(0,0,hv_Width/2,hv_Height/2, (Hlong)ui->label->winId(),"visible","",&hv_WindowHandle);
    HDevWindowStack::Push(hv_WindowHandle);


    //显示图片
    if (HDevWindowStack::IsOpen())
        DispObj(ho_Carb, HDevWindowStack::GetActive());
}

友情提示

Qt中winId()和Halcon中窗口句柄转换

OpenWindow(0,0,hv_Width/2,hv_Height/2, (Hlong)ui->label->winId(),“visible”,"",&hv_WindowHandle);

5.6 编译程序

运行结果如下:

06. 附录

6.1 测试程序下载

下载:【机器视觉】Qt联合Halcon编程之显示多图片.rar

以上是关于机器视觉Qt联合Halcon编程之显示多图片的主要内容,如果未能解决你的问题,请参考以下文章

机器视觉Qt联合Halcon编程之显示图片

机器视觉Qt联合Halcon编程之显示图片

Halcon与C#联合编程:使用S7协议实现机器视觉上位机与西门子PLC联动

qt多次调用函数显示多张图片

机器视觉Qt集成Halcon开发环境详解

机器视觉Qt集成Halcon开发环境详解