Qt开发:ImagePlay算子处理库IPL详解

IPL库是一个模块化图像处理框架,支持动态加载算法、可视化流程编辑和跨平台运行。其核心设计围绕以下目标:

  • 扩展性:通过插件机制添加新算法。

  • 灵活性:支持多数据类型(图像、矩阵、关键点等)。

  • 用户友好:提供GUI配置参数和实时预览。

核心组件及关系

核心类

类名职责关键方法/特性
IPLProcessProperty管理算法参数(如阈值、颜色)- 类型安全(Int/Double/String等)
- 序列化支持
- 绑定GUI控件
IPLProcess算法基类(如滤波、边缘检测)- 定义输入/输出
- 处理逻辑(processInputData
- 事件通知(进度/属性变更)
IPLData数据容器基类(图像、矩阵等)- 多态数据存储
- 类型标记(IPLDataType
- 数据转换(toImage()等)

2 关联梳理 

 

IPLProcess类

  IPLProcess 是ImagePlay框架中所有图像处理算法的抽象基类,定义了算法的统一接口和行为规范。其核心职责包括:

  • 算法生命周期管理(初始化、执行、销毁)

  • 数据流控制(输入/输出接口)

  • 参数管理(动态属性系统)

  • 事件通知(进度、状态变更)

 关键设计要素

算法分类与扩展支持
enum IPLProcessCategory {
    CATEGORY_IO, CATEGORY_EDGES, CATEGORY_FOURIER // ...共13个分类
};
enum IPLOpenCVSupport {
    OPENCV_NONE, OPENCV_OPTIONAL, OPENCV_ONLY 
};
  • 分类系统:通过枚举明确算法类型,便于GUI按功能组织(如边缘检测、几何变换)。

  • OpenCV集成:标记算法对OpenCV的依赖程度,指导运行时资源加载。

算法生命周期方法
方法调用时机典型实现内容
init()算法实例化后初始化内部状态、注册参数(addProcessPropertyXxx)、定义输入/输出类型
processInputData()处理输入数据时核心算法逻辑,读取参数(getProcessPropertyXxx)并生成结果
destroy()算法销毁前释放GPU内存等资源
before/afterProcessing()处理前后钩子数据预处理/后处理,统计计时等
数据流管理
std::vector<IPLProcessIO> _inputs, _outputs;
void addInput(std::string name, IPLDataType type);
  • 动态接口:算法运行时声明所需的输入/输出数量和类型(如单输入单输出、多输入等)。

  • 类型安全:通过 IPLDataType 确保数据兼容性。

属性系统详解

属性类型支持
void addProcessPropertyDouble("sigma", "Sigma", "Blur strength", 1.0);
double val = getProcessPropertyDouble("sigma");
  • 全类型覆盖:支持从基本类型(int/bool)到复杂类型(vector/color/point)。

  • 元数据绑定:每个属性关联标题、描述、取值范围,直接驱动GUI生成控件。

属性与GUI的联动
void notifyPropertyChangedEventHandler(); // 属性修改时触发GUI更新
  • 观察者模式:属性变化自动通知界面,实现实时参数调整。

序列化支持
std::string toJson(); // 序列化所有属性
  • 流程保存/加载:将算法配置(含参数值)导出为JSON,支持持久化。

事件与消息机制

进度通知
notifyProgressEventHandler(50); // 更新进度条至50%
  • 用途:长时间算法运行时反馈进度。

错误处理
addError("Invalid input size"); 
if (hasErrors()) { /* 停止流程 */ }
  • 多级消息:支持错误/警告/信息分级,可在GUI中差异化显示。

线程安全与状态管理

std::mutex _messageMutex; // 保护消息队列
bool _resultReady;        // 标记结果有效性
  • 临界区保护:消息队列的线程安全访问。

  • 状态标记:通过 _updateNeeded 等标志控制算法执行逻辑。

插件系统集成

static const std::string server_name() {return "IPLProcessServer";}
  • 插件契约:通过静态方法声明插件接口,动态库需实现此服务名称。

总结

设计亮点

  • 开闭原则:通过派生类扩展算法,无需修改框架。

  • 自描述性:属性元数据(标题/描述)减少硬编码GUI逻辑。

  • 跨平台支持:纯虚接口与Qt/OpenCV解耦。

IPLProcess 通过以下设计成为框架核心:

  • 标准化接口:统一算法开发范式。

  • 动态灵活性:运行时可扩展的属性和数据接口。

  • 生态集成:与Qt/OpenCV深度协作,同时保持独立性。

  • 用户友好:丰富的元数据和事件机制支撑GUI交互。

其设计模式组合(工厂、观察者、策略模式)和严谨的接口定义,使其成为图像处理流水线的高效抽象层

算子实例

     如IPLRotate 派生算子类,继承自 IPLClonableProcess<IPLRotate> 模板类,实现图像的旋转和缩放变换,自动获得克隆能力。

算子设计亮点特色

  • CRTP模式:通过模板继承实现多态克隆,避免虚函数开销。

  • OpenCV依赖:明确声明 OPENCV_ONLY,强制使用OpenCV实现。

///头文件
class IPLSHARED_EXPORT IPLRotate : public IPLClonableProcess<IPLRotate>
{
public:
                            IPLRotate() : IPLClonableProcess() { init(); }
                            ~IPLRotate()  { destroy(); }

    void                    init                    ();
    void                    destroy                 ();
    bool                    processInputData        (IPLData*, int, bool useOpenCV);
    IPLData*                getResultData           (int);

protected:
    IPLImage*               _result;
};


///-------cpp----------
void IPLRotate::init()
{
    // init
    _result     = NULL;

    // basic settings
    setClassName("IPLRotate");
    setTitle("Rotate/Zoom Image");
    setCategory(IPLProcess::CATEGORY_GEOMETRY);
    setOpenCVSupport(IPLProcess::OPENCV_ONLY);

    // inputs and outputs
    addInput("Image", IPL_IMAGE_COLOR);
    addOutput("Image", IPL_IMAGE_COLOR);

    // properties
    addProcessPropertyInt("angle", "Angle", "", 0, IPL_WIDGET_SLIDER, -180, 180);
    addProcessPropertyDouble("scale", "Scaling", "", 1.0, IPL_WIDGET_SLIDER, 0.1, 10.0);
    addProcessPropertyPoint("center", "Center", "", IPLPoint(0,0), IPL_WIDGET_POINT);
    addProcessPropertyInt("interpolation", "Interpolation:Nearest|Linear|Area|Cubic|Lanczos4", "", 0, IPL_WIDGET_COMBOBOX, 0, 4);
}

void IPLRotate::destroy()
{
    delete _result;
}

bool IPLRotate::processInputData(IPLData* data, int, bool)
{
    IPLImage* image = data->toImage();
	
    // delete previous result
    delete _result;
    _result = NULL;

    // get properties
    int angle = getProcessPropertyInt("angle");
    double scale = getProcessPropertyDouble("scale");
    int interpolation = getProcessPropertyInt("interpolation");
    IPLPoint center = getProcessPropertyPoint("center");

    // Compute a rotation matrix with respect to the center of the image
    //cv::Point centerPoint = cv::Point( image->width()/2, image->height()/2 );
    cv::Point centerPoint = cv::Point(center.x(), center.y());

    /*std::stringstream s;
    s << "<b>Original Aspect Ratio</b>: " << aspectRatio << "\n";
    s << "<b>New Aspect Ratio</b>: " << newAspectRatio << "\n";
    s << "<b>Height</b>: " << height << "\n";
    s << "<b>Width</b>: " << width;
    addInformation(s.str());*/

    _result = new IPLImage(image->type(), image->width(), image->height());

    cv::Mat result;

    // Get the rotation matrix with the specifications above
    cv::Mat rot_mat = getRotationMatrix2D(centerPoint, angle, scale);

    notifyProgressEventHandler(-1);

    // Rotate the warped image
    cv::warpAffine(image->toCvMat(), result, rot_mat, result.size(), interpolation);

    delete _result;
    _result = new IPLImage(result);

    return true;
}

IPLData* IPLRotate::getResultData(int)
{
    return _result;
}

IPLData

  IPLData 是ImagePlay框架中所有图像处理数据的抽象基类,作为算法间传递数据的统一容器。其核心职责是:

  • 多态数据封装:通过派生类支持多种数据类型(图像、矩阵、关键点等)。

  • 类型安全转换:提供显式的类型检查和转换接口。

  • 轻量级接口:仅保留最小必要方法,确保扩展性。

 关键设计解析

类型系统
IPLDataType _type;  // 数据类型标记(如IPL_IMAGE/IPL_MATRIX)
  • 作用:运行时识别具体数据类型,避免动态转换失败。

  • 典型类型(假设的枚举值):

    enum IPLDataType
    {
        IPL_IMAGE_BW = 0,
        IPL_IMAGE_GRAYSCALE,
        IPL_IMAGE_COLOR,
        IPL_IMAGE_ORIENTED,
        IPL_IMAGE_COMPLEX,
        IPL_POINT,
        IPL_MATRIX,
        IPL_SHAPES,
        IPL_UNDEFINED,
    
        //Add additional data types here
        //...
        IPL_KEYPOINTS,
        IPL_CV_MAT,
        IPL_VECTOR,
    
        IPL_NUM_DATATYPES
    };
    IPLSHARED_EXPORT const char *dataTypeName(IPLDataType type);
类型转换接口
virtual IPLImage* toImage();  // 转换为图像(派生类需实现)
  • 设计特点

    • 非纯虚函数:基类提供默认实现(可能返回nullptr或抛异常),允许部分派生类不实现全部转换。

    • 显式转换:强制开发者明确处理类型差异,比隐式转换更安全。

类型兼容性检查
bool isConvertibleTo(IPLDataType target);
  • 用途:在转换前检查合法性,例如:

    if (data->isConvertibleTo(IPL_IMAGE)) {
        IPLImage* img = data->toImage();
    }

派生类实现示例

图像数据(IPLImage
class IPLSHARED_EXPORT IPLImage : public IPLData
{
public:
    IPLImage();
    IPLImage( const IPLImage& image );
    IPLImage( IPLDataType _type, int width, int height );
    IPLImage( cv::Mat& cvMat );
    ~IPLImage();

    int getNumberOfPlanes( void )   { return _nrOfPlanes; }
    int width(void)                 { return _width; }
    int height(void)                { return _height; }

    uchar* rgb32 (void);
    static void rgb32CleanupHandler(void *info);
    IPLImagePlane* plane(int planeNr);
    void fillColor( ipl_basetype color );

    std::string                 toString(int x, int y);

    cv::Mat                     toCvMat();

protected:
    int                         _width;
    int                         _height;
    int                         _nrOfPlanes;
    std::vector<uchar>          _rgb32;
    static int                  _instanceCount;
    std::vector<IPLImagePlane*> _planes;
};
矩阵数据(IPLMatrix
class IPLSHARED_EXPORT IPLMatrix : public IPLData
{
public:
                    IPLMatrix       (int height, int width);
                    IPLMatrix       (int height, int width, ipl_basetype array[]);
                    IPLMatrix       (const IPLMatrix& other);
                    ~IPLMatrix      ();

    ipl_basetype    get             (int x, int y);
    ipl_basetype    get             (int i);
    void            set             (int x, int y, ipl_basetype value);
    void            set             (int i, ipl_basetype value);
    int             height          ()                                                  { return _height; }
    int             width           ()                                                  { return _width; }
    int             size            ()                                                  { return _height * _width; }

protected:
    int                             _width;
    int                             _height;
    std::vector<ipl_basetype>       _data;
};

典型使用场景

算法数据处理
bool EdgeDetectionProcess::processInputData(IPLData* data) {
    IPLImage* img = data->toImage();
    if (!img) {
        addError("Input must be an image");
        return false;
    }
    // ...处理逻辑...
}
多类型支持
void DisplayData(IPLData* data) {
    switch(data->type()) {
        case IPL_IMAGE: renderImage(data->toImage()); break;
        case IPL_POINT: drawPoint(data->toPoint()); break;
        // ...其他类型...
    }
}

 总结

IPLData 通过简洁的接口设计实现了:

  • 统一数据容器:屏蔽不同数据类型的差异。

  • 安全类型转换:通过显式接口降低错误风险。

  • 框架可扩展性:为新增数据类型提供标准接入点。

其设计体现了“单一职责”和“开闭原则”,是IPL库数据流处理的核心基石。通过引入现代C++特性(如智能指针、类型推导),可进一步提升易用性和安全性。

IPLProcessProperty类

IPLProcessProperty 是ImagePlay框架中算法参数的基类,负责:

  • 统一管理各种类型的算法参数(整型、浮点型、字符串等)

  • 绑定GUI控件与参数交互(滑动条、颜色选择器等)

  • 支持序列化用于保存/加载算法配置

典型派生类对比

类型存储值典型用途GUI控件
IPLProcessPropertyIntint阈值、核大小滑动条
IPLProcessPropertyDoubledouble标准差、缩放比例带小数点的滑动条
IPLProcessPropertyBoolbool开关选项复选框
IPLProcessPropertyColorIPLColor画笔颜色、ROI标记色颜色选择器
IPLProcessPropertyStringstd::string文件路径、文本输入文本框

详见算子属性

算子调用管理及显示

IPProcessFactory类

IPProcessFactory 是ImagePlay框架中的算法工厂类,采用工厂模式实现:

  • 集中管理所有图像处理算法(如滤波、边缘检测等)

  • 动态注册和实例化算法对象

  • 分类检索算法(按边缘检测/几何变换等类别)

class IPProcessFactory
{
public:
                        IPProcessFactory            ();
                        ~IPProcessFactory           ();
    void                registerProcess             (QString name, IPLProcess* getInstance);
    void                unregisterProcess           (QString name);
    IPLProcess*         getInstance                 (QString name);
    QStringList         getProcessNamesByCategory   (IPLProcess::IPLProcessCategory category);

private:
    QMap<QString, IPLProcess*>   _map;              //!< Contains all currently registered IPLProcesses by name
};



///---cpp----------
#include "IPProcessFactory.h"

IPProcessFactory::IPProcessFactory()
{
}

IPProcessFactory::~IPProcessFactory()
{
    // delete all template instances
/*    for(QMap<QString, IPLProcess*>::iterator it = _map.begin(); it != _map.end(); it++)
    {
        IPLProcess* p = it.value();
        delete p;
    }*/
}

void IPProcessFactory::registerProcess(QString name, IPLProcess *process)
{
    qDebug() << "IPProcessFactory::registerProcess: " << name << " -> " << process;
    _map.insert(name, process);
}

void IPProcessFactory::unregisterProcess(QString name)
{
    qDebug() << "IPProcessFactory::unregisterProcess: " << name;
    if(_map.contains(name))
    {
        // delete instance and remove from map
        delete _map.value(name);
        _map.remove(name);
    }
}

IPLProcess* IPProcessFactory::getInstance(QString name)
{
    qDebug() << "IPProcessFactory::getInstance: " << name;
    if(_map.contains(name))
    {
        // return a fresh copy of the template process
        IPLProcess* process = _map.value(name)->clone();
        process->properties()->clear();
        process->inputs()->clear();
        process->outputs()->clear();
        process->init();
        return process;
    }
    else
    {
        return NULL;
    }
}

QStringList IPProcessFactory::getProcessNamesByCategory(IPLProcess::IPLProcessCategory category)
{
    qDebug() << "IPProcessFactory::getProcessNamesByCategory";
    QStringList filteredList;
    for (auto it = _map.begin(); it != _map.end(); ++it)
    {
        if(it.value()->category() == category)
        {
            filteredList.push_back(it.key());
        }
    }
    return filteredList;
}

UI显示

主界面加载及注册
void MainWindow::loadProcesses()
{
    // we need a process factory to instanciate at runtime from string
    _factory = new IPProcessFactory;

    // register all processes to the factory
    _factory->registerProcess("IPLConvertToGray",       new IPLConvertToGray);
    _factory->registerProcess("IPLConvertToColor",      new IPLConvertToColor);
    _factory->registerProcess("IPLBinarize",            new IPLBinarize);
    _factory->registerProcess("IPLLoadImage",           new IPLLoadImage);
    _factory->registerProcess("IPLCamera",              new IPLCamera);
    //_factory->registerProcess("IPLLoadVideo",           new IPLLoadVideo);
    _factory->registerProcess("IPLLoadImageSequence",   new IPLLoadImageSequence);
    _factory->registerProcess("IPLSaveImage",           new IPLSaveImage);
    _factory->registerProcess("IPLSplitPlanes",         new IPLSplitPlanes);
    _factory->registerProcess("IPLMergePlanes",         new IPLMergePlanes);
    _factory->registerProcess("IPLGaussianLowPass",     new IPLGaussianLowPass);
    _factory->registerProcess("IPLGammaCorrection",     new IPLGammaCorrection);
    _factory->registerProcess("IPLConvolutionFilter",   new IPLConvolutionFilter);
    _factory->registerProcess("IPLMorphologyBinary",    new IPLMorphologyBinary);
    _factory->registerProcess("IPLMorphologyGrayscale", new IPLMorphologyGrayscale);
    _factory->registerProcess("IPLMorphologyHitMiss",   new IPLMorphologyHitMiss);
    _factory->registerProcess("IPLBlendImages",         new IPLBlendImages);
    _factory->registerProcess("IPLArithmeticOperations",new IPLArithmeticOperations);
    _factory->registerProcess("IPLArithmeticOperationsConstant", new IPLArithmeticOperationsConstant);
    _factory->registerProcess("IPLSynthesize",          new IPLSynthesize);
    _factory->registerProcess("IPLFlipImage",           new IPLFlipImage);
    _factory->registerProcess("IPLGradientOperator",    new IPLGradientOperator);
//    TODO: Fix algorithm and add again.
    _factory->registerProcess("IPLRandomPoint",         new IPLRandomPoint);
    _factory->registerProcess("IPLCanvasSize",          new IPLCanvasSize);
    _factory->registerProcess("IPLResize",              new IPLResize);
    _factory->registerProcess("IPLRotate",              new IPLRotate);

    _factory->registerProcess("IPLEnhanceMode",         new IPLEnhanceMode);
    _factory->registerProcess("IPLFillConcavities",     new IPLFillConcavities);
    _factory->registerProcess("IPLGabor",               new IPLGabor);
    _factory->registerProcess("IPLInverseContrastRatioMapping",new IPLInverseContrastRatioMapping);
    _factory->registerProcess("IPLMax",                 new IPLMax);
    _factory->registerProcess("IPLMaxMinMedian",        new IPLMaxMinMedian);
    _factory->registerProcess("IPLMedian",              new IPLMedian);
    _factory->registerProcess("IPLCanny",               new IPLCanny);
    _factory->registerProcess("IPLHoughCircles",        new IPLHoughCircles);
    _factory->registerProcess("IPLHarrisCorner",        new IPLHarrisCorner);
    _factory->registerProcess("IPLExtractLines",        new IPLExtractLines);
    _factory->registerProcess("IPLExtrema",             new IPLExtrema);
    _factory->registerProcess("IPLLaplaceOfGaussian",   new IPLLaplaceOfGaussian);
    _factory->registerProcess("IPLMin",                 new IPLMin);
    _factory->registerProcess("IPLMorphologicalEdge",   new IPLMorphologicalEdge);
    _factory->registerProcess("IPLNormalizeIllumination",new IPLNormalizeIllumination);
    _factory->registerProcess("IPLBinarizeSavola",      new IPLBinarizeSavola);
    _factory->registerProcess("IPLOnePixelEdge",        new IPLOnePixelEdge);
    _factory->registerProcess("IPLRankTransform",       new IPLRankTransform);
    _factory->registerProcess("IPLUnsharpMasking",      new IPLUnsharpMasking);
    _factory->registerProcess("IPLCompassMask",         new IPLCompassMask);

    _factory->registerProcess("IPLTriangleSegmentation",new IPLTriangleSegmentation);
    _factory->registerProcess("IPLStretchContrast",     new IPLStretchContrast);
    _factory->registerProcess("IPLNegate",              new IPLNegate);
    _factory->registerProcess("IPLMarkImage",           new IPLMarkImage);
    _factory->registerProcess("IPLLocalThreshold",      new IPLLocalThreshold);
    _factory->registerProcess("IPLHysteresisThreshold", new IPLHysteresisThreshold);
    _factory->registerProcess("IPLFalseColor",          new IPLFalseColor);
    _factory->registerProcess("IPLEqualizeHistogram",   new IPLEqualizeHistogram);
    _factory->registerProcess("IPLBinarizeUnimodal",    new IPLBinarizeUnimodal);
    _factory->registerProcess("IPLBinarizeOtsu",        new IPLBinarizeOtsu);
    _factory->registerProcess("IPLBinarizeKMeans",      new IPLBinarizeKMeans);
    _factory->registerProcess("IPLBinarizeEntropy",     new IPLBinarizeEntropy);
    _factory->registerProcess("IPLAddNoise",            new IPLAddNoise);

    _factory->registerProcess("IPLFFT",                 new IPLFFT);
    _factory->registerProcess("IPLIFFT",                new IPLIFFT);
    _factory->registerProcess("IPLFrequencyFilter",     new IPLFrequencyFilter);

    _factory->registerProcess("IPLLabelBlobs",          new IPLLabelBlobs);

    _factory->registerProcess("IPLAccumulate",          new IPLAccumulate);
    _factory->registerProcess("IPLHoughLines",          new IPLHoughLines);
    _factory->registerProcess("IPLHoughLineSegments",   new IPLHoughLineSegments);

    _factory->registerProcess("IPLUndistort",           new IPLUndistort);
    _factory->registerProcess("IPLWarpAffine",          new IPLWarpAffine);
    _factory->registerProcess("IPLWarpPerspective",     new IPLWarpPerspective);

    _factory->registerProcess("IPLGoodFeaturesToTrack", new IPLGoodFeaturesToTrack);

    // not ready:
    /*_factory->registerProcess("IPLMatchTemplate",       new IPLMatchTemplate);
    _factory->registerProcess("IPLFloodFill",           new IPLFloodFill);

    _factory->registerProcess("IPLOpticalFlow",         new IPLOpticalFlow);

    _factory->registerProcess("IPProcessScript",        new IPProcessScript);

    _factory->registerProcess("IPLFeatureDetection",    new IPLFeatureDetection);
    _factory->registerProcess("IPLFeatureMatcher",      new IPLFeatureMatcher);

    _factory->registerProcess("IPLCameraCalibration",   new IPLCameraCalibration);*/
}
算子列表UI呈现
void IPProcessListTabWidget::init(MainWindow *mainWindow)
{
    _mainWindow = mainWindow;

    clear();

    // items
    QStringList categoryIcons;
    categoryIcons.append(":/icons/16.png");
    categoryIcons.append(":/icons/12.png");
    categoryIcons.append(":/icons/27.png");
    categoryIcons.append(":/icons/26.png");
    categoryIcons.append(":/icons/26.png");
    categoryIcons.append(":/icons/8.png");
    categoryIcons.append(":/icons/8.png");
    categoryIcons.append(":/icons/8.png");
    categoryIcons.append(":/icons/8.png");
    categoryIcons.append(":/icons/8.png");
    categoryIcons.append(":/icons/8.png");
    categoryIcons.append(":/icons/8.png");

    QStringList processCategories;                      // CATEGORY_UNDEFINED
    processCategories.append("Input/Output");           // CATEGORY_IO
    processCategories.append("Conversions");            // CATEGORY_CONVERSIONS
    processCategories.append("Geometry");               // CATEGORY_GEOMETRY
    processCategories.append("Arithmetic Operations");  // CATEGORY_ARITHMETIC
    processCategories.append("Point Operations");       // CATEGORY_POINTOPERATIONS
    processCategories.append("Local Operations");       // CATEGORY_LOCALOPERATIONS
    processCategories.append("Morphology & Rank Order");// CATEGORY_MORPHOLOGY
    processCategories.append("Histogram");              // CATEGORY_HISTOGRAM
    processCategories.append("Edges");                  // CATEGORY_GRADIENTS
    processCategories.append("Gradients");              // CATEGORY_GRADIENTS
    processCategories.append("Fourier");                // CATEGORY_FOURIER
    processCategories.append("Objects");                // CATEGORY_OBJECTS
    processCategories.append("Plugins");                //

    //list process names by process category
    QList<QStringList> processLibrary;
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_IO));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_CONVERSIONS));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_GEOMETRY));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_ARITHMETIC));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_POINTOPERATIONS));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_LOCALOPERATIONS));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_MORPHOLOGY));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_HISTOGRAM));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_EDGES));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_GRADIENTS));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_FOURIER));
    processLibrary.append(mainWindow->factory()->getProcessNamesByCategory(IPLProcess::CATEGORY_OBJECTS));

    QStringList plugins;
    for(int i=0; i<mainWindow->pluginManager()->loadedPlugins()->size(); i++)
    {
        plugins.append(mainWindow->pluginManager()->loadedPlugins()->at(i));
    }
    processLibrary.append(plugins);

    // all processes tab
    _allProcessesList = new IPProcessList(mainWindow);

    QWidget* tabAll = new QWidget(this);
    tabAll->setLayout(new QVBoxLayout);
    QLabel* labelAll = new QLabel("All Processes", tabAll);
    labelAll->setStyleSheet("font-size: 12px; font-weight: bold;");
    tabAll->layout()->addWidget(labelAll);
    tabAll->layout()->addWidget(_allProcessesList);

    // rotate icon
    QPixmap pixmap(":/home.png");
    QMatrix transform;
    transform.rotate(90);
    addTab(tabAll, QIcon(pixmap.transformed(transform)), "");

    setIconSize(QSize(20, 20));

    // add all other tabs
    for(int i=0; i<processCategories.length(); i++)
    {
        QWidget* tab = new QWidget(this);
        tab->setLayout(new QVBoxLayout);
        QLabel* label = new QLabel(processCategories[i], tab);
        label->setStyleSheet("font-size: 12px; font-weight: bold;");
        IPProcessList* list = new IPProcessList(mainWindow, this);

        QPixmap categoryIcon;

        for(int j=0; j < processLibrary[i].length(); j++)
        {
            QString processID = processLibrary[i].at(j);

            IPLProcess* tmpProcess = mainWindow->factory()->getInstance(processID);

            // only add if instance exists
            if(tmpProcess)
            {
                QString title = QString::fromStdString(tmpProcess->title());
                QString keywords = QString::fromStdString(tmpProcess->keywords());

                // add to list
                list->addProcessItem(processID, title, keywords, tmpProcess->category());

                // and add to all processes list
                _allProcessesList->addProcessItem(processID, title, keywords, tmpProcess->category());

                // use icon of first process for the category tab
                if(categoryIcon.width() == 0)
                {
                    QFileInfo iconFile(_mainWindow->processIconPath(processID));

                    if(iconFile.exists())
                    {
                        categoryIcon = QPixmap(iconFile.absoluteFilePath());
                    }
                }
            }

            delete tmpProcess;
        }

        // sort items
        list->sortItems();

        // add GUI elements
        tab->layout()->addWidget(label);
        tab->layout()->addWidget(list);

        // for the last tab (plugins) add buttons
        if(i == processCategories.length()-1)
        {
            QPushButton* btnReloadPlugins = new QPushButton("Reload Plugins");
            connect(btnReloadPlugins, &QPushButton::clicked, mainWindow, &MainWindow::reloadPlugins);
            tab->layout()->addWidget(btnReloadPlugins);
        }

        // rotate icon
        //QPixmap pixmap(categoryIcons[i]);
        QMatrix transform;
        transform.rotate(90);

        // only add categories with entries
        addTab(tab, QIcon(categoryIcon.transformed(transform)), "");
        setTabToolTip(i+1, processCategories[i]);
    }

    // set plugins tab icon
    QPixmap pluginIcon(":/plugins.png");
    setTabIcon(count()-1, QIcon(pluginIcon.transformed(transform)));

    // sort all process list
    _allProcessesList->sortItems();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值