Bladeren bron

上传文件至 'src'

wang 2 weken geleden
bovenliggende
commit
0960c5a510
5 gewijzigde bestanden met toevoegingen van 576 en 0 verwijderingen
  1. 129 0
      src/algorithmparamfactory.cpp
  2. 38 0
      src/algorithmparamfactory.h
  3. 28 0
      src/algorithmparamstorage.h
  4. 295 0
      src/algorithmprocess.cpp
  5. 86 0
      src/algorithmprocess.h

+ 129 - 0
src/algorithmparamfactory.cpp

@@ -0,0 +1,129 @@
+#include "algorithmparamfactory.h"
+#include <QVariant>
+
+// Initialize static member
+QMap<QWidget*, QMap<QString, QWidget*>> AlgorithmParamWidgetFactory::m_paramWidgetMaps;
+
+QWidget* AlgorithmParamWidgetFactory::createParamWidget(const AlgorithmMeta& algMeta, QWidget* parent) {
+    qDebug() << "Creating param widget for algorithm:" << algMeta.type << "-" << algMeta.name;
+    qDebug() << "Number of parameters:" << algMeta.params.size();
+    
+    for (const ParamMeta& param : algMeta.params) {
+        qDebug() << "Parameter:" << param.name << "-" << param.displayName << "Type:" << static_cast<int>(param.type);
+    }
+    
+    QWidget* paramWidget = new QWidget(parent);
+    QVBoxLayout* mainLayout = new QVBoxLayout(paramWidget);
+    paramWidget->setLayout(mainLayout);
+
+    QMap<QString, QWidget*> paramMap;
+
+    for (const ParamMeta& param : algMeta.params) {
+        QWidget* rowWidget = new QWidget(paramWidget);
+        QHBoxLayout* rowLayout = new QHBoxLayout(rowWidget);
+        rowLayout->setContentsMargins(0, 0, 0, 0);
+
+        QLabel* label = new QLabel(param.displayName, rowWidget);
+        label->setFixedWidth(80);
+        rowLayout->addWidget(label);
+
+        QWidget* control = nullptr;
+        switch (param.type) {
+            case ParamType::Int: {
+                QSpinBox* spinBox = new QSpinBox(rowWidget);
+                spinBox->setRange(param.minVal, param.maxVal);
+                spinBox->setValue(param.defaultValue);
+                control = spinBox;
+                break;
+            }
+            case ParamType::Float: {
+                QDoubleSpinBox* doubleSpinBox = new QDoubleSpinBox(rowWidget);
+                doubleSpinBox->setRange(param.minVal, param.maxVal);
+                doubleSpinBox->setSingleStep(0.1);
+                doubleSpinBox->setValue(param.defaultValue);
+                control = doubleSpinBox;
+                break;
+            }
+            case ParamType::Bool: {
+                QCheckBox* checkBox = new QCheckBox(rowWidget);
+                checkBox->setChecked(param.defaultValue != 0);
+                control = checkBox;
+                break;
+            }
+            case ParamType::Enum: {
+                QComboBox* comboBox = new QComboBox(rowWidget);
+                for (auto it = param.enumItems.begin(); it != param.enumItems.end(); ++it) {
+                    comboBox->addItem(it.value(), it.key());
+                }
+                int defaultEnum = static_cast<int>(param.defaultValue);
+                comboBox->setCurrentIndex(comboBox->findData(defaultEnum));
+                control = comboBox;
+                break;
+            }
+        }
+
+        if (control) {
+            rowLayout->addWidget(control);
+            paramMap[param.name] = control;
+        }
+
+        mainLayout->addWidget(rowWidget);
+    }
+
+    QPushButton* resetBtn = new QPushButton("Reset Default", paramWidget);
+    mainLayout->addWidget(resetBtn);
+    QObject::connect(resetBtn, &QPushButton::clicked, resetBtn, [algMeta, paramMap]() {
+        AlgorithmParamWidgetFactory::resetToDefault(algMeta, paramMap);
+    });
+
+    // Store the parameter map for later use
+    m_paramWidgetMaps[paramWidget] = paramMap;
+
+    return paramWidget;
+}
+
+QMap<QString, QVariant> AlgorithmParamWidgetFactory::getParamValues(QWidget* paramWidget) {
+    QMap<QString, QVariant> paramValues;
+    
+    // Check if we have a parameter map for this widget
+    if (m_paramWidgetMaps.contains(paramWidget)) {
+        QMap<QString, QWidget*> paramMap = m_paramWidgetMaps[paramWidget];
+        
+        // Iterate through all parameters in the map
+        for (auto it = paramMap.begin(); it != paramMap.end(); ++it) {
+            QString paramName = it.key();
+            QWidget* control = it.value();
+            
+            // Get the value based on the control type
+            if (QSpinBox* spinBox = qobject_cast<QSpinBox*>(control)) {
+                paramValues[paramName] = spinBox->value();
+            } else if (QDoubleSpinBox* doubleSpinBox = qobject_cast<QDoubleSpinBox*>(control)) {
+                paramValues[paramName] = doubleSpinBox->value();
+            } else if (QCheckBox* checkBox = qobject_cast<QCheckBox*>(control)) {
+                paramValues[paramName] = checkBox->isChecked();
+            } else if (QComboBox* comboBox = qobject_cast<QComboBox*>(control)) {
+                paramValues[paramName] = comboBox->currentData().toInt();
+            }
+        }
+    }
+    
+    return paramValues;
+}
+
+void AlgorithmParamWidgetFactory::resetToDefault(const AlgorithmMeta& algMeta, const QMap<QString, QWidget*>& paramWidgetMap) {
+    for (const ParamMeta& param : algMeta.params) {
+        if (!paramWidgetMap.contains(param.name)) continue;
+        QWidget* control = paramWidgetMap[param.name];
+        if (QSpinBox* spinBox = qobject_cast<QSpinBox*>(control)) {
+            spinBox->setValue(param.defaultValue);
+        } else if (QDoubleSpinBox* doubleSpinBox = qobject_cast<QDoubleSpinBox*>(control)) {
+            doubleSpinBox->setValue(param.defaultValue);
+        } else if (QCheckBox* checkBox = qobject_cast<QCheckBox*>(control)) {
+            checkBox->setChecked(param.defaultValue != 0);
+        } else if (QComboBox* comboBox = qobject_cast<QComboBox*>(control)) {
+            int defaultEnum = static_cast<int>(param.defaultValue);
+            comboBox->setCurrentIndex(comboBox->findData(defaultEnum));
+        }
+    }
+}
+

