如何使用QT框架进行海康机器视觉算子SDK二次开发

目录

1.使用QT进行算子SDK二次开发需要了解那些知识?

1.1 了解SDK的安装目录下各个文件的作用。

1.1.1 头文件和静态库

1.1.2 C#需要引用的库

1.1.3 运行时依赖库

1.1.4 帮助文件

1.1.5 环境检测等实用工具

1.2 具备基本的C++编程基础知识

1.3 了解算子SDK在底层做了哪些工作?

1.3.1 算子SDK 简化了算子的初始化流程

1.3.2 算子SDK简化了参数设置和参数获取

1.3.3 算子SDK以面向对象的方式封装了算子工具

2.算子SDK二次开发QT开发环境配置

2.1 使用QtCreator作为集成开发环境

2.2 使用VisualStudio作为集成开发环境

3.典型的算子工具调用流程

4.如何渲染算子工具的运行结果

5.在VisualStudio环境中如何编辑渲染控件的信号和槽


1.使用QT进行算子SDK二次开发需要了解那些知识?

1.1 了解SDK的安装目录下各个文件的作用。

  1. 用户在安装完Vision Master软件之后,默认会在C盘Program Files(x86)目录下安装算子开发包,典型的路径是这样的:

    C:\Program Files (x86)\MVDAlgorithmSDK

    在此目录下,应该会看到以下文件夹

如何使用QT框架进行海康机器视觉算子SDK二次开发_第1张图片

         

下面分别讲一下图中各个文件夹的作用。

1.1.1 头文件和静态库

使用C++语言进行算子SDK二次开发,最为常见的方式是使用静态库.lib加头文件.h的方式,因此Includes和Libraries这两个文件夹是我们所关心的。后面在开发环境配置中会重点介绍着两个文件夹如何引用。

1.1.2 C#需要引用的库

其中ReferencedAssemblies文件夹中用户也可以发现大量的DLL,这些DLL是使用C#语言进行算子二次开发才需要用到的,对于C++开发者来说不需要关心,所以不必关注 。

1.1.3 运行时依赖库

Runtime文件夹非常重要,这是使用算子SDK开发的应用程序运行时需要依赖的动态库,缺少它您开发的应用程序将无法运行,如果您想要在一台没有安装算子SDK软件包的电脑上运行您的二次开发程序,您可以将Runtime文件下的x64文件夹(如果是32位系统,就是win32文件夹)下的所有文件复制到你开发的exe所在目录即可。对于在一台已经安装了算子SDK开发包的电脑上运行您开发的视觉应用程序,则完全不必进行前面所说的操作,因为Runtime的路径已经写到环境变量中,程序运行时依赖的动态库会首先从环境变量中查找。

1.1.4 帮助文件

  Documents文件夹存放的时开发需要查询的开发的帮助文档,这个文档对于视觉应用开发者来说是非常重要的,算子类库的用法和各种内置数据类型可以通过查询文档知道。

Samples文件夹存放的是二次开发示例程序,如果您需要快速入门,可以直接跳到这个文件夹内查看相关的示例程序。

1.1.5 环境检测等实用工具

MVDTools文件夹存放是环境的检测工具之类的应用程序,视觉应用的二次开发不必了解这个。

1.2 具备基本的C++编程基础知识

首先,具备基础的C++编程知识,算子SDK开发需要掌握的C++知识点并不多,并不需要对C++各种知识面面俱到的了解。这里对其中涉及到的一些基础知识点做一些简单介绍,以便在二次开发过程中能很好的理解算子SDK的用法。

在算子SDK中,开发者会经常遇到I开头的类,例如IMvdImage, IMvdShape, IHPFeaturePatMatchTool , 这个IInterface的首字母,所以IMvdImage, IMvdShape等都是抽象类,是不可以直接实例化的,所以类似下面这样的语句是无意义的。

IMvdImage image

你也不可以像下面这样写,编译通不过的:

