mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
redone grouped contours and fixed ratio slider
This commit is contained in:
@@ -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<MatOfPoint> foundContours = new ArrayList<>();
|
||||
private Mat binaryMat = new Mat();
|
||||
private List<MatOfPoint> filteredContours = new ArrayList<>();
|
||||
private Comparator<RotatedRect> sortByCentermostComparator = Comparator.comparingDouble(this::calcDistance);
|
||||
private Comparator<MatOfPoint> sortByMomentsX = Comparator.comparingDouble(this::calcMomentsX);
|
||||
private List<RotatedRect> 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<RotatedRect> inputRects, String sortMode) {
|
||||
switch (sortMode) {
|
||||
case "Largest":
|
||||
@@ -111,6 +121,7 @@ public class CVProcess {
|
||||
List<RotatedRect> groupTargets(List<MatOfPoint> inputContours, String intersectionPoint, String targetGroup) {
|
||||
finalCountours.clear();
|
||||
if (!targetGroup.equals("Single")) {
|
||||
inputContours.sort(sortByMomentsX);
|
||||
for (var i = 0; i < inputContours.size(); i++) {
|
||||
List<Point> 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) {
|
||||
|
||||
@@ -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<MatOfPoint> 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) {
|
||||
|
||||
Reference in New Issue
Block a user