+ 38 - 0
src/algorithmparamfactory.h

@@ -0,0 +1,38 @@
+#ifndef ALGORITHMPARAMFACTORY_H
+#define ALGORITHMPARAMFACTORY_H
+
+#include <QApplication>
+#include <QWidget>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QDoubleSpinBox>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QLabel>
+#include <QComboBox>
+#include <QPushButton>
+#include <QMap>
+#include <QString>
+#include <QDebug>
+#include <QVariant>
+
+#include "algorithmbase.h"
+
+// 4. Algorithm parameter widget factory (generates adjustment interface based on algorithm type)
+class AlgorithmParamWidgetFactory {
+public:
+    // Generate parameter adjustment interface for specified algorithm
+    static QWidget* createParamWidget(const AlgorithmMeta& algMeta, QWidget* parent = nullptr);
+    
+    // Get parameter values
+    static QMap<QString, QVariant> getParamValues(QWidget* paramWidget);
+    
+    // Reset to default values
+    static void resetToDefault(const AlgorithmMeta& algMeta, const QMap<QString, QWidget*>& paramWidgetMap);
+
+private:
+    // Store parameter widget maps for each parameter widget
+    static QMap<QWidget*, QMap<QString, QWidget*>> m_paramWidgetMaps;
+};
+
+#endif // ALGORITHMPARAMFACTORY_H

