|
|
@@ -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);
|
|
|
+}
|