IMvdImage *pImage = new IMvdImage();

以IMvdImage这个图像类举例来说,正确的用法是这样的:

//读取D盘下的图像文件testImage.bmp
IMvdImage *pImage;
CreateImageInstance(&pImage);
pImage.InitImage(“D:\\testImage.bmp”,MVD_PIXEL_MONO_08);

在算子SDK中绝大多数类都是抽象类,都不能直接实例化,需要显式的调用CreateXXXInstance(XXX指代某个具体类,如Image类),然后才能对其进行操作,否则就会出现空引用,从而引发程序异常。

1.3 了解算子SDK在底层做了哪些工作?

1.3.1 算子SDK 简化了算子的初始化流程

算子SDK的二次开发简化了算子的初始化工作。在算子初始化过程中,需要对算子进行加密校验和解密,然后根据算子的能力集进行内存分配,除此之外,还需要对常用的运行参数设置初始的默认值,这些工作对于视觉应用的开发者来说较为繁琐和重复,因此算子SDK对这些流程都做了封装,开发者只需要一行代码就可以实现算子的初始,大大降低了开发者调用底层机器视觉算法的难度和负担。

1.3.2 算子SDK简化了参数设置和参数获取

算子SDK的二次开发简化了算子的参数设置,算子的运行参数在底层实际上是对应不同的结构体,在开发者不了解这些运行参数的数据类型和结构体的情况下,想要直接设置底层算子的运行参数难度就很大。但算子SDK对这参数设置这部分也做了很好的封装,用户只需要调用算子工具的SetParam函数接口,就可以在不了解底层算子运行参数结构体的情况下,也能将参数设置进去。SetParam函数提供了两个参数,一个参数是paramName, 一个参数是paramValue,开发者只需要查阅帮助文件,找到对应工具的参数表格,就可以设置参数。例如:设置快速模板匹配工具的最小匹配得分:

FastFeatureMatchTool1.SetParam(“MinScore”,”0.65”);

同样,开发者通过GetParam接口也能很方便的获取算子工具的当前参数值。

1.3.3 算子SDK以面向对象的方式封装了算子工具

有过Halcon视觉开发经验的开发者都知道,底层算子的调用灵活性很高,但是完全是面向过程的,不能很好的做到代码的重用,用户需要自己使用C++设计模式去构建自己的算子类库,而我们的算子SDK就是封装好的算子类库,算子实例化之后,通过暴露的接口API设置其属性,调用其方法就能控制算子工具,而不需要程序自己去管理算子工具的内部状态,视觉应用的开发者只需要将更多的精力放在业务逻辑层,而不必关系算子内部是如何工作的。

使用Qt框架开发桌面应用程序,开发者通常有两种选择,一种是在Qt官方提供的集成开发环境QtCreator中进行开发,优势是配置引用相对简单,通过一个pro文件,qmake工具会自动生成makefile, 另外,QtCreator的代码实时纠错提醒以及高度集成的帮助文件系统,开发者遇到不了解的API只需要按下F1就能自动导航到帮助文档对应的条目,这个是很多开发者喜欢QtCreator的原因,但是QtCreator的调试工具做得确实不如VisualStudio, 调试时不如VisualStudio方便,VisualStudio可以很方便的查看但变量的值,而在QtCreator中,对于用户自定义的数据类型,往往只能看到这个变量的指针,而不能查看到具体的变量值。因此有一部分开发者选择VisualStudio作为集成开发环境,下面分别介绍这两种环境下如何配置算子SDK的二次开发。

2.算子SDK二次开发QT开发环境配置

2.1 使用QtCreator作为集成开发环境

创建Qt工程后,在pro文件中,需要添加一些配置,pro文件的典型写法如下截图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第2张图片

如图所示,在pro文件的第1行,QT += core gui axcontainer 表示我们需要用到头文件,特别的axcontainer ,这个是算子SDK开发需要用到ActiveX控件,所以必须要添加axcontianer.

