From f7f8271a1a011ef4774c3fe6249a4401e40834cd Mon Sep 17 00:00:00 2001 From: Spnetic-5 Date: Fri, 15 Mar 2024 21:59:58 +0530 Subject: [PATCH 1/2] Image Processing Operations in Electron --- imagelab_electron/imagelab-blocks.js | 10 ++++++ imagelab_electron/index.html | 7 +++++ imagelab_electron/operations.js | 1 + imagelab_electron/src/controller/main.js | 6 ++++ .../src/operator/miscellaneous/CLAHE.js | 31 +++++++++++++++++++ 5 files changed, 55 insertions(+) create mode 100644 imagelab_electron/src/operator/miscellaneous/CLAHE.js diff --git a/imagelab_electron/imagelab-blocks.js b/imagelab_electron/imagelab-blocks.js index 02ca649..feb0cad 100644 --- a/imagelab_electron/imagelab-blocks.js +++ b/imagelab_electron/imagelab-blocks.js @@ -931,6 +931,16 @@ Blockly.defineBlocksWithJsonArray([ "Thresholding is a method of image segmentation, in general it is used to create binary images. You can change the threshold value from the properties as well as you can assign a max value.", helpUrl: "", }, + { + type: "clahe", + message0: "Apply CLAHE", + previousStatement: null, + nextStatement: null, + colour: 270, + tooltip: + "Contrast Limited Adaptive Histogram Equalization (CLAHE) is used to improve contrast of images", + helpUrl: "", + }, { type: "border_for_all", message0: "with thickness %1", diff --git a/imagelab_electron/index.html b/imagelab_electron/index.html index 84f7e9d..6ead3a6 100644 --- a/imagelab_electron/index.html +++ b/imagelab_electron/index.html @@ -175,6 +175,13 @@ + + + diff --git a/imagelab_electron/operations.js b/imagelab_electron/operations.js index 50764ed..1384490 100644 --- a/imagelab_electron/operations.js +++ b/imagelab_electron/operations.js @@ -25,6 +25,7 @@ const PROCESS_OPERATIONS = { MORPHOLOGICAL: "filtering_morphological", ADAPTIVETHRESHOLDING: "thresholding_adaptivethreshold", SIMPLETHRESHOLDING: "thresholding_applythreshold", + CLAHE: "clahe" }; module.exports = PROCESS_OPERATIONS; diff --git a/imagelab_electron/src/controller/main.js b/imagelab_electron/src/controller/main.js index 385c084..b48890e 100644 --- a/imagelab_electron/src/controller/main.js +++ b/imagelab_electron/src/controller/main.js @@ -25,6 +25,7 @@ const RotateImage = require("../operator/geometric/RotateImage"); const ScaleImage = require("../operator/geometric/ScaleImage"); const AdaptiveThreshold = require("../operator/thresholding/AdaptiveThresholding"); const ApplyThreshold = require("../operator/thresholding/ApplyThreshold"); +const CLAHE = require("../operator/miscellaneous/CLAHE"); class MainController { // This private field is used to store the applied operators in the workspace @@ -244,6 +245,11 @@ class MainController { new ApplyThreshold(PROCESS_OPERATIONS.SIMPLETHRESHOLDING, id) ); break; + case PROCESS_OPERATIONS.CLAHE: + this.#appliedOperators.push( + new CLAHE(PROCESS_OPERATIONS.CLAHE, id) + ); + break; default: break; } diff --git a/imagelab_electron/src/operator/miscellaneous/CLAHE.js b/imagelab_electron/src/operator/miscellaneous/CLAHE.js new file mode 100644 index 0000000..72ab1c0 --- /dev/null +++ b/imagelab_electron/src/operator/miscellaneous/CLAHE.js @@ -0,0 +1,31 @@ +const OpenCvOperator = require("../OpenCvOperator"); + +/** + * This class contains the main logic + * of CLAHE processing of the image + */ +class CLAHE extends OpenCvOperator { + constructor(type, id) { + super(type, id); + } + + /** + * + * @param {Mat Image} image + * @returns + * Computes CLAHE + * to the Processed Mat image + */ + compute(image) { + let equalDst = new this.cv2.Mat(); + let claheDst = new this.cv2.Mat(); + this.cv2.cvtColor(image, image, this.cv2.COLOR_RGBA2GRAY, 0); + this.cv2.equalizeHist(image, equalDst); + let tileGridSize = new this.cv2.Size(8, 8); + let clahe = new this.cv2.CLAHE(40, tileGridSize); + clahe.apply(image, claheDst); + return claheDst; + } +} + +module.exports = CLAHE; From b1f88840d61656020bc14ca7c8aa16394b8643ff Mon Sep 17 00:00:00 2001 From: Spnetic-5 Date: Fri, 15 Mar 2024 22:33:27 +0530 Subject: [PATCH 2/2] Image Processing Operations in Java --- .../com/imagelab/DashboardController.java | 9 +- .../BlurringOperatorController.java | 23 +++ .../controllers/HistogramController.java | 25 ++- .../MiscellaneousOperatorController.java | 23 +++ .../imagelab/operator/histogram/CLAHE.java | 135 +++++++++++++++ .../imagebluring/ApplyBilateralBlur.java | 110 ++++++++++++ .../miscellaneousoperators/Watershed.java | 161 ++++++++++++++++++ .../forms/BilateralBlurPropertiesForm.java | 128 ++++++++++++++ .../view/forms/ClahePropertiesForm.java | 23 +++ .../view/forms/WatershedPropertiesForm.java | 92 ++++++++++ .../src/main/resources/com/imagelab/style.css | 36 ++-- 11 files changed, 750 insertions(+), 15 deletions(-) create mode 100644 imagelab_java/src/main/java/com/imagelab/operator/histogram/CLAHE.java create mode 100644 imagelab_java/src/main/java/com/imagelab/operator/imagebluring/ApplyBilateralBlur.java create mode 100644 imagelab_java/src/main/java/com/imagelab/operator/miscellaneousoperators/Watershed.java create mode 100644 imagelab_java/src/main/java/com/imagelab/view/forms/BilateralBlurPropertiesForm.java create mode 100644 imagelab_java/src/main/java/com/imagelab/view/forms/ClahePropertiesForm.java create mode 100644 imagelab_java/src/main/java/com/imagelab/view/forms/WatershedPropertiesForm.java diff --git a/imagelab_java/src/main/java/com/imagelab/DashboardController.java b/imagelab_java/src/main/java/com/imagelab/DashboardController.java index 6c6deec..f5f869a 100644 --- a/imagelab_java/src/main/java/com/imagelab/DashboardController.java +++ b/imagelab_java/src/main/java/com/imagelab/DashboardController.java @@ -538,7 +538,8 @@ public void initialize(URL url, ResourceBundle resourceBundle) { // Populating blurringOperatorsContainer. BlurringOperatorController.applyBlurEffectElement().element, BlurringOperatorController.applyGaussianEffectElement().element, - BlurringOperatorController.applyMedainBlurEffectElement().element + BlurringOperatorController.applyMedainBlurEffectElement().element, + BlurringOperatorController.applyBilateralEffectElement().element ); filteringOperatorsContainer.setSpacing(15d); @@ -589,7 +590,8 @@ public void initialize(URL url, ResourceBundle resourceBundle) { // Populating sobelDerivationContainer MiscellaneousOperatorController.cannyEdgeDetectionElement().element, MiscellaneousOperatorController.houghLineTransformElement().element, - MiscellaneousOperatorController.histogramEqualizationElement().element + MiscellaneousOperatorController.histogramEqualizationElement().element, + MiscellaneousOperatorController.WatershedAlgorithmElement().element ); contourOperationContainer.setSpacing(15d); contourOperationContainer.setAlignment(Pos.TOP_CENTER); @@ -607,7 +609,8 @@ public void initialize(URL url, ResourceBundle resourceBundle) { histogramOperationContainer.getChildren().addAll( // Populating Histogram operators HistogramController.histogramCalculationElement().element, - HistogramController.templateMatchingElement().element + HistogramController.templateMatchingElement().element, + HistogramController.claheElement().element ); setDashboardToInitialState(); } diff --git a/imagelab_java/src/main/java/com/imagelab/controllers/BlurringOperatorController.java b/imagelab_java/src/main/java/com/imagelab/controllers/BlurringOperatorController.java index ed33d6d..8c41e68 100644 --- a/imagelab_java/src/main/java/com/imagelab/controllers/BlurringOperatorController.java +++ b/imagelab_java/src/main/java/com/imagelab/controllers/BlurringOperatorController.java @@ -1,12 +1,14 @@ package com.imagelab.controllers; import com.imagelab.component.OperatorUIElement; +import com.imagelab.operator.imagebluring.ApplyBilateralBlur; import com.imagelab.operator.imagebluring.ApplyBlurEffect; import com.imagelab.operator.imagebluring.ApplyGaussianBlurEffect; import com.imagelab.operator.imagebluring.ApplyMedianBlurEffect; import com.imagelab.view.AbstractInformationUI; import com.imagelab.view.InformationContainerView; import com.imagelab.view.forms.AbstractPropertiesForm; +import com.imagelab.view.forms.BilateralBlurPropertiesForm; import com.imagelab.view.forms.GaussianBlurPropertiesForm; import com.imagelab.view.forms.MedianBlurPropertiesForm; import com.imagelab.view.forms.SimpleBlurPropertiesForm; @@ -75,4 +77,25 @@ public AbstractPropertiesForm buildPropertiesFormUI() { applyMedianBlurEffect.buildElement(); return applyMedianBlurEffect; } + public static OperatorUIElement applyBilateralEffectElement() { + //applybilateralEffect UI element. + OperatorUIElement applybilateralBlur = new OperatorUIElement() { + @Override + public AbstractInformationUI buildInformationUI() { + return new InformationContainerView(ApplyBilateralBlur + .Information.OPERATOR_INFO.toString()); + } + + @Override + public AbstractPropertiesForm buildPropertiesFormUI() { + return new BilateralBlurPropertiesForm((ApplyBilateralBlur) this.operator); + } + }; + applybilateralBlur.operator = new ApplyBilateralBlur(); + applybilateralBlur.operatorId = ApplyBilateralBlur.class.getCanonicalName(); + applybilateralBlur.operatorName = "APPLY-BILATERAL-BLUR"; + applybilateralBlur.elementStyleId = "applyBilateralBlur"; + applybilateralBlur.buildElement(); + return applybilateralBlur; + } } diff --git a/imagelab_java/src/main/java/com/imagelab/controllers/HistogramController.java b/imagelab_java/src/main/java/com/imagelab/controllers/HistogramController.java index add5663..3191892 100644 --- a/imagelab_java/src/main/java/com/imagelab/controllers/HistogramController.java +++ b/imagelab_java/src/main/java/com/imagelab/controllers/HistogramController.java @@ -1,14 +1,14 @@ package com.imagelab.controllers; import com.imagelab.component.OperatorUIElement; +import com.imagelab.operator.histogram.CLAHE; import com.imagelab.operator.histogram.HistogramCalculation; import com.imagelab.operator.histogram.TemplateMatching; -import com.imagelab.operator.transformation.LaplacianTransformation; import com.imagelab.view.AbstractInformationUI; import com.imagelab.view.InformationContainerView; import com.imagelab.view.forms.AbstractPropertiesForm; +import com.imagelab.view.forms.ClahePropertiesForm; import com.imagelab.view.forms.HistogramCalculationPropertiesForm; -import com.imagelab.view.forms.LaplacianTransformationPropertiesForm; import com.imagelab.view.forms.TemplateMatchingPropertiesForm; public class HistogramController { @@ -54,4 +54,25 @@ public AbstractPropertiesForm buildPropertiesFormUI() { templateMatching.buildElement(); return templateMatching; } + public static OperatorUIElement claheElement() { + //CLAHE Controller Function + OperatorUIElement claheElement = new OperatorUIElement() { + @Override + public AbstractInformationUI buildInformationUI() { + return new InformationContainerView(CLAHE + .Information.OPERATOR_INFO.toString()); + } + + @Override + public AbstractPropertiesForm buildPropertiesFormUI() { + return new ClahePropertiesForm((CLAHE) this.operator); + } + }; + claheElement.operator = new CLAHE(); + claheElement.operatorId = CLAHE.class.getCanonicalName(); + claheElement.operatorName = "CLAHE"; + claheElement.elementStyleId = "clahe"; + claheElement.buildElement(); + return claheElement; + } } diff --git a/imagelab_java/src/main/java/com/imagelab/controllers/MiscellaneousOperatorController.java b/imagelab_java/src/main/java/com/imagelab/controllers/MiscellaneousOperatorController.java index fcef284..5070371 100644 --- a/imagelab_java/src/main/java/com/imagelab/controllers/MiscellaneousOperatorController.java +++ b/imagelab_java/src/main/java/com/imagelab/controllers/MiscellaneousOperatorController.java @@ -4,12 +4,14 @@ import com.imagelab.operator.miscellaneousoperators.CannyEdgeDetection; import com.imagelab.operator.miscellaneousoperators.HistogramEqualization; import com.imagelab.operator.miscellaneousoperators.HoughLineTransform; +import com.imagelab.operator.miscellaneousoperators.Watershed; import com.imagelab.view.AbstractInformationUI; import com.imagelab.view.InformationContainerView; import com.imagelab.view.forms.AbstractPropertiesForm; import com.imagelab.view.forms.CannyEdgeDetectionPropertiesForm; import com.imagelab.view.forms.HistogramEqualizationPropertiesForm; import com.imagelab.view.forms.HoughLineTransformPropertiesForm; +import com.imagelab.view.forms.WatershedPropertiesForm; public class MiscellaneousOperatorController { @@ -76,4 +78,25 @@ public AbstractPropertiesForm buildPropertiesFormUI() { histogramEqualization.buildElement(); return histogramEqualization; } + public static OperatorUIElement WatershedAlgorithmElement() { + //Histogram Equalization transform properties form. + OperatorUIElement watershedAlgorithmElement = new OperatorUIElement() { + @Override + public AbstractInformationUI buildInformationUI() { + return new InformationContainerView(Watershed + .Information.OPERATOR_INFO.toString()); + } + + @Override + public AbstractPropertiesForm buildPropertiesFormUI() { + return new WatershedPropertiesForm((Watershed) this.operator); + } + }; + watershedAlgorithmElement.operator = new Watershed(); + watershedAlgorithmElement.operatorId = Watershed.class.getCanonicalName(); + watershedAlgorithmElement.operatorName = "WATERSHED"; + watershedAlgorithmElement.elementStyleId = "watershed"; + watershedAlgorithmElement.buildElement(); + return watershedAlgorithmElement; + } } diff --git a/imagelab_java/src/main/java/com/imagelab/operator/histogram/CLAHE.java b/imagelab_java/src/main/java/com/imagelab/operator/histogram/CLAHE.java new file mode 100644 index 0000000..df02828 --- /dev/null +++ b/imagelab_java/src/main/java/com/imagelab/operator/histogram/CLAHE.java @@ -0,0 +1,135 @@ +package com.imagelab.operator.histogram; + +import com.imagelab.operator.OpenCVOperator; +import com.imagelab.operator.basic.ReadImage; +import com.imagelab.operator.basic.WriteImage; +import com.imagelab.operator.filtering.ApplyBilateralFilter; +import com.imagelab.operator.filtering.ApplyBoxFilter; +import com.imagelab.operator.filtering.ApplyDilation; +import com.imagelab.operator.filtering.ApplyFilter2D; +import com.imagelab.operator.filtering.ApplyImagePyramid; +import com.imagelab.operator.filtering.ApplyImagePyramidDown; +import com.imagelab.operator.filtering.ApplyMorphological; +import com.imagelab.operator.filtering.ApplySQRBoxFilter; +import com.imagelab.operator.geotransformation.ColorMaps; +import com.imagelab.operator.geotransformation.ImageAffine; +import com.imagelab.operator.geotransformation.ImageReflection; +import com.imagelab.operator.geotransformation.RotateImage; +import com.imagelab.operator.geotransformation.ScaleImage; +import com.imagelab.operator.imagebluring.ApplyBlurEffect; +import com.imagelab.operator.imagebluring.ApplyGaussianBlurEffect; +import com.imagelab.operator.imagebluring.ApplyMedianBlurEffect; +import com.imagelab.operator.imageconversion.ColoredImageToBinary; +import com.imagelab.operator.imageconversion.ConvertToGrayscale; +import org.opencv.core.Core; +import org.opencv.core.Mat; +import org.opencv.imgproc.Imgproc; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** + * Contrast Limited Adaptive Histogram Equalization (CLAHE) operator class which contains + * adding a filter to an image related + * functionalities. + */ +public class CLAHE extends OpenCVOperator { + + /** + * This method contains the logic which validates the applicable + * openCV operations for a particular openCV operator. + * + * @param previous - accepts the previous operator to validate. + * @return - whether the received operator is valid or not. + */ + @Override + public boolean validate(OpenCVOperator previous) { + if (previous == null) { + return false; + } + return allowedOperators().contains(previous.getClass()); + } + + /** + * This method contains the openCV operator related specific logic. + * + * @param image - accepts the mat object processed from the previous steps. + * @return - processed computed Mat obj. + */ + @Override + public Mat compute(Mat image) { + return applyCLAHE(image); + } + + /** + * This method contains the applicable openCV operator for the selected + * openCV operator. + * + * @return - applicable operator. + */ + @Override + public Set> allowedOperators() { + Set> allowed = new HashSet<>(); + allowed.add(ReadImage.class); + allowed.add(WriteImage.class); + allowed.add(ImageReflection.class); + allowed.add(RotateImage.class); + allowed.add(ColorMaps.class); + allowed.add(ImageAffine.class); + allowed.add(ScaleImage.class); + allowed.add(ColoredImageToBinary.class); + allowed.add(ConvertToGrayscale.class); + allowed.add(ApplyBlurEffect.class); + allowed.add(ApplyGaussianBlurEffect.class); + allowed.add(ApplyMedianBlurEffect.class); + allowed.add(ApplyBoxFilter.class); + allowed.add(ApplyBilateralFilter.class); + allowed.add(ApplyImagePyramidDown.class); + allowed.add(ApplyImagePyramid.class); + allowed.add(ApplyDilation.class); + allowed.add(ApplyFilter2D.class); + allowed.add(ApplySQRBoxFilter.class); + allowed.add(ApplyMorphological.class); + return allowed; + } + + /** + * This method contains applying clahe filter related + * opencv logic. + * + * @param imageFile - source mat image. + * @return - clahe applied mat image. + */ + private Mat applyCLAHE(Mat imageFile) { + // Creating an empty matrix to store the result + Mat image = new Mat(); + + List channels = new LinkedList(); + Core.split(imageFile, channels); + org.opencv.imgproc.CLAHE clahe = Imgproc.createCLAHE(); + clahe.apply(channels.get(0), image); + + return image; + } + + /** + * Information related to the CLAHE operator. + */ + public enum Information { + /** + * Operator information in string format. + */ + OPERATOR_INFO { + /** + * @return - Operator information and name of the operator. + */ + public String toString() { + return "CLAHE\n\nThis operations allows" + + "you to apply Contrast Limited Adaptive Histogram Equalization" + + "to your image"; + } + } + } +} diff --git a/imagelab_java/src/main/java/com/imagelab/operator/imagebluring/ApplyBilateralBlur.java b/imagelab_java/src/main/java/com/imagelab/operator/imagebluring/ApplyBilateralBlur.java new file mode 100644 index 0000000..ef61683 --- /dev/null +++ b/imagelab_java/src/main/java/com/imagelab/operator/imagebluring/ApplyBilateralBlur.java @@ -0,0 +1,110 @@ +package com.imagelab.operator.imagebluring; + +import com.imagelab.operator.OpenCVOperator; +import com.imagelab.operator.basic.ReadImage; +import com.imagelab.operator.basic.WriteImage; +import com.imagelab.operator.geotransformation.ColorMaps; +import com.imagelab.operator.geotransformation.ImageAffine; +import com.imagelab.operator.geotransformation.ImageReflection; +import com.imagelab.operator.geotransformation.RotateImage; +import com.imagelab.operator.geotransformation.ScaleImage; +import com.imagelab.operator.imageconversion.ColoredImageToBinary; +import com.imagelab.operator.imageconversion.ConvertToGrayscale; +import org.opencv.core.Mat; +import org.opencv.imgproc.Imgproc; + +import java.util.HashSet; +import java.util.Set; + +/** + * Operator class which contains the logic related to the + * applying bilateral blur effects to an image UI element. + */ +public class ApplyBilateralBlur extends OpenCVOperator { + // properties of bilateral blur effect. + private int diameter = 15; + private int sigmaColor = 80; + private int sigmaSpace = 80; + + @Override + public boolean validate(OpenCVOperator previous) { + if (previous == null) { + return false; + } + return allowedOperators().contains(previous.getClass()); + } + + + @Override + public Mat compute(Mat image) { + return applyBilateralBlurEffect(image, getDiameter(), getsigmaColor(), getsigmaSpace()); + } + + @Override + public Set> allowedOperators() { + Set> allowed = new HashSet<>(); + allowed.add(ReadImage.class); + allowed.add(RotateImage.class); + allowed.add(ColorMaps.class); + allowed.add(ScaleImage.class); + allowed.add(ImageAffine.class); + allowed.add(ImageReflection.class); + allowed.add(WriteImage.class); + allowed.add(ColoredImageToBinary.class); + allowed.add(ConvertToGrayscale.class); + allowed.add(ApplyBlurEffect.class); + allowed.add(ApplyGaussianBlurEffect.class); + allowed.add(ApplyMedianBlurEffect.class); + allowed.add(ApplyBilateralBlur.class); + return allowed; + } + + private Mat applyBilateralBlurEffect(Mat imageFile, + int diameter, int sigmaSpace, int sigmaColor) { + Mat image = new Mat(); + Imgproc.bilateralFilter(imageFile, image, diameter, sigmaColor, sigmaSpace); + return image; + } + + public int getDiameter() { + return diameter; + } + + public void setDiameter(int diameter) { + this.diameter = diameter; + } + + public int getsigmaColor() { + return sigmaColor; + } + + public void setsigmaColor(int sigmaColor) { + this.sigmaColor = sigmaColor; + } + + public int getsigmaSpace() { + return sigmaSpace; + } + + public void setsigmaSpace(int sigmaSpace) { + this.sigmaSpace = sigmaSpace; + } + + /** + * Information related to the ApplyBilateralBlurEffect operator. + */ + public enum Information { + /** + * Operator information in string format. + */ + OPERATOR_INFO { + /** + * @return - Operator information and name of the operator. + */ + public String toString() { + return "Apply bilateral blur\n\nThis operations allows" + + " you to apply bilateral blur effects to your image."; + } + } + } +} diff --git a/imagelab_java/src/main/java/com/imagelab/operator/miscellaneousoperators/Watershed.java b/imagelab_java/src/main/java/com/imagelab/operator/miscellaneousoperators/Watershed.java new file mode 100644 index 0000000..6e96b22 --- /dev/null +++ b/imagelab_java/src/main/java/com/imagelab/operator/miscellaneousoperators/Watershed.java @@ -0,0 +1,161 @@ +package com.imagelab.operator.miscellaneousoperators; + +import java.util.HashSet; +import java.util.Set; + +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.Point; +import org.opencv.core.Size; +import org.opencv.imgproc.Imgproc; + +import com.imagelab.operator.OpenCVOperator; +import com.imagelab.operator.basic.ReadImage; +import com.imagelab.operator.basic.WriteImage; +import com.imagelab.operator.drawing.DrawCircle; +import com.imagelab.operator.drawing.DrawLine; +import com.imagelab.operator.filtering.ApplyBoxFilter; +import com.imagelab.operator.filtering.ApplyErosion; +import com.imagelab.operator.filtering.ApplyImagePyramid; +import com.imagelab.operator.filtering.ApplyImagePyramidDown; +import com.imagelab.operator.geotransformation.ImageAffine; +import com.imagelab.operator.geotransformation.ImageReflection; +import com.imagelab.operator.geotransformation.RotateImage; +import com.imagelab.operator.imagebluring.ApplyBlurEffect; +import com.imagelab.operator.imagebluring.ApplyGaussianBlurEffect; +import com.imagelab.operator.imagebluring.ApplyMedianBlurEffect; +import com.imagelab.operator.imageconversion.ColoredImageToBinary; +import com.imagelab.operator.imageconversion.ConvertToGrayscale; + + +public class Watershed extends OpenCVOperator{ + + private int lowThreshold = 60; + + private int highThreshold = 180; + + @Override + public boolean validate(OpenCVOperator previous) { + if (previous == null) { + return false; + } + return allowedOperators().contains(previous.getClass()); + } + + @Override + public Mat compute(Mat image) { + System.out.println("Applied Watershed Algorithm"); + return watershedAlgorithm(image,getLowThreshold(),getHighThresold()); + } + + private Mat watershedAlgorithm(Mat src,int low,int high){ + // Creating an empty matrix to store the result -> store the edges + Mat bg = new Mat(); + Mat fg = new Mat(); + Mat markers = new Mat(); + Mat marker_tempo = new Mat(); + + // Empty matrix for gry image + Mat gray = new Mat(); + // Kernel for morphological operations + Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size((2*2) + 1, (2*2)+1)); + + // Converting the image from color to Gray + Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY); + + // Thresholding the image + Imgproc.threshold(gray, gray, low, high, Imgproc.THRESH_OTSU); + + // Open + Imgproc.morphologyEx(gray, gray, Imgproc.MORPH_OPEN, kernel); + + // Background + Imgproc.dilate(gray, bg, kernel); + Imgproc.threshold(bg,bg,1, 128,Imgproc.THRESH_BINARY_INV); + + // Foreground + Imgproc.erode(gray,fg,new Mat(),new Point(-1,-1),2); + + Core.add(fg, bg, markers); + + markers.convertTo(marker_tempo, CvType.CV_32S); + + // Watershed Algorithm + Imgproc.watershed(src, marker_tempo); + + return marker_tempo; + } + /** + * Type integer + * @return + */ + public int getLowThreshold() { + return this.lowThreshold; + } + /** + * To set the low threshold of the output image. + * + * @return - low threshold + */ + public void setLowThreshold(int low) { + this.lowThreshold = low; + } + /** + * To get the high threshold of the output image. + * + * @return - high threshold + */ + public int getHighThresold() { + return this.highThreshold; + } + + /** + * To set the high threshold of the output image. + * + * @param highThreshold -high threshold + */ + public void setHighThresold(int high) { + this.highThreshold = high; + } + + @Override + public Set> allowedOperators() { + Set> allowed = new HashSet<>(); + allowed.add(ReadImage.class); + allowed.add(RotateImage.class); + allowed.add(WriteImage.class); + allowed.add(DrawLine.class); + allowed.add(DrawCircle.class); + allowed.add(ColoredImageToBinary.class); + allowed.add(ConvertToGrayscale.class); + allowed.add(ApplyBlurEffect.class); + allowed.add(ApplyGaussianBlurEffect.class); + allowed.add(ApplyMedianBlurEffect.class); + allowed.add(ApplyBoxFilter.class); + allowed.add(ApplyImagePyramidDown.class); + allowed.add(ApplyImagePyramid.class); + allowed.add(ApplyErosion.class); + allowed.add(ImageAffine.class); + allowed.add(ImageReflection.class); + return allowed; + } + public enum Information { + /** + * Operator information in string format. + */ + OPERATOR_INFO { + /** + * @return - Operator information and name + * of the operator. + */ + public String toString() { + return "Watershed\n\n used to detect the edges in an image." + + " It accepts a RGB image as input and it uses a multistage algorithm." + + " You can perform this operation on an image using the Watershed() function in OpenCV."; + } + } + } + + +} diff --git a/imagelab_java/src/main/java/com/imagelab/view/forms/BilateralBlurPropertiesForm.java b/imagelab_java/src/main/java/com/imagelab/view/forms/BilateralBlurPropertiesForm.java new file mode 100644 index 0000000..e7d0e75 --- /dev/null +++ b/imagelab_java/src/main/java/com/imagelab/view/forms/BilateralBlurPropertiesForm.java @@ -0,0 +1,128 @@ +package com.imagelab.view.forms; + +import com.imagelab.operator.imagebluring.ApplyBilateralBlur; + +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; + +/** + * Applying bilateral blur effects operation related + * UI properties form. + */ +public class BilateralBlurPropertiesForm extends AbstractPropertiesForm { + /** + * Builds the BilateralBlurPropertiesForm. + * + * @param operator - operator which requires this properties form. + */ + public BilateralBlurPropertiesForm(ApplyBilateralBlur operator) { + //Bilateral blur tittle container. + PropertiesFormTitleContainer bilateralBlurTitleContainer; + bilateralBlurTitleContainer = new PropertiesFormTitleContainer("Bilateral Blur Properties"); + + //Diameter + VBox diameterContainer = new VBox(); + diameterContainer.setPrefWidth(205.0); + diameterContainer.setSpacing(10); + Label lblDiameter = new Label("Diameter"); + TextField diameterTextField = new TextField(String.valueOf(15.0)); + diameterTextField.setPrefSize(205.0, 27.0); + Label lblErrDiameter = new Label("Error"); + lblErrDiameter.setTextFill(Color.web("#f20028")); + lblErrDiameter.setVisible(false); + //Listener to capture text change. + diameterTextField.textProperty().addListener((observable, oldValue, newValue) -> { + int newVal; + if ("".equals(newValue)) { + newVal = 0; + lblErrDiameter.setVisible(true); + lblErrDiameter.setText("Enter a value"); + } else { + try{ + newVal = Integer.parseInt(newValue); + lblErrDiameter.setVisible(false); + operator.setDiameter(newVal); + } catch(Exception e) { + lblErrDiameter.setVisible(true); + lblErrDiameter.setText("Enter an Integer"); + } + } + }); + diameterContainer.getChildren().addAll(lblDiameter, diameterTextField, lblErrDiameter); + + //Sigma Space + VBox sigmaSpaceContainer = new VBox(); + sigmaSpaceContainer.setPrefWidth(205.0); + sigmaSpaceContainer.setSpacing(10); + Label lblSigmaSpace = new Label("Sigma Space"); + TextField sigmaSpaceTextField = new TextField(String.valueOf(80)); + sigmaSpaceTextField.setPrefSize(205.0, 27.0); + Label lblSigmaSpaceErr = new Label("Error"); + lblSigmaSpaceErr.setTextFill(Color.web("#f20028")); + lblSigmaSpaceErr.setVisible(false); + //Listener to capture text change. + sigmaSpaceTextField.textProperty().addListener((observable, oldValue, newValue) -> { + int newVal; + if ("".equals(newValue)) { + newVal = 0; + lblSigmaSpaceErr.setVisible(true); + lblSigmaSpaceErr.setText("Enter a value"); + } else { + try{ + newVal = Integer.parseInt(newValue); + lblSigmaSpaceErr.setVisible(false); + operator.setsigmaSpace(newVal); + } catch(Exception e) { + lblSigmaSpaceErr.setVisible(true); + lblSigmaSpaceErr.setText("Enter an Integer"); + } + } + }); + sigmaSpaceContainer.getChildren().addAll(lblSigmaSpace, sigmaSpaceTextField, lblSigmaSpaceErr); + + //Sigma Colour + VBox sigmaColorContainer = new VBox(); + sigmaColorContainer.setPrefWidth(205.0); + sigmaColorContainer.setSpacing(10); + Label lblSigmaColor = new Label("Sigma Colour"); + TextField sigmaColorTextField = new TextField(String.valueOf(80)); + sigmaColorTextField.setPrefSize(205.0, 27.0); + Label lblSigmaColorErr = new Label("Error"); + lblSigmaColorErr.setTextFill(Color.web("#f20028")); + lblSigmaColorErr.setVisible(false); + //Listener to capture text change. + sigmaColorTextField.textProperty().addListener((observable, oldValue, newValue) -> { + int newVal; + if ("".equals(newValue)) { + newVal = 0; + lblSigmaColorErr.setVisible(true); + lblSigmaColorErr.setText("Enter a value"); + } else { + try{ + newVal = Integer.parseInt(newValue); + lblSigmaColorErr.setVisible(false); + operator.setsigmaColor(newVal); + } catch(Exception e) { + lblSigmaColorErr.setVisible(true); + lblSigmaColorErr.setText("Enter an Integer"); + } + } + }); + sigmaColorContainer.getChildren().addAll(lblSigmaColor, sigmaColorTextField, lblSigmaColorErr); + + VBox bilateralBlurPropertiesContainer = new VBox(); + bilateralBlurPropertiesContainer.setPrefSize(205, 47); + bilateralBlurPropertiesContainer.setSpacing(20); + bilateralBlurPropertiesContainer.setLayoutX(14); + bilateralBlurPropertiesContainer.setLayoutY(14); + bilateralBlurPropertiesContainer.getChildren().addAll( + bilateralBlurTitleContainer, + diameterContainer, + sigmaSpaceContainer, + sigmaColorContainer + ); + getChildren().addAll(bilateralBlurPropertiesContainer); + } +} diff --git a/imagelab_java/src/main/java/com/imagelab/view/forms/ClahePropertiesForm.java b/imagelab_java/src/main/java/com/imagelab/view/forms/ClahePropertiesForm.java new file mode 100644 index 0000000..56cfec1 --- /dev/null +++ b/imagelab_java/src/main/java/com/imagelab/view/forms/ClahePropertiesForm.java @@ -0,0 +1,23 @@ +package com.imagelab.view.forms; + +import com.imagelab.operator.histogram.CLAHE; + +import javafx.scene.layout.VBox; + +public class ClahePropertiesForm extends AbstractPropertiesForm { + public ClahePropertiesForm(CLAHE operator) { + //Clahe title container. + PropertiesFormTitleContainer clahePropertiesTitleContainer; + clahePropertiesTitleContainer = new PropertiesFormTitleContainer("CLAHE"); + + VBox clahePropertiesContainer = new VBox(); + clahePropertiesContainer.setPrefSize(205, 47); + clahePropertiesContainer.setSpacing(20); + clahePropertiesContainer.setLayoutX(14); + clahePropertiesContainer.setLayoutY(14); + clahePropertiesContainer.getChildren().addAll( + clahePropertiesTitleContainer + ); + getChildren().addAll(clahePropertiesContainer); + } +} diff --git a/imagelab_java/src/main/java/com/imagelab/view/forms/WatershedPropertiesForm.java b/imagelab_java/src/main/java/com/imagelab/view/forms/WatershedPropertiesForm.java new file mode 100644 index 0000000..9132f77 --- /dev/null +++ b/imagelab_java/src/main/java/com/imagelab/view/forms/WatershedPropertiesForm.java @@ -0,0 +1,92 @@ +package com.imagelab.view.forms; + +import com.imagelab.operator.miscellaneousoperators.Watershed; + +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.scene.control.Label; +import javafx.scene.control.Slider; +import javafx.scene.layout.VBox; + +public class WatershedPropertiesForm extends AbstractPropertiesForm { + public WatershedPropertiesForm(Watershed operator) { + // title container + PropertiesFormTitleContainer WatershedTitleContainer; + WatershedTitleContainer = new PropertiesFormTitleContainer("Watershed"); + + // Space container + VBox spaceContainer = new VBox(); + spaceContainer.setPrefWidth(205.0); + spaceContainer.setSpacing(10); + Label lblSpaceOne = new Label(""); + Label lblSpaceTwo = new Label(""); + spaceContainer.getChildren().addAll(lblSpaceOne, lblSpaceTwo); + + // Thresold low + VBox lowThresholdSliderContainer = new VBox(); + lowThresholdSliderContainer.setPrefWidth(205.0); + lowThresholdSliderContainer.setSpacing(10); + Label lblLowThresoldSlider = new Label("Low Thresold :"); + + Slider lowThresoldSlider = new Slider(); + lowThresoldSlider.setMin(0); + lowThresoldSlider.setMax(300); + lowThresoldSlider.setValue(60); + // enable TickLabels and Tick Marks + lowThresoldSlider.setShowTickLabels(true); + lowThresoldSlider.setShowTickMarks(true); + lowThresoldSlider.setBlockIncrement(50); + // Adding Listener to value property. + lowThresoldSlider.valueProperty().addListener(new ChangeListener() { + + @Override + public void changed(ObservableValue observable, Number oldValue, Number newValue) { + // TODO Auto-generated method stub + lblLowThresoldSlider.setText(String.format("Low Thresold : %d units", (int)newValue.doubleValue())); + operator.setLowThreshold((int)newValue.doubleValue()); + } + + }); + lowThresholdSliderContainer.getChildren().addAll(lblLowThresoldSlider, lowThresoldSlider); + + // Thresold high + VBox highThresholdSliderContainer = new VBox(); + highThresholdSliderContainer.setPrefWidth(205.0); + highThresholdSliderContainer.setSpacing(10); + Label lblHighThresoldSlider = new Label("High Thresold :"); + + Slider highThresoldSlider = new Slider(); + highThresoldSlider.setMin(0); + highThresoldSlider.setMax(300); + highThresoldSlider.setValue(60); + // enable TickLabels and Tick Marks + highThresoldSlider.setShowTickLabels(true); + highThresoldSlider.setShowTickMarks(true); + highThresoldSlider.setBlockIncrement(50); + // Adding Listener to value property. + highThresoldSlider.valueProperty().addListener(new ChangeListener() { + + @Override + public void changed(ObservableValue observable, Number oldValue, Number newValue) { + // TODO Auto-generated method stub + lblHighThresoldSlider.setText(String.format("High Thresold : %d units", (int)newValue.doubleValue())); + operator.setHighThresold((int)newValue.doubleValue()); + } + + }); + highThresholdSliderContainer.getChildren().addAll(lblHighThresoldSlider, highThresoldSlider); + + VBox watershedContainer = new VBox(); + watershedContainer.setPrefSize(205, 47); + watershedContainer.setSpacing(20); + watershedContainer.setLayoutX(14); + watershedContainer.setLayoutY(14); + watershedContainer.getChildren().addAll( + WatershedTitleContainer, + lowThresholdSliderContainer, + highThresholdSliderContainer + ); + getChildren().addAll(watershedContainer); + + } +} diff --git a/imagelab_java/src/main/resources/com/imagelab/style.css b/imagelab_java/src/main/resources/com/imagelab/style.css index 2738a76..4420165 100644 --- a/imagelab_java/src/main/resources/com/imagelab/style.css +++ b/imagelab_java/src/main/resources/com/imagelab/style.css @@ -133,6 +133,13 @@ -fx-text-fill: white; } +/*Apply bilateral blur effects + to an image UI element*/ + #applyBilateralBlur { + -fx-background-color: #1e301e; + -fx-text-fill: white; +} + /*Apply box filter effects to an image UI element*/ #applyBoxFilter { @@ -245,6 +252,11 @@ -fx-background-color: #432775; -fx-text-fill: white; } +/*Watershed styles */ +#watershed{ + -fx-background-color: #1d0d3a; + -fx-text-fill: white; +} /** * Find Contours UI element styles */ @@ -255,10 +267,10 @@ /** * Bounding Box For Contours UI element styles */ - #boundBoxContours{ +#boundBoxContours{ -fx-background-color: #056378; -fx-text-fill: white; - } +} /** * Histogram calculation */ #calHist{ @@ -267,19 +279,23 @@ } /** * Image Moments UI element styles */ - #imageMoments{ +#imageMoments{ -fx-background-color: #0C4956; -fx-text-fill: white; - } - /** +} +/** * Convex Hull UI element styles */ - #convexHull{ +#convexHull{ -fx-background-color: #0D5C84; -fx-text-fill: white; - } - /* +} +/* * Template Matching element styles */ - #templateMatch{ +#templateMatch{ -fx-background-color: #1C5AB9; -fx-text-fill: white; - } \ No newline at end of file +} +#clahe{ + -fx-background-color: #142f57; + -fx-text-fill: white; +} \ No newline at end of file