diff --git a/Main/src/main/java/com/chameleonvision/vision/VisionProcess.java b/Main/src/main/java/com/chameleonvision/vision/VisionProcess.java index 30589dc71..5e5d62552 100644 --- a/Main/src/main/java/com/chameleonvision/vision/VisionProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/VisionProcess.java @@ -11,6 +11,7 @@ import com.google.gson.GsonBuilder; import edu.wpi.cscore.VideoMode; import edu.wpi.first.networktables.*; import edu.wpi.first.wpiutil.CircularBuffer; +import org.apache.commons.lang3.tuple.Pair; import org.opencv.core.Mat; import java.util.ArrayList; @@ -21,7 +22,6 @@ public class VisionProcess { private final CameraCapture cameraCapture; private final List pipelines = new ArrayList<>(); - private final CameraFrameRunnable cameraRunnable; private final CameraStreamerRunnable streamRunnable; private final VisionProcessRunnable visionRunnable; public final CameraStreamer cameraStreamer; @@ -32,13 +32,10 @@ public class VisionProcess { private final CVPipelineSettings driverModeSettings = new CVPipelineSettings(); private CVPipeline driverModePipeline = new DriverVisionPipeline(driverModeSettings); - // shitty stuff - private volatile Mat lastCameraFrame = new Mat(); - private volatile boolean hasUnprocessedFrame = true; private volatile CVPipelineResult lastPipelineResult; // network table stuff - private NetworkTable defaultTable; + private final NetworkTable defaultTable; private NetworkTableEntry ntPipelineEntry; private NetworkTableEntry ntDriverModeEntry; private int ntDriveModeListenerID; @@ -57,14 +54,6 @@ public class VisionProcess { pipelines.add(new CVPipeline2d("New Pipeline")); setPipeline(0, false); - // Thread to grab frames from the camera - // TODO: (HIGH) fix video modes!!! - this.cameraRunnable = new CameraFrameRunnable(cameraCapture.getProperties().videoModes.get(0).fps); - - lastPipelineResult = new DriverVisionPipeline.DriverPipelineResult( - null, cameraRunnable.getFrame(new Mat()), 0 - ); - // Thread to put frames on the dashboard this.cameraStreamer = new CameraStreamer(cameraCapture, name); this.streamRunnable = new CameraStreamerRunnable(30, cameraStreamer); @@ -77,18 +66,8 @@ public class VisionProcess { } public void start() { - System.out.println("Starting NetworkTables"); + System.out.println("Starting NetworkTables."); initNT(defaultTable); - - System.out.println("Starting camera thread."); - new Thread(cameraRunnable).start(); - while (cameraRunnable.cameraFrame == null) { - try { - if (lastCameraFrame.cols() > 0) break; - } catch (Exception e) { -// e.printStackTrace(); - } - } System.out.println("Starting vision thread."); new Thread(visionRunnable).start(); System.out.println("Starting stream thread."); @@ -217,7 +196,7 @@ public class VisionProcess { //noinspection unchecked List targets = (List) data.targets; - ntTimeStampEntry.setDouble(data.processTime); + ntTimeStampEntry.setDouble(data.imageTimestamp); ntPitchEntry.setDouble(targets.get(0).pitch); ntYawEntry.setDouble(targets.get(0).yaw); ntAreaEntry.setDouble(targets.get(0).area); @@ -231,12 +210,12 @@ public class VisionProcess { ntYawEntry.setDouble(0.0); ntAreaEntry.setDouble(0.0); ntTimeStampEntry.setDouble(0.0); + ntAuxListEntry.setString(""); } } public void setVideoMode(VideoMode newMode) { cameraCapture.setVideoMode(newMode); - cameraRunnable.updateCameraFPS(newMode.fps); cameraStreamer.setNewVideoMode(newMode); } @@ -277,59 +256,6 @@ public class VisionProcess { return pipelines.get(pipelineIndex); } - /** - * CameraFrameRunnable grabs images from the cameraProcess - * at a specified loopTime - */ - protected class CameraFrameRunnable extends LoopingRunnable { - private Mat cameraFrame; - private long timestampMicros; - - private final Object frameLock = new Object(); - - /** - * CameraFrameRunnable grabs images from the cameraProcess - * at a specified framerate - * @param cameraFPS FPS of camera - */ - CameraFrameRunnable(int cameraFPS) { - // add 2 FPS to allow for a bit of overhead - // TODO: (low) test the effect of this - super(1000L/(cameraFPS + 2)); - } - - void updateCameraFPS(int newFPS) { - super.loopTimeMs = 1000L / (newFPS + 2); - } - - @Override - public void process() { - - // Grab camera frames - var camData = cameraCapture.getFrame(); - if (camData.getLeft().cols() > 0) { -// System.out.println("grabbing frame"); -// synchronized (frameLock) { -// cameraFrame = camData.getLeft(); -// } - timestampMicros = camData.getRight(); - camData.getLeft().copyTo(lastCameraFrame); - hasUnprocessedFrame = true; - - } - } - - public Mat getFrame(Mat dst) { - if (cameraFrame != null) { - dst = cameraFrame; - } else { - System.out.println("no frame"); - } - return dst; - } - - } - /** * VisionProcessRunnable will process images as quickly as possible */ @@ -337,48 +263,36 @@ public class VisionProcess { volatile Double fps = 0.0; private CircularBuffer fpsAveragingBuffer = new CircularBuffer(7); - @SuppressWarnings("FieldCanBeLocal") - private CVPipelineResult result; private Mat streamBuffer = new Mat(); @Override public void run() { var lastUpdateTimeNanos = System.nanoTime(); while(!Thread.interrupted()) { -// System.out.println("running vision process"); - while(!hasUnprocessedFrame) { - try { - Thread.sleep(3); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + // blocking call, will block until camera has a new frame. + Pair camData = cameraCapture.getFrame(); - lastCameraFrame.copyTo(streamBuffer); // = //cameraRunnable.getFrame(streamBuffer); - hasUnprocessedFrame = false; - - if (streamBuffer.cols() > 0 && streamBuffer.rows() > 0) { - result = currentPipeline.runPipeline(streamBuffer); - lastPipelineResult = result; + Mat camFrame = camData.getLeft(); + if (camFrame.cols() > 0 && camFrame.rows() > 0) { + CVPipelineResult result = currentPipeline.runPipeline(camFrame); if (result != null) { + result.setTimestamp(camData.getRight()); + lastPipelineResult = result; updateNetworkTableData(lastPipelineResult); updateUI(lastPipelineResult); } - } var deltaTimeNanos = lastUpdateTimeNanos - System.nanoTime(); fpsAveragingBuffer.addFirst(1.0 / (deltaTimeNanos * 1E-09)); lastUpdateTimeNanos = System.nanoTime(); fps = getAverageFPS(); - - // TODO: (HIGH) do something with the result } } - public double getAverageFPS() { + double getAverageFPS() { var temp = 0.0; for(int i = 0; i < 7; i++) { temp += fpsAveragingBuffer.get(i); @@ -389,31 +303,32 @@ public class VisionProcess { } - private class CameraStreamerRunnable extends LoopingRunnable { + private static class CameraStreamerRunnable extends LoopingRunnable { - public final CameraStreamer streamer; + final CameraStreamer streamer; private Mat streamBuffer = new Mat(); private CameraStreamerRunnable(int cameraFPS, CameraStreamer streamer) { // add 2 FPS to allow for a bit of overhead // TODO: (low) test the effect of this - super(1000L/(cameraFPS + 2)); +// super(1000L/(cameraFPS + 2)); + super(10L); this.streamer = streamer; } @Override protected void process() { // System.out.println("running camera streamer"); - Mat latestMat = lastPipelineResult.outputMat; //visionRunnable.result; - if (latestMat != null && latestMat.cols() > 0) { - latestMat.copyTo(streamBuffer); - streamer.runStream(streamBuffer); - streamBuffer.release(); +// Mat latestMat = lastPipelineResult.outputMat; //visionRunnable.result; +// if (latestMat != null && latestMat.cols() > 0) { +// latestMat.copyTo(streamBuffer); +// streamer.runStream(streamBuffer); +// streamBuffer.release(); // if (toStreamMat != null && toStreamMat.cols() > 0) { // } else { // System.out.println("fuuuuck"); // } - } +// } } } } diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java b/Main/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java index d1f8371fb..ff031de59 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java @@ -31,9 +31,8 @@ public class USBCameraCapture implements CameraCapture { @Override public Pair getFrame() { Long deltaTime; - synchronized (cvSink) { - deltaTime = cvSink.grabFrame(imageBuffer) * 1000L; - } + // TODO: Why multiply by 1000 here? + deltaTime = cvSink.grabFrame(imageBuffer) * 1000L; return Pair.of(imageBuffer, deltaTime); } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/CVPipeline2d.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/CVPipeline2d.java index 8bb2f3f51..898c9e57a 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/CVPipeline2d.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/CVPipeline2d.java @@ -89,11 +89,10 @@ public class CVPipeline2d extends CVPipeline { public final boolean hasTarget; public final Mat outputMat; public final long processTime; + public long imageTimestamp = 0; public CVPipelineResult(List targets, Mat outputMat, long processTime) { this.targets = targets; @@ -16,4 +17,8 @@ public abstract class CVPipelineResult { this.outputMat = outputMat; this.processTime = processTime; } + + public void setTimestamp(long timestamp) { + imageTimestamp = timestamp; + } } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/BlurPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/BlurPipe.java index 029e5e523..eeb175356 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/BlurPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/BlurPipe.java @@ -30,6 +30,7 @@ public class BlurPipe implements Pipe { try { Imgproc.blur(processBuffer, processBuffer, new Size(blurSize, blurSize)); processBuffer.copyTo(outputMat); + processBuffer.release(); } catch (CvException e) { System.err.println("(BlurPipe) Exception thrown by OpenCV: \n" + e.getMessage()); } @@ -37,10 +38,7 @@ public class BlurPipe implements Pipe { input.copyTo(outputMat); } - long processTime = System.nanoTime() - processStartNanos; - Pair output = Pair.of(outputMat, processTime); - processBuffer.release(); - return output; + return Pair.of(outputMat, processTime); } } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Collect2dTargetsPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Collect2dTargetsPipe.java index 87a627fc2..d1c0fb960 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Collect2dTargetsPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Collect2dTargetsPipe.java @@ -43,30 +43,32 @@ public class Collect2dTargetsPipe implements Pipe, List { - CVPipeline2d.Target2d t = new CVPipeline2d.Target2d(); - t.rawPoint = r; - switch (calibrationMode) { - case None: - t.calibratedX = camProps.centerX; - t.calibratedY = camProps.centerY; - break; - case Single: - t.calibratedX = calibrationPoint.get(0).doubleValue(); - t.calibratedY = calibrationPoint.get(1).doubleValue(); - break; - case Dual: - t.calibratedX = (r.center.y - calibrationB) / calibrationM; - t.calibratedY = (r.center.x * calibrationM) + calibrationB; - break; + if (input.size() > 0) { + for (RotatedRect r : input) { + CVPipeline2d.Target2d t = new CVPipeline2d.Target2d(); + t.rawPoint = r; + switch (calibrationMode) { + case None: + t.calibratedX = camProps.centerX; + t.calibratedY = camProps.centerY; + break; + case Single: + t.calibratedX = calibrationPoint.get(0).doubleValue(); + t.calibratedY = calibrationPoint.get(1).doubleValue(); + break; + case Dual: + t.calibratedX = (r.center.y - calibrationB) / calibrationM; + t.calibratedY = (r.center.x * calibrationM) + calibrationB; + break; + } + + t.pitch = calculatePitch(r.center.y, t.calibratedY); + t.yaw = calculateYaw(r.center.x, t.calibratedX); + t.area = r.size.area(); + + targets.add(t); } - - t.pitch = calculatePitch(r.center.y, t.calibratedY); - t.yaw = calculateYaw(r.center.x, t.calibratedX); - t.area = r.size.area(); - - targets.add(t); - }); + } long processTime = System.nanoTime() - processStartNanos; return Pair.of(targets, processTime); diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Draw2dContoursPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Draw2dContoursPipe.java index 3fc361f47..69481fb68 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Draw2dContoursPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/Draw2dContoursPipe.java @@ -17,6 +17,7 @@ public class Draw2dContoursPipe implements Pipe>, Ma private final Draw2dContoursSettings settings; private CaptureStaticProperties camProps; + private Mat processBuffer = new Mat(); private Mat outputMat = new Mat(); public Draw2dContoursPipe(Draw2dContoursSettings settings, CaptureStaticProperties camProps) { @@ -32,48 +33,51 @@ public class Draw2dContoursPipe implements Pipe>, Ma public Pair run(Pair> input) { long processStartNanos = System.nanoTime(); - outputMat = input.getLeft(); + if (settings.showCrosshair || settings.showCentroid || settings.showMaximumBox || settings.showRotatedBox) { + input.getLeft().copyTo(processBuffer); - if (input.getRight() != null && !input.getRight().isEmpty()) { - for (RotatedRect r : input.getRight()) { - if (r == null) continue; + if (input.getRight().size() > 0) { + for (RotatedRect r : input.getRight()) { + if (r == null) continue; - List drawnContour = new ArrayList<>(); - Point[] vertices = new Point[4]; - r.points(vertices); - MatOfPoint contour = new MatOfPoint(vertices); - drawnContour.add(contour); + List drawnContour = new ArrayList<>(); + Point[] vertices = new Point[4]; + r.points(vertices); + MatOfPoint contour = new MatOfPoint(vertices); + drawnContour.add(contour); - if (settings.showCentroid) { - Imgproc.circle(outputMat, r.center, 3, Helpers.colorToScalar(settings.centroidColor)); - } + if (settings.showCentroid) { + Imgproc.circle(processBuffer, r.center, 3, Helpers.colorToScalar(settings.centroidColor)); + } - if (settings.showRotatedBox) { - Imgproc.drawContours(outputMat, drawnContour, 0, Helpers.colorToScalar(settings.rotatedBoxColor), settings.boxOutlineSize); - } + if (settings.showRotatedBox) { + Imgproc.drawContours(processBuffer, drawnContour, 0, Helpers.colorToScalar(settings.rotatedBoxColor), settings.boxOutlineSize); + } - if (settings.showMaximumBox) { - Rect box = Imgproc.boundingRect(contour); - Imgproc.rectangle(outputMat, new Point(box.x, box.y), new Point((box.x + box.width), (box.y + box.height)), Helpers.colorToScalar(settings.maximumBoxColor), settings.boxOutlineSize); + if (settings.showMaximumBox) { + Rect box = Imgproc.boundingRect(contour); + Imgproc.rectangle(processBuffer, new Point(box.x, box.y), new Point((box.x + box.width), (box.y + box.height)), Helpers.colorToScalar(settings.maximumBoxColor), settings.boxOutlineSize); + } } } - } - if (settings.showCrosshair) { - Point xMax = new Point(camProps.centerX + 10, camProps.centerY); - Point xMin = new Point(camProps.centerX - 10, camProps.centerY); - Point yMax = new Point(camProps.centerX, camProps.centerY + 10); - Point yMin = new Point(camProps.centerX, camProps.centerY - 10); - if (outputMat != null && outputMat.cols() > 0) { - Imgproc.line(outputMat, xMax, xMin, Helpers.colorToScalar(settings.crosshairColor), 2); - Imgproc.line(outputMat, yMax, yMin, Helpers.colorToScalar(settings.crosshairColor), 2); + if (settings.showCrosshair) { + Point xMax = new Point(camProps.centerX + 10, camProps.centerY); + Point xMin = new Point(camProps.centerX - 10, camProps.centerY); + Point yMax = new Point(camProps.centerX, camProps.centerY + 10); + Point yMin = new Point(camProps.centerX, camProps.centerY - 10); + Imgproc.line(processBuffer, xMax, xMin, Helpers.colorToScalar(settings.crosshairColor), 2); + Imgproc.line(processBuffer, yMax, yMin, Helpers.colorToScalar(settings.crosshairColor), 2); } + + processBuffer.copyTo(outputMat); + processBuffer.release(); + } else { + input.getLeft().copyTo(outputMat); } long processTime = System.nanoTime() - processStartNanos; - Pair output = Pair.of(outputMat, processTime); - outputMat.release(); - return output; + return Pair.of(outputMat, processTime); } public static class Draw2dContoursSettings { diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/ErodeDilatePipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/ErodeDilatePipe.java index 4534f8ae1..3798856d5 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/ErodeDilatePipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/ErodeDilatePipe.java @@ -30,20 +30,24 @@ public class ErodeDilatePipe implements Pipe { public Pair run(Mat input) { long processStartNanos = System.nanoTime(); - input.copyTo(processBuffer); + if (erode || dilate) { + input.copyTo(processBuffer); - if (erode) { - Imgproc.erode(processBuffer, processBuffer, kernel); - } + if (erode) { + Imgproc.erode(processBuffer, processBuffer, kernel); + } - if (dilate) { - Imgproc.erode(processBuffer, processBuffer, kernel); + if (dilate) { + Imgproc.erode(processBuffer, processBuffer, kernel); + } + + processBuffer.copyTo(outputMat); + processBuffer.release(); + } else { + input.copyTo(outputMat); } long processTime = System.nanoTime() - processStartNanos; - processBuffer.copyTo(outputMat); - Pair output = Pair.of(outputMat, processTime); - processBuffer.release(); - return output; + return Pair.of(outputMat, processTime); } } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/FilterContoursPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/FilterContoursPipe.java index 9870e43a5..121216214 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/FilterContoursPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/FilterContoursPipe.java @@ -40,30 +40,32 @@ public class FilterContoursPipe implements Pipe, List maxArea) { - continue; + if (input.size() > 0) { + for (MatOfPoint Contour : input) { + try { + double contourArea = Imgproc.contourArea(Contour); + double AreaRatio = (contourArea / camProps.imageArea) * 100; + double minArea = (MathHandler.sigmoid(area.get(0))); + double maxArea = (MathHandler.sigmoid(area.get(1))); + if (AreaRatio < minArea || AreaRatio > maxArea) { + continue; + } + var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray())); + double minExtent = (extent.get(0).doubleValue() * rect.size.area()) / 100; + double maxExtent = (extent.get(1).doubleValue() * rect.size.area()) / 100; + if (contourArea <= minExtent || contourArea >= maxExtent) { + continue; + } + Rect bb = Imgproc.boundingRect(Contour); + double aspectRatio = ((double)bb.width / bb.height); + if (aspectRatio < ratio.get(0).doubleValue() || aspectRatio > ratio.get(1).doubleValue()) { + continue; + } + filteredContours.add(Contour); + } catch (Exception e) { + System.err.println("Error while filtering contours"); + e.printStackTrace(); } - var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray())); - double minExtent = (extent.get(0).doubleValue() * rect.size.area()) / 100; - double maxExtent = (extent.get(1).doubleValue() * rect.size.area()) / 100; - if (contourArea <= minExtent || contourArea >= maxExtent) { - continue; - } - Rect bb = Imgproc.boundingRect(Contour); - double aspectRatio = ((double)bb.width / bb.height); - if (aspectRatio < ratio.get(0).doubleValue() || aspectRatio > ratio.get(1).doubleValue()) { - continue; - } - filteredContours.add(Contour); - } catch (Exception e) { - System.err.println("Error while filtering contours"); - e.printStackTrace(); } } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/GroupContoursPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/GroupContoursPipe.java index 070a895a8..b2d3df9aa 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/GroupContoursPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/GroupContoursPipe.java @@ -41,56 +41,59 @@ public class GroupContoursPipe implements Pipe, List sorted = new ArrayList<>(input); - sorted.sort(sortByMomentsX); + if (input.size() > 0) { - Collections.reverse(sorted); + List sorted = new ArrayList<>(input); + sorted.sort(sortByMomentsX); - switch (group) { - case Single: { - input.forEach(c -> { - MatOfPoint2f contour = new MatOfPoint2f(); - contour.fromArray(c.toArray()); - if (contour.cols() != 0 && contour.rows() != 0) { - RotatedRect rect = Imgproc.minAreaRect(contour); - groupedContours.add(rect); - } - }); - break; - } - case Dual: { - for (var i = 0; i < input.size(); i++) { - List finalContourList = new ArrayList<>(input.get(i).toList()); - - try { - MatOfPoint firstContour = input.get(i); - MatOfPoint secondContour = input.get(i + 1); - - if (isIntersecting(firstContour, secondContour)) { - finalContourList.addAll(secondContour.toList()); - } else { - finalContourList.clear(); - continue; - } - - intersectMatA.release(); - intersectMatB.release(); - firstContour.release(); - secondContour.release(); + Collections.reverse(sorted); + switch (group) { + case Single: { + input.forEach(c -> { MatOfPoint2f contour = new MatOfPoint2f(); - contour.fromList(finalContourList); - + contour.fromArray(c.toArray()); if (contour.cols() != 0 && contour.rows() != 0) { RotatedRect rect = Imgproc.minAreaRect(contour); groupedContours.add(rect); } - } catch (IndexOutOfBoundsException e) { - System.err.println("GroupContours: WTF"); - finalContourList.clear(); - } + }); + break; + } + case Dual: { + for (var i = 0; i < input.size(); i++) { + List finalContourList = new ArrayList<>(input.get(i).toList()); + + try { + MatOfPoint firstContour = input.get(i); + MatOfPoint secondContour = input.get(i + 1); + + if (isIntersecting(firstContour, secondContour)) { + finalContourList.addAll(secondContour.toList()); + } else { + finalContourList.clear(); + continue; + } + + intersectMatA.release(); + intersectMatB.release(); + firstContour.release(); + secondContour.release(); + + MatOfPoint2f contour = new MatOfPoint2f(); + contour.fromList(finalContourList); + + if (contour.cols() != 0 && contour.rows() != 0) { + RotatedRect rect = Imgproc.minAreaRect(contour); + groupedContours.add(rect); + } + } catch (IndexOutOfBoundsException e) { + System.err.println("GroupContours: WTF"); + finalContourList.clear(); + } + } + break; } - break; } } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/HsvPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/HsvPipe.java index 454f851d5..47544297b 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/HsvPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/HsvPipe.java @@ -38,11 +38,11 @@ public class HsvPipe implements Pipe { System.err.println("(HsvPipe) Exception thrown by OpenCV: \n" + e.getMessage()); } - long processTime = System.nanoTime() - processStartNanos; processBuffer.copyTo(outputMat); - Pair output = Pair.of(outputMat, processTime); processBuffer.release(); - return output; + + long processTime = System.nanoTime() - processStartNanos; + return Pair.of(outputMat, processTime); } } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/RotateFlipPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/RotateFlipPipe.java index a4a604dfb..94cf483ff 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/RotateFlipPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/RotateFlipPipe.java @@ -28,15 +28,27 @@ public class RotateFlipPipe implements Pipe { public Pair run(Mat input) { long processStartNanos = System.nanoTime(); - input.copyTo(processBuffer); + boolean shouldFlip = !flip.equals(ImageFlipMode.NONE); + boolean shouldRotate = !rotation.equals(ImageRotation.DEG_0); - Core.flip(processBuffer, processBuffer, flip.value); - Core.rotate(processBuffer, processBuffer, rotation.value); + if (shouldFlip || shouldRotate) { + input.copyTo(processBuffer); + + if (shouldFlip) { + Core.flip(processBuffer, processBuffer, flip.value); + } + + if (shouldRotate) { + Core.rotate(processBuffer, processBuffer, rotation.value); + } + + processBuffer.copyTo(outputMat); + processBuffer.release(); + } else { + input.copyTo(outputMat); + } long processTime = System.nanoTime() - processStartNanos; - processBuffer.copyTo(outputMat); - Pair output = Pair.of(outputMat, processTime); - processBuffer.release(); - return output; + return Pair.of(outputMat, processTime); } } diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SortContoursPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SortContoursPipe.java index 329b848a2..7281f2a6c 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SortContoursPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SortContoursPipe.java @@ -44,32 +44,35 @@ public class SortContoursPipe implements Pipe, List 0) { + sortedContours.addAll(input); + + switch (sort) { + case Largest: + sortedContours.sort(SortByLargestComparator); + break; + case Smallest: + sortedContours.sort(SortBySmallestComparator); + break; + case Highest: + sortedContours.sort(SortByHighestComparator); + break; + case Lowest: + sortedContours.sort(SortByLowestComparator); + break; + case Leftmost: + sortedContours.sort(SortByLeftmostComparator); + break; + case Rightmost: + sortedContours.sort(SortByRightmostComparator); + break; + case Centermost: + sortedContours.sort(SortByCentermostComparator); + break; + default: + break; + } } long processTime = System.nanoTime() - processStartNanos; diff --git a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SpeckleRejectPipe.java b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SpeckleRejectPipe.java index 7edebf7f7..058e955d6 100644 --- a/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SpeckleRejectPipe.java +++ b/Main/src/main/java/com/chameleonvision/vision/pipeline/pipes/SpeckleRejectPipe.java @@ -27,19 +27,21 @@ public class SpeckleRejectPipe implements Pipe, List 0) { + double averageArea = 0.0; - for (MatOfPoint c : input) { - averageArea += Imgproc.contourArea(c); - } + for (MatOfPoint c : input) { + averageArea += Imgproc.contourArea(c); + } - averageArea /= input.size(); + averageArea /= input.size(); - double minAllowedArea = minPercentOfAvg / 100.0 * averageArea; + double minAllowedArea = minPercentOfAvg / 100.0 * averageArea; - for (MatOfPoint c : input) { - if (Imgproc.contourArea(c) >= minAllowedArea) { - despeckledContours.add(c); + for (MatOfPoint c : input) { + if (Imgproc.contourArea(c) >= minAllowedArea) { + despeckledContours.add(c); + } } } diff --git a/Main/src/main/java/com/chameleonvision/web/Server.java b/Main/src/main/java/com/chameleonvision/web/Server.java index 6141dc173..bbb1c0461 100644 --- a/Main/src/main/java/com/chameleonvision/web/Server.java +++ b/Main/src/main/java/com/chameleonvision/web/Server.java @@ -20,7 +20,6 @@ public class Server { ws.onClose(ctx -> { handler.onClose(ctx); System.out.println("Socket Disconnected"); - // TODO: (HIGH) add generalSettingsSave ConfigManager.saveSettings(); }); ws.onBinaryMessage(ctx -> {