Java tutorial
/* * Copyright (c) 2017 Titan Robotics Club (http://www.titanrobotics.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package samples; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfKeyPoint; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.features2d.FeatureDetector; import org.opencv.imgproc.Imgproc; import java.io.File; import java.io.FileWriter; import java.io.IOException; /** * GripPipeline class. * * <p>An OpenCV pipeline generated by GRIP. * * @author GRIP */ public class GripPipeline { private final String instanceName; private double[] hslThresholdHue; //Outputs private Mat blurOutput = new Mat(); private Mat hslThresholdOutput = new Mat(); private MatOfKeyPoint findBlobsOutput = new MatOfKeyPoint(); static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } public GripPipeline(final String instanceName, double[] hslThresholdHue) { this.instanceName = instanceName; this.hslThresholdHue = hslThresholdHue; } public String toString() { return instanceName; } /** * This is the primary method that runs the entire pipeline and updates the outputs. */ public void process(Mat source0) { // Step Blur0: Mat blurInput = source0; BlurType blurType = BlurType.get("Box Blur"); double blurRadius = 100.0; blur(blurInput, blurType, blurRadius, blurOutput); // Step HSL_Threshold0: Mat hslThresholdInput = blurOutput; double[] hslThresholdSaturation = { 110.0, 255.0 }; double[] hslThresholdLuminance = { 0.0, 180.0 }; hslThreshold(hslThresholdInput, hslThresholdHue, hslThresholdSaturation, hslThresholdLuminance, hslThresholdOutput); // Step FindhslThreshold(_Blobs0: Mat findBlobsInput = hslThresholdOutput; double findBlobsMinArea = 1.0; double[] findBlobsCircularity = { 0.0, 1.0 }; boolean findBlobsDarkBlobs = false; findBlobs(findBlobsInput, findBlobsMinArea, findBlobsCircularity, findBlobsDarkBlobs, findBlobsOutput); } /** * This method is a generated getter for the output of a Blur. * @return Mat output from Blur. */ public Mat blurOutput() { return blurOutput; } /** * This method is a generated getter for the output of a HSL_Threshold. * @return Mat output from HSL_Threshold. */ public Mat hslThresholdOutput() { return hslThresholdOutput; } /** * This method is a generated getter for the output of a Find_Blobs. * @return MatOfKeyPoint output from Find_Blobs. */ public MatOfKeyPoint findBlobsOutput() { return findBlobsOutput; } /** * An indication of which type of filter to use for a blur. * Choices are BOX, GAUSSIAN, MEDIAN, and BILATERAL */ enum BlurType { BOX("Box Blur"), GAUSSIAN("Gaussian Blur"), MEDIAN("Median Filter"), BILATERAL("Bilateral Filter"); private final String label; BlurType(String label) { this.label = label; } public static BlurType get(String type) { if (BILATERAL.label.equals(type)) { return BILATERAL; } else if (GAUSSIAN.label.equals(type)) { return GAUSSIAN; } else if (MEDIAN.label.equals(type)) { return MEDIAN; } else { return BOX; } } @Override public String toString() { return this.label; } } /** * Softens an image using one of several filters. * @param input The image on which to perform the blur. * @param type The blurType to perform. * @param doubleRadius The radius for the blur. * @param output The image in which to store the output. */ private void blur(Mat input, BlurType type, double doubleRadius, Mat output) { int radius = (int) (doubleRadius + 0.5); int kernelSize; switch (type) { case BOX: kernelSize = 2 * radius + 1; Imgproc.blur(input, output, new Size(kernelSize, kernelSize)); break; case GAUSSIAN: kernelSize = 6 * radius + 1; Imgproc.GaussianBlur(input, output, new Size(kernelSize, kernelSize), radius); break; case MEDIAN: kernelSize = 2 * radius + 1; Imgproc.medianBlur(input, output, kernelSize); break; case BILATERAL: Imgproc.bilateralFilter(input, output, -1, radius, radius); break; } } /** * Segment an image based on hue, saturation, and luminance ranges. * * @param input The image on which to perform the HSL threshold. * @param hue The min and max hue * @param sat The min and max saturation * @param lum The min and max luminance * @param out The image in which to store the output. */ private void hslThreshold(Mat input, double[] hue, double[] sat, double[] lum, Mat out) { Imgproc.cvtColor(input, out, Imgproc.COLOR_BGR2HLS); Core.inRange(out, new Scalar(hue[0], lum[0], sat[0]), new Scalar(hue[1], lum[1], sat[1]), out); } /** * Detects groups of pixels in an image. * @param input The image on which to perform the find blobs. * @param minArea The minimum size of a blob that will be found * @param circularity The minimum and maximum circularity of blobs that will be found * @param darkBlobs The boolean that determines if light or dark blobs are found. * @param blobList The output where the MatOfKeyPoint is stored. */ private void findBlobs(Mat input, double minArea, double[] circularity, Boolean darkBlobs, MatOfKeyPoint blobList) { FeatureDetector blobDet = FeatureDetector.create(FeatureDetector.SIMPLEBLOB); try { File tempFile = File.createTempFile("config", ".xml"); StringBuilder config = new StringBuilder(); config.append("<?xml version=\"1.0\"?>\n"); config.append("<opencv_storage>\n"); config.append("<thresholdStep>10.</thresholdStep>\n"); config.append("<minThreshold>50.</minThreshold>\n"); config.append("<maxThreshold>220.</maxThreshold>\n"); config.append("<minRepeatability>2</minRepeatability>\n"); config.append("<minDistBetweenBlobs>10.</minDistBetweenBlobs>\n"); config.append("<filterByColor>1</filterByColor>\n"); config.append("<blobColor>"); config.append((darkBlobs ? 0 : 255)); config.append("</blobColor>\n"); config.append("<filterByArea>1</filterByArea>\n"); config.append("<minArea>"); config.append(minArea); config.append("</minArea>\n"); config.append("<maxArea>"); config.append(Integer.MAX_VALUE); config.append("</maxArea>\n"); config.append("<filterByCircularity>1</filterByCircularity>\n"); config.append("<minCircularity>"); config.append(circularity[0]); config.append("</minCircularity>\n"); config.append("<maxCircularity>"); config.append(circularity[1]); config.append("</maxCircularity>\n"); config.append("<filterByInertia>1</filterByInertia>\n"); config.append("<minInertiaRatio>0.1</minInertiaRatio>\n"); config.append("<maxInertiaRatio>" + Integer.MAX_VALUE + "</maxInertiaRatio>\n"); config.append("<filterByConvexity>1</filterByConvexity>\n"); config.append("<minConvexity>0.95</minConvexity>\n"); config.append("<maxConvexity>" + Integer.MAX_VALUE + "</maxConvexity>\n"); config.append("</opencv_storage>\n"); FileWriter writer; writer = new FileWriter(tempFile, false); writer.write(config.toString()); writer.close(); blobDet.read(tempFile.getPath()); } catch (IOException e) { e.printStackTrace(); } blobDet.detect(input, blobList); } }