From 259753e582fb1d1663302f0cb24767b63c0d88a0 Mon Sep 17 00:00:00 2001 From: ori agranat Date: Fri, 4 Oct 2019 16:46:16 +0300 Subject: [PATCH] redone grouped contours and fixed ratio slider --- .../chameleonvision/Handler/MathHandler.java | 5 ++ .../vision/process/CVProcess.java | 55 +++++++++++-------- .../vision/process/VisionProcess.java | 6 +- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/Main/src/main/java/com/chameleonvision/Handler/MathHandler.java b/Main/src/main/java/com/chameleonvision/Handler/MathHandler.java index 40971fffc..fd2c4edbb 100644 --- a/Main/src/main/java/com/chameleonvision/Handler/MathHandler.java +++ b/Main/src/main/java/com/chameleonvision/Handler/MathHandler.java @@ -1,4 +1,6 @@ package com.chameleonvision.Handler; +import org.apache.commons.math3.util.FastMath; + import java.lang.Math; public class MathHandler { MathHandler(){} @@ -12,4 +14,7 @@ public class MathHandler { } return ((k / (1 + Math.pow(Math.E,(a + (b * x))))) + bias); } + public static double toSlope(double angle){ + return FastMath.atan(FastMath.toRadians(angle - 90)); + } } diff --git a/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java index bee2cb7ae..007e52166 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java @@ -6,6 +6,8 @@ import org.apache.commons.math3.util.FastMath; import org.jetbrains.annotations.NotNull; import org.opencv.core.*; import org.opencv.imgproc.Imgproc; +import org.opencv.imgproc.Moments; + import java.util.*; @SuppressWarnings("WeakerAccess") @@ -20,14 +22,16 @@ public class CVProcess { put("Quintuple", 5); }}; private Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5)); + private Size blur = new Size(1,1); private Mat hsvImage = new Mat(); private List foundContours = new ArrayList<>(); private Mat binaryMat = new Mat(); private List filteredContours = new ArrayList<>(); private Comparator sortByCentermostComparator = Comparator.comparingDouble(this::calcDistance); + private Comparator sortByMomentsX = Comparator.comparingDouble(this::calcMomentsX); private List finalCountours = new ArrayList<>(); - private Mat intersectMatA = new Mat(); - private Mat intersectMatB = new Mat(); + private MatOfPoint2f intersectMatA = new MatOfPoint2f(); + private MatOfPoint2f intersectMatB = new MatOfPoint2f(); CVProcess(CameraValues cameraValues) { this.cameraValues = cameraValues; @@ -35,6 +39,7 @@ public class CVProcess { void hsvThreshold(Mat srcImage, Mat dst, @NotNull Scalar hsvLower, @NotNull Scalar hsvUpper, boolean shouldErode, boolean shouldDilate) { Imgproc.cvtColor(srcImage, hsvImage, Imgproc.COLOR_RGB2HSV, 3); + Imgproc.blur(hsvImage, hsvImage, blur); Core.inRange(hsvImage, hsvLower, hsvUpper, dst); if (shouldErode) { Imgproc.erode(dst, dst, kernel); @@ -57,20 +62,22 @@ public class CVProcess { for (MatOfPoint Contour : inputContours) { try { double contourArea = Imgproc.contourArea(Contour); - double minArea = (MathHandler.sigmoid(area.get(0)) * cameraValues.ImageArea) / 100; - double maxArea = (MathHandler.sigmoid(area.get(1)) * cameraValues.ImageArea) / 100; - if (contourArea <= minArea || contourArea >= maxArea) { + double AreaRatio = (contourArea / cameraValues.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())); var targetFullness = contourArea; - double minExtent = (double) (extent.get(0) * rect.size.area())/ 100; + double minExtent = (double) (extent.get(0) * rect.size.area()) / 100; double maxExtent = (double) (extent.get(1) * rect.size.area()) / 100; if (targetFullness <= minExtent || contourArea >= maxExtent) { continue; } - double aspectRatio = rect.size.width / rect.size.height;//TODO i think aspectRatio is inverted + Rect bb = Imgproc.boundingRect(Contour); + double aspectRatio = (bb.width / bb.height); if (aspectRatio < ratio.get(0) || aspectRatio > ratio.get(1)) { continue; } @@ -86,7 +93,10 @@ public class CVProcess { private double calcDistance(RotatedRect rect) { return FastMath.sqrt(FastMath.pow(cameraValues.CenterX - rect.center.x, 2) + FastMath.pow(cameraValues.CenterY - rect.center.y, 2)); } - + private double calcMomentsX(MatOfPoint c){ + Moments m = Imgproc.moments(c); + return (m.get_m10()/m.get_m00()); + } RotatedRect sortTargetsToOne(List inputRects, String sortMode) { switch (sortMode) { case "Largest": @@ -111,6 +121,7 @@ public class CVProcess { List groupTargets(List inputContours, String intersectionPoint, String targetGroup) { finalCountours.clear(); if (!targetGroup.equals("Single")) { + inputContours.sort(sortByMomentsX); for (var i = 0; i < inputContours.size(); i++) { List FinalContourList = new ArrayList<>(inputContours.get(i).toList()); for (var c = 0; c < (targetGrouping.get(targetGroup) - 1); c++) { @@ -157,24 +168,20 @@ public class CVProcess { return true; } try { - Imgproc.fitLine(ContourOne, intersectMatA, Imgproc.CV_DIST_L2, 0, 0.01, 0.01); - Imgproc.fitLine(ContourTwo, intersectMatB, Imgproc.CV_DIST_L2, 0, 0.01, 0.01); - double vxA = intersectMatA.get(0, 0)[0]; - double vyA = intersectMatA.get(1, 0)[0]; - double x0A = intersectMatA.get(2, 0)[0]; - double y0A = intersectMatA.get(3, 0)[0]; - double mA = vyA / vxA; - double vxB = intersectMatB.get(0, 0)[0]; - double vyB = intersectMatB.get(1, 0)[0]; - double x0B = intersectMatB.get(2, 0)[0]; - double y0B = intersectMatB.get(3, 0)[0]; - double mB = vyB / vxB; - double bA = y0A - (mA*x0A); - double bB = y0B - (mB*x0B); + intersectMatA.fromArray(ContourOne.toArray()); + intersectMatB.fromArray(ContourTwo.toArray()); + RotatedRect a = Imgproc.fitEllipse(intersectMatA); + RotatedRect b = Imgproc.fitEllipse(intersectMatB); + double mA = MathHandler.toSlope(a.angle); + double mB = MathHandler.toSlope(b.angle); + double x0A = a.center.x; + double y0A = a.center.y; + double x0B = b.center.x; + double y0B = b.center.y; double intersectionX = ((mA * x0A) - y0A - (mB * x0B) + y0B )/ (mA - mB); double intersectionY = (mA * (intersectionX - x0A)) + y0A; - double massX = intersectionX + 1; - double massY = intersectionY + ((mA + bA + mB +bB) / 2); + double massX = (x0A + x0B) / 2; + double massY = (y0A + y0B) / 2; switch (IntersectionPoint) { case "Up": { if (intersectionY < massY) { diff --git a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java index 8440f108f..aa55cb1db 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java @@ -37,6 +37,7 @@ public class VisionProcess implements Runnable { private Mat hsvThreshMat = new Mat(); private Mat streamOutputMat = new Mat(); private Scalar contourRectColor = new Scalar(255, 0, 0); + private Scalar BoxRectColor = new Scalar(0, 0, 233); private long timeStamp = 0; public VisionProcess(Camera processCam) { @@ -103,9 +104,12 @@ public class VisionProcess implements Runnable { List drawnContour = new ArrayList<>(); Point[] vertices = new Point[4]; contourRect.points(vertices); - drawnContour.add(new MatOfPoint(vertices)); + MatOfPoint contour = new MatOfPoint(vertices); + drawnContour.add(contour); + Rect box = Imgproc.boundingRect(contour); Imgproc.drawContours(inputMat, drawnContour, 0, contourRectColor, 3); Imgproc.circle(inputMat, contourRect.center, 3, contourRectColor); + Imgproc.rectangle(inputMat,new Point(box.x, box.y), new Point((box.x + box.width),(box.y + box.height)), BoxRectColor,2); } private void updateNetworkTables(PipelineResult pipelineResult) {