+ 28 - 0
src/algorithmparamstorage.h

@@ -0,0 +1,28 @@
+#ifndef ALGORITHMPARAMSTORAGE_H
+#define ALGORITHMPARAMSTORAGE_H
+
+#include <QMap>
+#include <QString>
+#include <QVariant>
+#include "algorithmparamfactory.h"
+
+// Algorithm parameter storage class
+// Used to store and manage parameters for different algorithms
+class AlgorithmParamStorage {
+public:
+    // Singleton instance
+    static AlgorithmParamStorage* instance();
+    
+    // Store parameters for an algorithm
+    void storeParams(const QString& algorithmType, const QMap<QString, QVariant>& params);
+    
+    // Get parameters for an algorithm
+    QMap<QString, QVariant> getParams(const QString& algorithmType);
+    
+    // Check if parameters exist for an algorithm
+    bool hasParams(const QString& algorithmType);
+    
+    // Remove parameters for an algorithm
+    void removeParams(const QString& algorithmType);
+    
+    // Clear

+ 295 - 0
src/algorithmprocess.cpp

@@ -0,0 +1,295 @@
+#include "algorithmprocess.h"
+#include "algorithmfactory.h"
+#include <QJsonObject>
+#include <QFile>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QIODevice>
+
+AlgorithmProcess::AlgorithmProcess()
+{
+
+}
+
+void AlgorithmProcess::addStep(const QString& algorithmName, const QJsonObject& params)
+{
+    AlgorithmStep step;
+    step.name = algorithmName;
+    step.params = params;
+    addStep(step);
+}
+
+void AlgorithmProcess::addStep(const AlgorithmStep& step)
+{
+    steps.append(step);
+    std::shared_ptr<AlgorithmBase> algorithm = std::shared_ptr<AlgorithmBase>(AlgorithmFactory::create(step.name));
+    if (algorithm) {
+        AlgorithmMeta params = algorithm->getParams();
+        for (int i = 0; i < params.params.size(); ++i) {
+            QString paramName = params.params[i].name;
+            if (step.params.contains(paramName)) {
+                QJsonValue value = step.params[paramName];
+                if (value.isDouble()) {
+                    params.params[i].defaultValue = value.toDouble();
+                } else if (value.isBool()) {
+                    params.params[i].defaultValue = value.toBool() ? 1.0 : 0.0;
+                }
+            }
+        }
+        algorithm->setParams(params);
+        stepsAlgorithm.push_back(algorithm);
+    }
+
+}
+
+void AlgorithmProcess::insertStep(int index, const AlgorithmStep& step)
+{
+    if (index >= 0 && index <= steps.size()) {
+        steps.insert(index, step);
+        std::shared_ptr<AlgorithmBase> algorithm = std::shared_ptr<AlgorithmBase>(AlgorithmFactory::create(step.name));
+        if (algorithm) {
+            AlgorithmMeta params = algorithm->getParams();
+            for (int i = 0; i < params.params.size(); ++i) {
+                QString paramName = params.params[i].name;
+                if (step.params.contains(paramName)) {
+                    QJsonValue value = step.params[paramName];
+                    if (value.isDouble()) {
+                        params.params[i].defaultValue = value.toDouble();
+                    } else if (value.isBool()) {
+                        params.params[i].defaultValue = value.toBool() ? 1.0 : 0.0;
+                    }
+                }
+            }
+            algorithm->setParams(params);
+            stepsAlgorithm.insert(index, algorithm);
+        }
+    }
+}
+
+void AlgorithmProcess::removeStep(int index)
+{
+    if (index >= 0 && index < steps.size() && index < stepsAlgorithm.size()) {
+        steps.remove(index);
+        stepsAlgorithm.remove(index);
+    }
+}
+
+void AlgorithmProcess::moveStep(int fromIndex, int toIndex)
+{
+    if (fromIndex >= 0 && fromIndex < steps.size() && toIndex >= 0 && toIndex < steps.size() &&
+        fromIndex < stepsAlgorithm.size() && toIndex < stepsAlgorithm.size()) {
+        steps.move(fromIndex, toIndex);
+        stepsAlgorithm.move(fromIndex, toIndex);
+    }
+}
+
+QVector<AlgorithmProcess::AlgorithmStep> AlgorithmProcess::getSteps() const
+{
+    return steps;
+}
+
+QVector<std::shared_ptr<AlgorithmBase>> AlgorithmProcess::getAlgorithSteps() const
+{
+    return stepsAlgorithm;
+}
+
+void AlgorithmProcess::clearSteps()
+{
+    steps.clear();
+    stepsAlgorithm.clear();
+}
+cv::Mat AlgorithmProcess::executeStep(int index){
+    // Check if index is valid
+    QVector<std::shared_ptr<AlgorithmBase>> algorithmSteps = getAlgorithSteps();
+    if (index < 0 || index > algorithmSteps.size()) {
+        return Src;
+    }
+    
+    std::shared_ptr<AlgorithmBase> stepAlgorithm = algorithmSteps[index];
+    if (!stepAlgorithm) {
+        return Src;
+    }
+    // Subsequent steps, use previous algorithm's output
+    std::shared_ptr<AlgorithmBase> stepAlgorithmPre=nullptr;
+    if(index - 1>0){
+        stepAlgorithmPre = algorithmSteps[index - 1];
+    }
+    if (stepAlgorithmPre) {
+          RuntimeParamsBase* preParams = stepAlgorithmPre->getRuntimeParams();
+          if (preParams) {
+             // Try to cast to specific algorithm's runtime params
+             if (auto* cannyParams = dynamic_cast<CannyEdge::RuntimeParamsCannyEdge*>(preParams)) {
+                 stepAlgorithm->process(cannyParams->outimage);
+             } else if (auto* thresholdParams = dynamic_cast<Thresholding::RuntimeParamsThresholding*>(preParams)) {
+                 stepAlgorithm->process(thresholdParams->outimage);
+             } else if (auto* gaussianParams = dynamic_cast<GaussianBlur::RuntimeParamsGaussianBlur*>(preParams)) {
+                 stepAlgorithm->process(gaussianParams->outimage);
+             } else if (auto* medianParams = dynamic_cast<MedianBlur::RuntimeParamsGaussianBlur*>(preParams)) {
+                 stepAlgorithm->process(medianParams->outimage);
+             } else if (auto* dilateParams = dynamic_cast<Dilate::RuntimeParamsDilate*>(preParams)) {
+                 stepAlgorithm->process(dilateParams->outimage);
+             } else if (auto* erodeParams = dynamic_cast<Erode::RuntimeParamsErode*>(preParams)) {
+                 stepAlgorithm->process(erodeParams->outimage);
+             } else if (auto* grayscaleParams = dynamic_cast<Grayscale::RuntimeParamsGrayscale*>(preParams)) {
+                 stepAlgorithm->process(grayscaleParams->outimage);
+             } else if (auto* histParams = dynamic_cast<HistogramEqualization::RuntimeParamsHistogramEqualization*>(preParams)) {
+                 stepAlgorithm->process(histParams->outimage);
+             } else if (auto* contoursParams = dynamic_cast<FindContours::RuntimeParamsFindContours*>(preParams)) {
+                 stepAlgorithm->process(contoursParams->outimage);
+             }
+          }
+          else {
+             // Fallback: use global image
+             stepAlgorithm->process(Src.clone());
+          }
+      }else{
+        stepAlgorithm->process(Src.clone());
+    }
+
+    return Src;
+}
+cv::Mat AlgorithmProcess::execute(const cv::Mat& inputImage)
+{
+
+    cv::Mat currentImage = inputImage.clone();
+    for (int i = 0; i < steps.size(); ++i) {
+        std::shared_ptr<AlgorithmBase> algorithm = stepsAlgorithm[i];
+        if (algorithm) {
+            // 执行算法
+            algorithm->process(currentImage);
+            // 更新currentImage为当前算法的输出
+            RuntimeParamsBase* runtimeParams = algorithm->getRuntimeParams();
+            if (runtimeParams) {
+                // 尝试获取输出图像
+                if (auto* cannyParams = dynamic_cast<CannyEdge::RuntimeParamsCannyEdge*>(runtimeParams)) {
+                    currentImage = cannyParams->outimage.clone();
+                } else if (auto* thresholdParams = dynamic_cast<Thresholding::RuntimeParamsThresholding*>(runtimeParams)) {
+                    currentImage = thresholdParams->outimage.clone();
+                } else if (auto* gaussianParams = dynamic_cast<GaussianBlur::RuntimeParamsGaussianBlur*>(runtimeParams)) {
+                    currentImage = gaussianParams->outimage.clone();
+                } else if (auto* medianParams = dynamic_cast<MedianBlur::RuntimeParamsGaussianBlur*>(runtimeParams)) {
+                    currentImage = medianParams->outimage.clone();
+                } else if (auto* dilateParams = dynamic_cast<Dilate::RuntimeParamsDilate*>(runtimeParams)) {
+                    currentImage = dilateParams->outimage.clone();
+                } else if (auto* erodeParams = dynamic_cast<Erode::RuntimeParamsErode*>(runtimeParams)) {
+                    currentImage = erodeParams->outimage.clone();
+                } else if (auto* grayscaleParams = dynamic_cast<Grayscale::RuntimeParamsGrayscale*>(runtimeParams)) {
+                    currentImage = grayscaleParams->outimage.clone();
+                } else if (auto* histParams = dynamic_cast<HistogramEqualization::RuntimeParamsHistogramEqualization*>(runtimeParams)) {
+                    currentImage = histParams->outimage.clone();
+                } else if (auto* contoursParams = dynamic_cast<FindContours::RuntimeParamsFindContours*>(runtimeParams)) {
+                    currentImage = contoursParams->outimage.clone();
+                }
+            }
+        }
+    }
+    return currentImage;
+}
+
+bool AlgorithmProcess::saveToFile(const QString& filePath) const
+{
+    QFile file(filePath);
+    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+        return false;
+    }
+
+    QJsonArray stepsArray;
+    for (const AlgorithmStep& step : steps) {
+        QJsonObject stepObj;
+        stepObj["name"] = step.name;
+        stepObj["type"] = step.type;
+        stepObj["params"] = step.params;
+        stepsArray.append(stepObj);
+    }
+
+    QJsonObject rootObj;
+    rootObj["steps"] = stepsArray;
+
+    QJsonDocument doc(rootObj);
+    QByteArray jsonData = doc.toJson(QJsonDocument::Indented);
+
+    file.write(jsonData);
+    file.close();
+
+    return true;
+}
+
+bool AlgorithmProcess::loadFromFile(const QString& filePath)
+{
+    QFile file(filePath);
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        return false;
+    }
+
+    QByteArray jsonData = file.readAll();
+    QJsonDocument doc = QJsonDocument::fromJson(jsonData);
+
+    if (!doc.isObject()) {
+        file.close();
+        return false;
+    }
+
+    QJsonObject rootObj = doc.object();
+    if (!rootObj.contains("steps") || !rootObj["steps"].isArray()) {
+        file.close();
+        return false;
+    }
+
+    QJsonArray stepsArray = rootObj["steps"].toArray();
+
+    steps.clear();
+    stepsAlgorithm.clear();
+    for (const QJsonValue& value : stepsArray) {
+        if (!value.isObject()) {
+            continue;
+        }
+
+        QJsonObject stepObj = value.toObject();
+        if (!stepObj.contains("name") || !stepObj["name"].isString()) {
+            continue;
+        }
+
+        AlgorithmStep step;
+        step.name = stepObj["name"].toString();
+
+        if (stepObj.contains("type") && stepObj["type"].isString()) {
+            step.type = stepObj["type"].toString();
+        }
+
+        if (stepObj.contains("params") && stepObj["params"].isObject()) {
+            step.params = stepObj["params"].toObject();
+        }
+
+        steps.append(step);
+        std::shared_ptr<AlgorithmBase> algorithm = std::shared_ptr<AlgorithmBase>(AlgorithmFactory::create(step.name));
+        if (algorithm) {
+            AlgorithmMeta params = algorithm->getParams();
+            for (int i = 0; i < params.params.size(); ++i) {
+                QString paramName = params.params[i].name;
+                if (step.params.contains(paramName)) {
+                    QJsonValue value = step.params[paramName];
+                    if (value.isDouble()) {
+                        params.params[i].defaultValue = value.toDouble();
+                    } else if (value.isBool()) {
+                        params.params[i].defaultValue = value.toBool() ? 1.0 : 0.0;
+                    }
+                }
+            }
+            algorithm->setParams(params);
+            stepsAlgorithm.push_back(algorithm);
+        }
+    }
+
+    file.close();
+    return true;
+}
+
+bool AlgorithmProcess::saveProcess(const QString& filePath) const
+{
+    return saveToFile(filePath);
+}
+
+bool AlgorithmProcess::loadProcess(const QString& filePath)
+{
+    return loadFromFile(filePath);
+}