在pro文件的第22行,必须在工程的根目录下放上mvrenderactivexlib.cpp文件,pro文件的第25行,必须在工程的根目录下放上mvrenderactivexlib.h头文件。

在pro文件的第29行,定义了一个宏 MVD_INSTALL_DIR, 将算子包的安装目录指定当前工作目录的往上4级,其实就是C:/Program Files (x86)/MVDAlogrithmSDK 这个路径,由于pro文件中配置的路径不允许存在空格或者中文字符,所以用$quote( )包含起来。

在pro的第31行,指定工程引用到的头文件。这个时候我们前面定义的MVD_INSTALL_DIR就起到作用了,可以缩短头文件路径的写法。

接着我们还需要指定静态库的路径和依赖的动态库路径,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第3张图片

在pro文件的第43行,指定win64工程需要链接的动态库,写法是:

         LIBS += -L$$静态库路径 –l静态库名称

如图所示,MVDShapeCpp.lib和MVDImageCpp.lib 是必须用到的库,无论你用到什么算法工具,这个都是必不可少的,而MVDAlmightyPatMatchCpp.lib, MVDPreproMaskCpp.lib, MVDCircleFindCpp.lib 则是根据工程是否用到来决定是否添加,没有到相关的算子工具,则无需添加。

在pro文件的第52行,指定的是win32工程需要链接的静态库。

至此,pro文件就配置好了,开发者可以参照这个pro文件的写法来配置自己的工程,写法是基本一致的,只需要修改一下MVD_INSTALL_DIR这个宏指代的MVDAlgorithmSDK的安装路径就好了,然后再根据自己的需求,添加需要用到静态库(修改上面pro文件的44-47行,54-56行的内容即可)。

配置完pro文件,接着是添加用到的渲染控件,打开Qt Designer, 在窗口设计器中,把ActiveX控件的容器QAxWidget 拖到窗口中,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第4张图片

                                                             添加QAxWidget容器到窗体中

添加了ActiveX控件的容器后,我们就需要添加具体的ActiveX控件了,在窗体设计器中,对着拖进去的QAxWidget这个容器右键,选择需要加Activ控件,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第5张图片 如何使用QT框架进行海康机器视觉算子SDK二次开发_第6张图片


在弹出右键菜单中选择“设置控件”,然后在弹出的对话框中,输入Mv,会过滤掉很多不需要选择的控件,选择MvRenderActivex Control。

好了,到了这一步,基本上QT的配置就完成,还需要在工程的头文件中添加一些常用的头文件,例如,在mainwindow.h头文件中添加算子SDK二次开发常用的头文件。如下:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第7张图片                                                                                    添加算子SDK常用头文件

2.2 使用VisualStudio作为集成开发环境

我们以VisualStudio 2017为例,在VS中开发Qt应用程序,就不需要什么pro文件,只需要在工程设置中设置头文件路径和静态库路径。
首先设置附加头文件目录,在VS菜单栏中找到“项目”->“xxx项目属性”(这里xxx指代用户的项目名称)在弹出的对话框中设置附加头文件目录,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第8张图片

                                                                   设置附加包含目录

接着编辑附加包含目录,这些附加的包含目录是必不可少的,必须添加,否则程序编译会报错,分别是

$(QTDIR)\include\ActiveQt;

$(MVDALGO_DEV_ENV)\Includes\Algorithm; $(MVDALGO_DEV_ENV)\Includes\MvRenderOcx;

$(MVDALGO_DEV_ENV)\Includes\VisionDesiner;

添加ActiveQt目录是因为需要用到AcitveX容器,Algorithm, MvRenderOcx, VisionDesigner这几个头文件目录包含了渲染控件,以及所有算子需要用到的 头文件,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第9张图片

                                                                       编辑附加头文件路径

设置完了附加头文件路径,接着就是设置附加静态库路径和链接时需要链接的静态库名称,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第10张图片

                                                                    配置附加静态库路径

