|
@@ -0,0 +1,272 @@
|
|
|
|
|
+#include "processflowfactory.h"
|
|
|
|
|
+#include <QFile>
|
|
|
|
|
+#include <QJsonDocument>
|
|
|
|
|
+#include <QJsonObject>
|
|
|
|
|
+#include <QJsonArray>
|
|
|
|
|
+
|
|
|
|
|
+// 初始化静态成员
|
|
|
|
|
+ProcessFlowFactory* ProcessFlowFactory::instance = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ProcessFlowFactory* ProcessFlowFactory::getInstance()
|
|
|
|
|
+{
|
|
|
|
|
+ if (!instance) {
|
|
|
|
|
+ instance = new ProcessFlowFactory();
|
|
|
|
|
+ }
|
|
|
|
|
+ return instance;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ProcessFlowFactory::ProcessFlowFactory()
|
|
|
|
|
+ : flowName("默认流程")
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ProcessFlowFactory::~ProcessFlowFactory()
|
|
|
|
|
+{
|
|
|
|
|
+ cleanup();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void ProcessFlowFactory::cleanup()
|
|
|
|
|
+{
|
|
|
|
|
+ for (ProcessStep* step : steps) {
|
|
|
|
|
+ delete step;
|
|
|
|
|
+ }
|
|
|
|
|
+ steps.clear();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ImageExtractStep* ProcessFlowFactory::createImageExtractStep(const QString& name)
|
|
|
|
|
+{
|
|
|
|
|
+ ImageExtractStep* step = new ImageExtractStep(name);
|
|
|
|
|
+ return step;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+AlgorithmRunStep* ProcessFlowFactory::createAlgorithmRunStep(const QString& name)
|
|
|
|
|
+{
|
|
|
|
|
+ AlgorithmRunStep* step = new AlgorithmRunStep(name);
|
|
|
|
|
+ return step;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void ProcessFlowFactory::addStep(ProcessStep* step)
|
|
|
|
|
+{
|
|
|
|
|
+ if (step) {
|
|
|
|
|
+ steps.append(step);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void ProcessFlowFactory::insertStep(int index, ProcessStep* step)
|
|
|
|
|
+{
|
|
|
|
|
+ if (step && index >= 0 && index <= steps.size()) {
|
|
|
|
|
+ steps.insert(index, step);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void ProcessFlowFactory::removeStep(int index)
|
|
|
|
|
+{
|
|
|
|
|
+ if (index >= 0 && index < steps.size()) {
|
|
|
|
|
+ delete steps[index];
|
|
|
|
|
+ steps.removeAt(index);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+ProcessStep* ProcessFlowFactory::getStep(int index) const
|
|
|
|
|
+{
|
|
|
|
|
+ if (index >= 0 && index < steps.size()) {
|
|
|
|
|
+ return steps[index];
|
|
|
|
|
+ }
|
|
|
|
|
+ return nullptr;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void ProcessFlowFactory::clearSteps()
|
|
|
|
|
+{
|
|
|
|
|
+ cleanup();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+cv::Mat ProcessFlowFactory::executeFlow(const cv::Mat& inputImage)
|
|
|
|
|
+{
|
|
|
|
|
+ lastError.clear();
|
|
|
|
|
+
|
|
|
|
|
+ if (steps.isEmpty()) {
|
|
|
|
|
+ setError("流程中没有步骤");
|
|
|
|
|
+ return cv::Mat();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cv::Mat currentImage = inputImage;
|
|
|
|
|
+
|
|
|
|
|
+ // 依次执行每个步骤
|
|
|
|
|
+ for (int i = 0; i < steps.size(); ++i) {
|
|
|
|
|
+ ProcessStep* step = steps[i];
|
|
|
|
|
+
|
|
|
|
|
+ // 跳过禁用的步骤
|
|
|
|
|
+ if (!step->isEnabled()) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 执行步骤
|
|
|
|
|
+ currentImage = step->execute(currentImage);
|
|
|
|
|
+
|
|
|
|
|
+ // 检查执行结果
|
|
|
|
|
+ if (currentImage.empty()) {
|
|
|
|
|
+ setError(QString("步骤 %1 (%2) 执行失败: %3")
|
|
|
|
|
+ .arg(i + 1)
|
|
|
|
|
+ .arg(step->getName())
|
|
|
|
|
+ .arg(step->getLastError()));
|
|
|
|
|
+ return cv::Mat();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return currentImage;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+cv::Mat ProcessFlowFactory::executeStep(int index, const cv::Mat& inputImage)
|
|
|
|
|
+{
|
|
|
|
|
+ lastError.clear();
|
|
|
|
|
+
|
|
|
|
|
+ if (index < 0 || index >= steps.size()) {
|
|
|
|
|
+ setError("步骤索引超出范围");
|
|
|
|
|
+ return cv::Mat();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ProcessStep* step = steps[index];
|
|
|
|
|
+ if (!step->isEnabled()) {
|
|
|
|
|
+ setError("步骤已被禁用");
|
|
|
|
|
+ return cv::Mat();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cv::Mat result = step->execute(inputImage);
|
|
|
|
|
+
|
|
|
|
|
+ if (result.empty()) {
|
|
|
|
|
+ setError(QString("步骤执行失败: %1").arg(step->getLastError()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool ProcessFlowFactory::loadFromJson(const QJsonObject& json)
|
|
|
|
|
+{
|
|
|
|
|
+ clearSteps();
|
|
|
|
|
+
|
|
|
|
|
+ // 加载流程名称
|
|
|
|
|
+ flowName = json.value("flowName").toString("默认流程");
|
|
|
|
|
+
|
|
|
|
|
+ // 加载步骤
|
|
|
|
|
+ QJsonArray stepsArray = json.value("steps").toArray();
|
|
|
|
|
+ for (const QJsonValue& stepValue : stepsArray) {
|
|
|
|
|
+ QJsonObject stepObj = stepValue.toObject();
|
|
|
|
|
+ QString stepType = stepObj.value("type").toString();
|
|
|
|
|
+ QString stepName = stepObj.value("name").toString();
|
|
|
|
|
+
|
|
|
|
|
+ ProcessStep* step = nullptr;
|
|
|
|
|
+
|
|
|
|
|
+ if (stepType == "ImageExtract") {
|
|
|
|
|
+ ImageExtractStep* extractStep = createImageExtractStep(stepName);
|
|
|
|
|
+
|
|
|
|
|
+ // 加载图像提取参数
|
|
|
|
|
+ QJsonObject params = stepObj.value("params").toObject();
|
|
|
|
|
+ int source = params.value("source").toInt(0);
|
|
|
|
|
+ QString imagePath = params.value("imagePath").toString();
|
|
|
|
|
+ int cameraIndex = params.value("cameraIndex").toInt(0);
|
|
|
|
|
+
|
|
|
|
|
+ extractStep->setImageSource(static_cast<ImageExtractStep::ImageSource>(source));
|
|
|
|
|
+ extractStep->setImagePath(imagePath);
|
|
|
|
|
+ extractStep->setCameraIndex(cameraIndex);
|
|
|
|
|
+
|
|
|
|
|
+ step = extractStep;
|
|
|
|
|
+ } else if (stepType == "AlgorithmRun") {
|
|
|
|
|
+ AlgorithmRunStep* algoStep = createAlgorithmRunStep(stepName);
|
|
|
|
|
+
|
|
|
|
|
+ // 加载算法参数
|
|
|
|
|
+ QJsonObject params = stepObj.value("params").toObject();
|
|
|
|
|
+ QString algoType = params.value("algorithmType").toString();
|
|
|
|
|
+ QJsonObject algoParams = params.value("algorithmParams").toObject();
|
|
|
|
|
+
|
|
|
|
|
+ algoStep->setAlgorithmType(algoType);
|
|
|
|
|
+ algoStep->setAlgorithmParams(algoParams);
|
|
|
|
|
+
|
|
|
|
|
+ step = algoStep;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (step) {
|
|
|
|
|
+ // 加载启用状态
|
|
|
|
|
+ bool enabled = stepObj.value("enabled").toBool(true);
|
|
|
|
|
+ step->setEnabled(enabled);
|
|
|
|
|
+
|
|
|
|
|
+ addStep(step);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+QJsonObject ProcessFlowFactory::saveToJson() const
|
|
|
|
|
+{
|
|
|
|
|
+ QJsonObject json;
|
|
|
|
|
+ json["flowName"] = flowName;
|
|
|
|
|
+
|
|
|
|
|
+ QJsonArray stepsArray;
|
|
|
|
|
+ for (ProcessStep* step : steps) {
|
|
|
|
|
+ QJsonObject stepObj;
|
|
|
|
|
+ stepObj["name"] = step->getName();
|
|
|
|
|
+ stepObj["enabled"] = step->isEnabled();
|
|
|
|
|
+
|
|
|
|
|
+ if (step->getType() == ProcessStep::ImageExtract) {
|
|
|
|
|
+ stepObj["type"] = "ImageExtract";
|
|
|
|
|
+
|
|
|
|
|
+ ImageExtractStep* extractStep = static_cast<ImageExtractStep*>(step);
|
|
|
|
|
+ QJsonObject params;
|
|
|
|
|
+ params["source"] = static_cast<int>(extractStep->getImageSource());
|
|
|
|
|
+ params["imagePath"] = extractStep->getImagePath();
|
|
|
|
|
+ params["cameraIndex"] = extractStep->getCameraIndex();
|
|
|
|
|
+
|
|
|
|
|
+ stepObj["params"] = params;
|
|
|
|
|
+ } else if (step->getType() == ProcessStep::AlgorithmRun) {
|
|
|
|
|
+ stepObj["type"] = "AlgorithmRun";
|
|
|
|
|
+
|
|
|
|
|
+ AlgorithmRunStep* algoStep = static_cast<AlgorithmRunStep*>(step);
|
|
|
|
|
+ QJsonObject params;
|
|
|
|
|
+ params["algorithmType"] = algoStep->getAlgorithmType();
|
|
|
|
|
+ params["algorithmParams"] = algoStep->getAlgorithmParams();
|
|
|
|
|
+
|
|
|
|
|
+ stepObj["params"] = params;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ stepsArray.append(stepObj);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ json["steps"] = stepsArray;
|
|
|
|
|
+ return json;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool ProcessFlowFactory::loadFromFile(const QString& filePath)
|
|
|
|
|
+{
|
|
|
|
|
+ QFile file(filePath);
|
|
|
|
|
+ if (!file.open(QIODevice::ReadOnly)) {
|
|
|
|
|
+ setError("无法打开文件: " + filePath);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ QByteArray data = file.readAll();
|
|
|
|
|
+ file.close();
|
|
|
|
|
+
|
|
|
|
|
+ QJsonDocument doc = QJsonDocument::fromJson(data);
|
|
|
|
|
+ if (doc.isNull()) {
|
|
|
|
|
+ setError("无效的JSON文件");
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return loadFromJson(doc.object());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool ProcessFlowFactory::saveToFile(const QString& filePath) const
|
|
|
|
|
+{
|
|
|
|
|
+ QFile file(filePath);
|
|
|
|
|
+ if (!file.open(QIODevice::WriteOnly)) {
|
|
|
|
|
+ setError("无法创建文件: " + filePath);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ QJsonObject json = saveToJson();
|
|
|
|
|
+ QJsonDocument doc(json);
|
|
|
|
|
+ file.write(doc.toJson(QJsonDocument::Indented));
|
|
|
|
|
+ file.close();
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|