+ 86 - 0
src/algorithmprocess.h

@@ -0,0 +1,86 @@
+#ifndef ALGORITHMPROCESS_H
+#define ALGORITHMPROCESS_H
+
+#include <QVector>
+#include <QString>
+#include <QJsonObject>
+#include <opencv2/opencv.hpp>
+#include "algorithm.h"
+#include <typeindex>
+
+
+
+class AlgorithmProcess
+{
+public:
+    // Algorithm step structure
+    struct AlgorithmStep
+    {
+        QString name;        // Algorithm name
+        QString type;        // Algorithm type
+        QJsonObject params;  // Parameters as JSON object
+
+        bool operator==(const AlgorithmStep& other) const
+        {
+            return (name == other.name) &&
+                   (type == other.type) &&
+                   (params == other.params); // QJsonObject ����֧�� == �Ƚ�
+        }
+    };
+    
+    // Constructor
+    AlgorithmProcess();
+    
+    // Add algorithm step
+    void addStep(const QString& algorithmName, const QJsonObject& params = QJsonObject());
+    
+    // Add algorithm step with type
+    void addStep(const AlgorithmStep& step);
+    
+    // Insert algorithm step
+    void insertStep(int index, const AlgorithmStep& step);
+    
+    // Remove algorithm step
+    void removeStep(int index);
+    
+    // Move algorithm step
+    void moveStep(int fromIndex, int toIndex);
+    
+    // Get algorithm steps
+    QVector<AlgorithmStep> getSteps() const;
+
+    QVector<std::shared_ptr<AlgorithmBase>> getAlgorithSteps() const;
+
+    
+    // Clear all steps
+    void clearSteps();
+
+    // Execute algorithm process
+    cv::Mat execute(const cv::Mat& inputImage);
+
+    cv::Mat executeStep(int index);
+    
+    // Save algorithm process to JSON file
+    bool saveToFile(const QString& filePath) const;
+    
+    // Load algorithm process from JSON file
+    bool loadFromFile(const QString& filePath);
+    
+    // Save process (wrapper for saveToFile)
+    bool saveProcess(const QString& filePath) const;
+    
+    // Load process (wrapper for loadFromFile)
+    bool loadProcess(const QString& filePath);
+    void setGlobalMat(cv::Mat& src){
+        Src=src;
+    };
+    cv::Mat getGlobalMat() const{
+       return Src;
+    };
+private:
+    QVector<AlgorithmStep> steps;
+    QVector<std::shared_ptr<AlgorithmBase>> stepsAlgorithm;
+    cv::Mat Src;
+};
+
+#endif // ALGORITHMPROCESS_H