|
|
@@ -0,0 +1,373 @@
|
|
|
+#include "algorithm.h"
|
|
|
+#include "algorithmregistry.h"
|
|
|
+
|
|
|
+
|
|
|
+CannyEdge::CannyEdge() {
|
|
|
+ cannyMeta.name = "Canny Edge Detection";
|
|
|
+ cannyMeta.addParam("Threshold 1", "double", 50.0, 0.0, 255.0);
|
|
|
+ cannyMeta.addParam("Threshold 2", "double", 150.0, 0.0, 255.0);
|
|
|
+ cannyMeta.addParam("Aperture Size", "int", 3, 1, 7);
|
|
|
+ cannyMeta.addParam("L2 Gradient", "bool", false, 0.0, 1.0);
|
|
|
+}
|
|
|
+
|
|
|
+void CannyEdge::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+ // Get parameters from cannyMeta
|
|
|
+ double threshold1 = 50.0;
|
|
|
+ double threshold2 = 150.0;
|
|
|
+ int apertureSize = 3;
|
|
|
+ bool l2gradient = false;
|
|
|
+
|
|
|
+ for (const auto& param : cannyMeta.params) {
|
|
|
+ if (param.name == "Threshold 1") threshold1 = param.value.toDouble();
|
|
|
+ if (param.name == "Threshold 2") threshold2 = param.value.toDouble();
|
|
|
+ if (param.name == "Aperture Size") apertureSize = param.value.toInt();
|
|
|
+ if (param.name == "L2 Gradient") l2gradient = param.value.toBool();
|
|
|
+ }
|
|
|
+
|
|
|
+ cv::Mat gray;
|
|
|
+ if (image.channels() == 3) {
|
|
|
+ cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
|
|
|
+ } else {
|
|
|
+ gray = image;
|
|
|
+ }
|
|
|
+
|
|
|
+ cv::Canny(gray, image, threshold1, threshold2, apertureSize, l2gradient);
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+
|
|
|
+ // Count edges (simple implementation)
|
|
|
+ runtimeParams.edgeCount = cv::countNonZero(image);
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta CannyEdge::getParams() {
|
|
|
+ return cannyMeta;
|
|
|
+}
|
|
|
+
|
|
|
+void CannyEdge::setParams(const AlgorithmMeta& params) {
|
|
|
+ cannyMeta = params;
|
|
|
+}
|
|
|
+
|
|
|
+Thresholding::Thresholding() {
|
|
|
+ AlgoritName = "Thresholding";
|
|
|
+ Thresh = 127;
|
|
|
+ MaxVal = 255;
|
|
|
+ Type = 0;
|
|
|
+}
|
|
|
+
|
|
|
+void Thresholding::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+
|
|
|
+ // Convert to grayscale image
|
|
|
+ cv::Mat gray;
|
|
|
+ if (image.channels() == 3) {
|
|
|
+ cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
|
|
|
+ } else {
|
|
|
+ gray = image;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Execute thresholding
|
|
|
+ cv::threshold(gray, image, Thresh, MaxVal, Type);
|
|
|
+ // Count white pixels
|
|
|
+ runtimeParams.whitePixelCount = cv::countNonZero(image);
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta Thresholding::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ p.addParam("Threshold", "int", Thresh, 0, 255);
|
|
|
+ p.addParam("Max Value", "int", MaxVal, 0, 255);
|
|
|
+ p.addParam("Threshold Type", "int", Type, 0, 4);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void Thresholding::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+ for (auto& param : params.params) {
|
|
|
+ if (param.name == "Threshold") Thresh = param.value.toInt();
|
|
|
+ if (param.name == "Max Value") MaxVal = param.value.toInt();
|
|
|
+ if (param.name == "Threshold Type") Type = param.value.toInt();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+GaussianBlur::GaussianBlur() {
|
|
|
+ AlgoritName = "Gaussian Blur";
|
|
|
+ KernelSize = 5;
|
|
|
+ SigmaX = 1.5;
|
|
|
+ SigmaY = 0.0;
|
|
|
+}
|
|
|
+
|
|
|
+void GaussianBlur::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+ // Ensure kernel size is odd
|
|
|
+ int ksize = KernelSize;
|
|
|
+ if (ksize % 2 == 0) {
|
|
|
+ ksize++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Execute Gaussian blur
|
|
|
+ cv::GaussianBlur(image, image, cv::Size(ksize, ksize), SigmaX, SigmaY);
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta GaussianBlur::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ p.addParam("Kernel Size", "int", KernelSize, 1, 31);
|
|
|
+ p.addParam("Sigma X", "double", SigmaX, 0.0, 10.0);
|
|
|
+ p.addParam("Sigma Y", "double", SigmaY, 0.0, 10.0);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void GaussianBlur::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+ for (auto& param : params.params) {
|
|
|
+ if (param.name == "Kernel Size") KernelSize = param.value.toInt();
|
|
|
+ if (param.name == "Sigma X") SigmaX = param.value.toDouble();
|
|
|
+ if (param.name == "Sigma Y") SigmaY = param.value.toDouble();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+MedianBlur::MedianBlur() {
|
|
|
+ AlgoritName = "Median Blur";
|
|
|
+ KernelSize = 5;
|
|
|
+}
|
|
|
+
|
|
|
+void MedianBlur::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+ // Ensure kernel size is odd
|
|
|
+ int ksize = KernelSize;
|
|
|
+ if (ksize % 2 == 0) {
|
|
|
+ ksize++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Execute median blur
|
|
|
+ cv::medianBlur(image, image, ksize);
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta MedianBlur::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ p.addParam("Kernel Size", "int", KernelSize, 1, 31);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void MedianBlur::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+ for (auto& param : params.params) {
|
|
|
+ if (param.name == "Kernel Size") KernelSize = param.value.toInt();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Dilate::Dilate() {
|
|
|
+ AlgoritName = "Dilate";
|
|
|
+ KernerSize = 3;
|
|
|
+ Iterations = 1;
|
|
|
+}
|
|
|
+
|
|
|
+void Dilate::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+ // Create structuring element
|
|
|
+ cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(KernerSize, KernerSize));
|
|
|
+
|
|
|
+ // Execute dilation
|
|
|
+ cv::dilate(image, image, kernel, cv::Point(-1, -1), Iterations);
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta Dilate::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ p.addParam("Kernel Size", "int", KernerSize, 0, 100);
|
|
|
+ p.addParam("Iterations", "int", Iterations, 0, 100);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void Dilate::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+ for (auto& param : params.params) {
|
|
|
+ if (param.name == "Kernel Size") KernerSize = param.value.toInt();
|
|
|
+ if (param.name == "Iterations") Iterations = param.value.toInt();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Erode::Erode() {
|
|
|
+ AlgoritName = "Erode";
|
|
|
+ KernerSize = 3;
|
|
|
+ Iterations = 1;
|
|
|
+}
|
|
|
+
|
|
|
+void Erode::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+ // Create structuring element
|
|
|
+ cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(KernerSize, KernerSize));
|
|
|
+
|
|
|
+ // Execute erosion
|
|
|
+ cv::erode(image, image, kernel, cv::Point(-1, -1), Iterations);
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta Erode::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ p.addParam("Kernel Size", "int", KernerSize, 0, 100);
|
|
|
+ p.addParam("Iterations", "int", Iterations, 0, 100);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void Erode::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+ for (auto& param : params.params) {
|
|
|
+ if (param.name == "Kernel Size") KernerSize = param.value.toInt();
|
|
|
+ if (param.name == "Iterations") Iterations = param.value.toInt();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Grayscale::Grayscale() {
|
|
|
+ AlgoritName = "Grayscale";
|
|
|
+}
|
|
|
+
|
|
|
+void Grayscale::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+ // Execute grayscale conversion
|
|
|
+ if (image.channels() == 3) {
|
|
|
+ cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta Grayscale::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void Grayscale::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+}
|
|
|
+
|
|
|
+HistogramEqualization::HistogramEqualization() {
|
|
|
+ AlgoritName = "Histogram Equalization";
|
|
|
+}
|
|
|
+
|
|
|
+void HistogramEqualization::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+ // Convert to grayscale image
|
|
|
+ cv::Mat gray;
|
|
|
+ if (image.channels() == 3) {
|
|
|
+ cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
|
|
|
+ } else {
|
|
|
+ gray = image;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Execute histogram equalization
|
|
|
+ cv::equalizeHist(gray, image);
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta HistogramEqualization::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void HistogramEqualization::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+}
|
|
|
+
|
|
|
+FindContours::FindContours() {
|
|
|
+ AlgoritName = "Find Contours";
|
|
|
+ Mode = 3; // RETR_TREE
|
|
|
+ Method = 2; // CHAIN_APPROX_SIMPLE
|
|
|
+}
|
|
|
+
|
|
|
+void FindContours::process(cv::Mat image) {
|
|
|
+ // Store input parameters
|
|
|
+ runtimeParams.inputimage = image.clone(); // Store input image
|
|
|
+
|
|
|
+
|
|
|
+ // Convert to grayscale image
|
|
|
+ cv::Mat gray;
|
|
|
+ if (image.channels() == 3) {
|
|
|
+ cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
|
|
|
+ } else {
|
|
|
+ gray = image;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Binarization
|
|
|
+ cv::Mat binary;
|
|
|
+ cv::threshold(gray, binary, 127, 255, cv::THRESH_BINARY);
|
|
|
+
|
|
|
+ // Find contours
|
|
|
+ std::vector<std::vector<cv::Point>> contours;
|
|
|
+ std::vector<cv::Vec4i> hierarchy;
|
|
|
+ cv::findContours(binary, contours, hierarchy, Mode, Method);
|
|
|
+
|
|
|
+ // Draw contours
|
|
|
+ cv::Mat result = cv::Mat::zeros(image.size(), CV_8UC3);
|
|
|
+ cv::drawContours(result, contours, -1, cv::Scalar(0, 255, 0), 2);
|
|
|
+
|
|
|
+ // Convert result back to grayscale if needed
|
|
|
+ if (image.channels() == 1) {
|
|
|
+ cv::cvtColor(result, image, cv::COLOR_BGR2GRAY);
|
|
|
+ } else {
|
|
|
+ image = result;
|
|
|
+ }
|
|
|
+
|
|
|
+ runtimeParams.contourCount = static_cast<int>(contours.size());
|
|
|
+
|
|
|
+ // Store output parameters
|
|
|
+ runtimeParams.outimage = image.clone(); // Store output image
|
|
|
+}
|
|
|
+
|
|
|
+AlgorithmMeta FindContours::getParams() {
|
|
|
+ AlgorithmMeta p;
|
|
|
+ p.name = QString::fromStdString(AlgoritName);
|
|
|
+ p.addParam("Retrieval Mode", "int", Mode, 0, 4);
|
|
|
+ p.addParam("Approx Method", "int", Method, 0, 3);
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void FindContours::setParams(const AlgorithmMeta& params) {
|
|
|
+ AlgoritName = params.name.toStdString();
|
|
|
+ for (auto& param : params.params) {
|
|
|
+ if (param.name == "Retrieval Mode") Mode = param.value.toInt();
|
|
|
+ if (param.name == "Approx Method") Method = param.value.toInt();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|