编辑附加库目录,如下图所示:

 如何使用QT框架进行海康机器视觉算子SDK二次开发_第11张图片

                                                               编辑附加库目录 

 切换到链接器的“输入”,设置链接的静态库名称,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第12张图片

                                                               编辑需要链接的静态库名称 

链接的静态库Qt5AxBased.lib,Qt5AxContainerd.lib 是必不可少的(注意这里库名称后面带有d,表明工程配置是Debug生成模式,如果用户工程配置的是Release模式,则不需要带d),因为需要用到ActiveX容器。MVDShapeCpp.lib, MVDImageCpp.lib 也是必不可少的。而MVDCircleFindCpp.lib则需要根据开发者是否用到做取舍,如果没用到则不必添加,如果用到其他的算子工具,必须在这里添加其他算子工具的静态库名称。

3.典型的算子工具调用流程

算子工具的典型调用流程如下:

我们以调用圆查找算子工具为例(例子只是为了解释说明调用流程,不具有实际意义),典型的代码如下:

//创建一个矩形框作为圆查找ROI
IMvdRectangleF *pRect;
CreateRectangleInstance(&pRect,currentImage->GetWidth()/2,currentImage->GetHeight()/2,100,100);
//创建一个圆查找工具实例
ICircleFindTool *pCircleFindTool;
CreateCircleFindToolInstance(&pCircleFindTool);
//设置输入图像
pCircleFindTool->SetInputImage(currentImage);
//设置圆查找ROI
pCircleFindTool->SetROI(pRect);
//运行圆查找工具
pCircleFindTool->Run();
//获取圆查找结果
ICircleFindResult *pResult = pCircleFindTool->GetResult();
if(pResult!=nullptr)
{
      MVD_POINT_F cent = pResult->GetCircleCenter();
      qDebug()<<"CentX="<

4.如何渲染算子工具的运行结果

算子工具运行完成后,我们可以获取其结果,将结果组装成各种IMvdShape,然后将Shape添加到控件的Shape列表中。添加后渲染控件就会自动渲染图形结果了。我们还是用代码来说明问题。

首先,编写一个函数,用来显示图像和渲染Shape,代码如下:

/**
 * @brief 在控件上显示图像
 * @param pImage 输入图像
 */
void MainWindow::ShowImage(IMvdImage *pImage)
{
    if(pImage!=nullptr)
    {
        long long nInImgPtr = (long long)(currentImage);
        QVariant vInputImg(nInImgPtr);      ui->axWidgetRender->dynamicCall("MV_LoadImageFromObject(const QVariant& varImageObj)", vInputImg);
        ui->axWidgetRender->dynamicCall("MV_Display()");
        pPreproMaskTool->SetInputImage(currentImage);
    }
}

/**
 * @brief 添加图形源
 * @param pShape 输入图形
 */
void MainWindow::AddShape(IMvdShape *pShape)
{
    QVariant qVarHandle(reinterpret_cast(pShape));
    MVD_SHAPE_HANDLE handle = 0;
    MVD_SHAPE_HANDLE* pHandle = &handle;
    QVariant pQVarHandle((long long)(pHandle));
    ui->axWidgetRender->dynamicCall("MV_AddShapeEx(const QVariant&, const QVariant&)", qVarHandle, pQVarHandle);
}

为了简化清除图形和显示图形的写法,我们再定义两个宏,一个用来清除控件上的所有图形,一个用来刷新控件的显示。

#define CLEAR_SHAPES ui->axWidgetRender->dynamicCall("MV_ClearShapes()")
#define MVD_DISPLAY ui->axWidgetRender->dynamicCall("MV_Display()")

这样我们只需要在需要清除图形的地方添加CLEAR_SHAPES; 需要刷新控件显示的地方添加MVD_DISPLAY。

好了,渲染算子的运行结果功能就完备了,再举一个完整的简单例子来说明渲染控件的用法。

举例:调用圆查找功能算子,并渲染圆查找结果,代码如下:

try 
{
        //清除图形
        CLEAR_SHAPES;
        //显示图像
        ShowImage(currentImage);
        //实例化一个扇环区域,扇环中心100,100,内径40,外径80,起始角//度0,终止角度360
        IMvdAnnularSectorF *pAnnualarsector;       CreateAnnularSectorInstance(&pAnnualarsector,MVD_POINT_F{100,100},40,80,0,360);  
        //实例化圆查找工具
        ICircleFindTool *pcirFindTool;
        CreateCircleFindToolInstance(&pcirFindTool);
        //设置输入图像
        pcirFindTool->SetInputImage(currentImage);
        //设置ROI
        pcirFindTool->SetROI(pAnnualarsector);
        //算子运行
        pcirFindTool->Run();
	    //获取结果
        ICircleFindResult *pCirleFindResult = pcirFindTool->GetResult();
        if(pCirleFindResult!=nullptr)
        {
         //在控件上渲染查找到的圆
        IMvdCircleF *pCircle;
        CreateCircleInstance(&pCircle,MVD_POINT_F{0,0},10);
        pCircle->SetCenter(pCirleFindResult->GetCircleCenter();    
        pCircle->SetRadius(pCirleFindResult->GetCircleRadius();
        pCircle->SetBorderColor(MVD_COLOR{0x7f,0xff,0,0});
        AddShape(pCircle);
        }
        MVD_DISPLAY;        
} 
catch (IMVDException &ex) 
{
       QString errorMessage = QString::fromLocal8Bit("执行算法模块发生异常,返回错误码")+QString::number(ex.GetErrorCode(),16);
       QMessageBox::warning(this,"Warning",errorMessage);
}

5.在VisualStudio环境中如何编辑渲染控件的信号和槽

不同于在QtCreator中,在VS中打开QtDesigner,编辑渲染控件时,渲染控件的右键菜单中并不能找到“转到槽”这一项。这一点确实不如在QtCreator中打开QtDesigner来的方便。但我们还是有办法来达到添加信号和槽的目的。

方法1:手动添加connect函数,例如连接渲染控件图形发生改变信号到槽函数

connect(ui.axWidget,
SIGNAL(MV_SHAPECHANGED(int,int,QVariant&)),
this,
SLOT(OnShapechanged(int,int,QVariant&)));

方法2:按照命名规范添加槽函数

Qt会自动给每一个控件将的信号和槽连接起来,原因是在窗体的构造函数中调用了SetupUi函数,而在SetupUi函数的最后一行有一条语句:

QMetaObject::connectSlotsByName(MainWindow)

如果我们写的槽函数符合on_对象名_信号名,就会自动将信号和槽连接上,例如渲染控件的名称是axWidget,我们在头文件中声明一个槽函数:

on_axWidget_MV_SHAPECHANGED(int eventType,int shapeType,QVariant& shapeHandle)

然后在CPP文件中实现这个函数即可。

举例:获取用户在渲染控件上绘制的ROI对象。

在QtGuiApplication.h文件中声明一个槽函数

void OnShapechanged(int eventType,int shapeType,QVariant& var);

然后声明一个IMvdRectangleF* roi 用来存放ROI数据

如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第13张图片

接着在QtGuiApplication.文件中实现上面添加的槽函数

在窗体的构造函数中,连接信号和槽,并创建ROI的实例,如下图所示:

如何使用QT框架进行海康机器视觉算子SDK二次开发_第14张图片

接着我们要实现槽函数onShapeChanged(int,int,QVariant&)

如何使用QT框架进行海康机器视觉算子SDK二次开发_第15张图片

这个函数表达的意思是:只接受当前绘制矩形框作为ROI,用户右键添加的其他图形无视。

你可能感兴趣的:(机器视觉,大数据)