mirror of
https://github.com/PhotonVision/photonvision
synced 2026-07-03 03:01:40 +00:00
redone grouped contours and fixed ratio slider
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
package com.chameleonvision.Handler;
|
package com.chameleonvision.Handler;
|
||||||
|
import org.apache.commons.math3.util.FastMath;
|
||||||
|
|
||||||
import java.lang.Math;
|
import java.lang.Math;
|
||||||
public class MathHandler {
|
public class MathHandler {
|
||||||
MathHandler(){}
|
MathHandler(){}
|
||||||
@@ -12,4 +14,7 @@ public class MathHandler {
|
|||||||
}
|
}
|
||||||
return ((k / (1 + Math.pow(Math.E,(a + (b * x))))) + bias);
|
return ((k / (1 + Math.pow(Math.E,(a + (b * x))))) + bias);
|
||||||
}
|
}
|
||||||
|
public static double toSlope(double angle){
|
||||||
|
return FastMath.atan(FastMath.toRadians(angle - 90));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import org.apache.commons.math3.util.FastMath;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.opencv.core.*;
|
import org.opencv.core.*;
|
||||||
import org.opencv.imgproc.Imgproc;
|
import org.opencv.imgproc.Imgproc;
|
||||||
|
import org.opencv.imgproc.Moments;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
@@ -20,14 +22,16 @@ public class CVProcess {
|
|||||||
put("Quintuple", 5);
|
put("Quintuple", 5);
|
||||||
}};
|
}};
|
||||||
private Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 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 Mat hsvImage = new Mat();
|
||||||
private List<MatOfPoint> foundContours = new ArrayList<>();
|
private List<MatOfPoint> foundContours = new ArrayList<>();
|
||||||
private Mat binaryMat = new Mat();
|
private Mat binaryMat = new Mat();
|
||||||
private List<MatOfPoint> filteredContours = new ArrayList<>();
|
private List<MatOfPoint> filteredContours = new ArrayList<>();
|
||||||
private Comparator<RotatedRect> sortByCentermostComparator = Comparator.comparingDouble(this::calcDistance);
|
private Comparator<RotatedRect> sortByCentermostComparator = Comparator.comparingDouble(this::calcDistance);
|
||||||
|
private Comparator<MatOfPoint> sortByMomentsX = Comparator.comparingDouble(this::calcMomentsX);
|
||||||
private List<RotatedRect> finalCountours = new ArrayList<>();
|
private List<RotatedRect> finalCountours = new ArrayList<>();
|
||||||
private Mat intersectMatA = new Mat();
|
private MatOfPoint2f intersectMatA = new MatOfPoint2f();
|
||||||
private Mat intersectMatB = new Mat();
|
private MatOfPoint2f intersectMatB = new MatOfPoint2f();
|
||||||
|
|
||||||
CVProcess(CameraValues cameraValues) {
|
CVProcess(CameraValues cameraValues) {
|
||||||
this.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) {
|
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.cvtColor(srcImage, hsvImage, Imgproc.COLOR_RGB2HSV, 3);
|
||||||
|
Imgproc.blur(hsvImage, hsvImage, blur);
|
||||||
Core.inRange(hsvImage, hsvLower, hsvUpper, dst);
|
Core.inRange(hsvImage, hsvLower, hsvUpper, dst);
|
||||||
if (shouldErode) {
|
if (shouldErode) {
|
||||||
Imgproc.erode(dst, dst, kernel);
|
Imgproc.erode(dst, dst, kernel);
|
||||||
@@ -57,20 +62,22 @@ public class CVProcess {
|
|||||||
for (MatOfPoint Contour : inputContours) {
|
for (MatOfPoint Contour : inputContours) {
|
||||||
try {
|
try {
|
||||||
double contourArea = Imgproc.contourArea(Contour);
|
double contourArea = Imgproc.contourArea(Contour);
|
||||||
double minArea = (MathHandler.sigmoid(area.get(0)) * cameraValues.ImageArea) / 100;
|
double AreaRatio = (contourArea / cameraValues.ImageArea)*100;
|
||||||
double maxArea = (MathHandler.sigmoid(area.get(1)) * cameraValues.ImageArea) / 100;
|
double minArea = (MathHandler.sigmoid(area.get(0)));
|
||||||
if (contourArea <= minArea || contourArea >= maxArea) {
|
double maxArea = (MathHandler.sigmoid(area.get(1)));
|
||||||
|
if (AreaRatio < minArea || AreaRatio > maxArea) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray()));
|
var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray()));
|
||||||
|
|
||||||
var targetFullness = contourArea;
|
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;
|
double maxExtent = (double) (extent.get(1) * rect.size.area()) / 100;
|
||||||
if (targetFullness <= minExtent || contourArea >= maxExtent) {
|
if (targetFullness <= minExtent || contourArea >= maxExtent) {
|
||||||
continue;
|
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)) {
|
if (aspectRatio < ratio.get(0) || aspectRatio > ratio.get(1)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -86,7 +93,10 @@ public class CVProcess {
|
|||||||
private double calcDistance(RotatedRect rect) {
|
private double calcDistance(RotatedRect rect) {
|
||||||
return FastMath.sqrt(FastMath.pow(cameraValues.CenterX - rect.center.x, 2) + FastMath.pow(cameraValues.CenterY - rect.center.y, 2));
|
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<RotatedRect> inputRects, String sortMode) {
|
RotatedRect sortTargetsToOne(List<RotatedRect> inputRects, String sortMode) {
|
||||||
switch (sortMode) {
|
switch (sortMode) {
|
||||||
case "Largest":
|
case "Largest":
|
||||||
@@ -111,6 +121,7 @@ public class CVProcess {
|
|||||||
List<RotatedRect> groupTargets(List<MatOfPoint> inputContours, String intersectionPoint, String targetGroup) {
|
List<RotatedRect> groupTargets(List<MatOfPoint> inputContours, String intersectionPoint, String targetGroup) {
|
||||||
finalCountours.clear();
|
finalCountours.clear();
|
||||||
if (!targetGroup.equals("Single")) {
|
if (!targetGroup.equals("Single")) {
|
||||||
|
inputContours.sort(sortByMomentsX);
|
||||||
for (var i = 0; i < inputContours.size(); i++) {
|
for (var i = 0; i < inputContours.size(); i++) {
|
||||||
List<Point> FinalContourList = new ArrayList<>(inputContours.get(i).toList());
|
List<Point> FinalContourList = new ArrayList<>(inputContours.get(i).toList());
|
||||||
for (var c = 0; c < (targetGrouping.get(targetGroup) - 1); c++) {
|
for (var c = 0; c < (targetGrouping.get(targetGroup) - 1); c++) {
|
||||||
@@ -157,24 +168,20 @@ public class CVProcess {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Imgproc.fitLine(ContourOne, intersectMatA, Imgproc.CV_DIST_L2, 0, 0.01, 0.01);
|
intersectMatA.fromArray(ContourOne.toArray());
|
||||||
Imgproc.fitLine(ContourTwo, intersectMatB, Imgproc.CV_DIST_L2, 0, 0.01, 0.01);
|
intersectMatB.fromArray(ContourTwo.toArray());
|
||||||
double vxA = intersectMatA.get(0, 0)[0];
|
RotatedRect a = Imgproc.fitEllipse(intersectMatA);
|
||||||
double vyA = intersectMatA.get(1, 0)[0];
|
RotatedRect b = Imgproc.fitEllipse(intersectMatB);
|
||||||
double x0A = intersectMatA.get(2, 0)[0];
|
double mA = MathHandler.toSlope(a.angle);
|
||||||
double y0A = intersectMatA.get(3, 0)[0];
|
double mB = MathHandler.toSlope(b.angle);
|
||||||
double mA = vyA / vxA;
|
double x0A = a.center.x;
|
||||||
double vxB = intersectMatB.get(0, 0)[0];
|
double y0A = a.center.y;
|
||||||
double vyB = intersectMatB.get(1, 0)[0];
|
double x0B = b.center.x;
|
||||||
double x0B = intersectMatB.get(2, 0)[0];
|
double y0B = b.center.y;
|
||||||
double y0B = intersectMatB.get(3, 0)[0];
|
|
||||||
double mB = vyB / vxB;
|
|
||||||
double bA = y0A - (mA*x0A);
|
|
||||||
double bB = y0B - (mB*x0B);
|
|
||||||
double intersectionX = ((mA * x0A) - y0A - (mB * x0B) + y0B )/ (mA - mB);
|
double intersectionX = ((mA * x0A) - y0A - (mB * x0B) + y0B )/ (mA - mB);
|
||||||
double intersectionY = (mA * (intersectionX - x0A)) + y0A;
|
double intersectionY = (mA * (intersectionX - x0A)) + y0A;
|
||||||
double massX = intersectionX + 1;
|
double massX = (x0A + x0B) / 2;
|
||||||
double massY = intersectionY + ((mA + bA + mB +bB) / 2);
|
double massY = (y0A + y0B) / 2;
|
||||||
switch (IntersectionPoint) {
|
switch (IntersectionPoint) {
|
||||||
case "Up": {
|
case "Up": {
|
||||||
if (intersectionY < massY) {
|
if (intersectionY < massY) {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public class VisionProcess implements Runnable {
|
|||||||
private Mat hsvThreshMat = new Mat();
|
private Mat hsvThreshMat = new Mat();
|
||||||
private Mat streamOutputMat = new Mat();
|
private Mat streamOutputMat = new Mat();
|
||||||
private Scalar contourRectColor = new Scalar(255, 0, 0);
|
private Scalar contourRectColor = new Scalar(255, 0, 0);
|
||||||
|
private Scalar BoxRectColor = new Scalar(0, 0, 233);
|
||||||
private long timeStamp = 0;
|
private long timeStamp = 0;
|
||||||
|
|
||||||
public VisionProcess(Camera processCam) {
|
public VisionProcess(Camera processCam) {
|
||||||
@@ -103,9 +104,12 @@ public class VisionProcess implements Runnable {
|
|||||||
List<MatOfPoint> drawnContour = new ArrayList<>();
|
List<MatOfPoint> drawnContour = new ArrayList<>();
|
||||||
Point[] vertices = new Point[4];
|
Point[] vertices = new Point[4];
|
||||||
contourRect.points(vertices);
|
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.drawContours(inputMat, drawnContour, 0, contourRectColor, 3);
|
||||||
Imgproc.circle(inputMat, contourRect.center, 3, contourRectColor);
|
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) {
|
private void updateNetworkTables(PipelineResult pipelineResult) {
|
||||||
|
|||||||
Reference in New Issue
Block a user