插件:插件用于扩展应用程序的功能。一个插件就是一个简单的库(windows上的后缀是 *.dll)。可以在运行时加载和使用插件,以处理特定的任务。
参考书籍 《OpenCV3与Qt5计算机视觉应用开发第三章》
1 定义接口
接口用于实现应用程序和插件之间的对话,接口为c++头文件,通常接口包含期望在插件中出现的所有函数。
1.1 创建头文件
打开Qt Creator,依次选择 “File” - “New File or Project” - “C++” - “C++ Header File”,输入"cvplugininterface"作为文件名称(输入你认为合适的名称),继续下一步,直到进入代码编辑器模式。
1.2 编辑代码(函数声明)
将编辑器中的代码修改为如下:
#ifndef CVPLUGININTERFACE_H
#define CVPLUGININTERFACE_H
#include <QObject>
#include <QString>
#include "opencv2/opencv.hpp"
class CvPluginInterface
{
public:
virtual ~CvPluginInterface() {}
virtual QString description() = 0;
virtual void processImage(const cv::Mat &inputImage, const cv::Mat &outputImage) = 0;
};
#define CVPLUGININTERFACE_IID "com.amin.cvplugin"
Q_DECLARE_INTERFACE(CvPluginInterface, CVPLUGININTERFACE_IID)
#endif // CVPLUGININTERFACE_H
注意: 代码段:
#ifndef CVPLUGININTERFACE_H
#define CVPLUGININTERFACE_H
...
#endif // CVPLUGININTERFACE_H
为创建头文件时自动添加,用于保证在应用程序编译过程中,对每个头文件只包含和处理一次。
代码段解析: 插件接口包含一个名为description()的函数,用于返回所有插件的描述及其相关有用信息。包含一个名为processImage的函数,该函数以OpenCV Mat 类作为输入,并返回 “1” 作为输出。在该函数中,我们希望每个插件都可以执行某种图像处理、滤波等操作,并返回处理结果。
CVPLUGININTERFACE_IID应该是与包名类似的唯一字符串,但是也可以根据自己的喜好更改。Q_DECLARE_INTERFACE宏将类定义为接口,如果不包含这个宏,Qt将无法把这个类作为插件接口来使用。
2 创建插件
2.1 创建library
打开Qt Creator,依次选择 “File” - " New File or Project" - " Library" - “c++ Library”,输入插件名“median_filter_plugin”(或者你认为合适的名称,但是最好遵循类似的命名规范),点击下一步,在type上一定要选择“Shared Library”,在“ Select Required Modules” 页面,确保只选中了“QtCore”,点击继续直到进入代码编辑器页面。
2.2 链接接口
首先将创建的接口文件 cvplugininterface.h 复制到新创建的插件项目的文件夹内,然后右键单击插件项目,选择“ Add Existing Files ”,将接口头文件添加至插件。
然后我们需要告诉Qt这是一个插件,不只是简单的库。需要在 * .pro文件中添加CONFIG += plugin
2.3 链接OpenCV
在 * .pro 文件中添加以下代码(路径为OpenCV路径,根据自己电脑路径添加)
INCLUDEPATH += C:/app/vs_opencv_qt/opencv453/build/install/include
LIBS += C:/app/vs_opencv_qt/opencv453/build/install/x64/vc16/lib/*.lib
3 编辑代码
打开刚创建的median_filter_plugin插件,打开median_filter_plugin.h头文件,并进行如下修改:
#ifndef MEDIAN_FILTER_PLUGIN_H
#define MEDIAN_FILTER_PLUGIN_H
#include "median_filter_plugin_global.h"
#include "cvplugininterface.h"
class MEDIAN_FILTER_PLUGINSHARED_EXPORT Median_filter_plugin: public QObject, public CvPluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "com.amin.cvplugininterface")
Q_INTERFACES(CvPluginInterface)
public:
Median_filter_plugin();
~Median_filter_plugin();
QString description();
void processImage(const cv::Mat &inputImage, cv::Mat &outputImage);
};
#endif // MEDIAN_FILTER_PLUGIN_H
代码段分析:
- 首先,包含了cvplugininterface.h头文件;
- 然后,确保Median_filter_plugin类继承了QObject和CvPluginInterface;
- 之后,添加了Qt所需的一些宏,以便可以将我们的库识别为插件。
第一个Q_OBJECT宏,默认情况下存在与所有Qt类,以允许Qt特定的功能(如信号与槽)可用。
第二个是Q_PLUGIN_METADATA,需要在一个插件的源代码中刚好出现一次,用于添加关于插件的元数据。
最后一个是Q_INTERFACES,用于声明插件中实现的接口。 - 然后添加description()和processImage()的定义;
- 最后,将所需的修改和具体实现添加到“ median_filter_plugin.cpp” 文件中,最后cpp文件中的代码如下:
#include "median_filter_plugin.h"
Median_filter_plugin::Median_filter_plugin()
{
}
Median_filter_plugin::~Median_filter_plugin()
{
}
QString Median_filter_plugin::description()
{
return "This plugin applies median blur filters to any image."
" This plugin's goal is to make us more familiar with the"
" concept of plugins in general.";
}
void Median_filter_plugin::processImage(const cv::Mat &inputImage, cv::Mat &outputImage)
{
cv::medianBlur(inputImage, outputImage, 5);
}
我们向cpp文件中添加了类析构函数的实现、description()函数和processImage()函数的实现。
至此,接口创建完毕。点击Build将创建一个插件文件,该插件文件通常与工程项目在同一级文件夹中。