package com.chameleonvision.vision.process; import com.chameleonvision.vision.CameraValues; import org.jetbrains.annotations.NotNull; import org.opencv.core.*; import org.opencv.imgproc.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class VisionProcess { private HashMapTargetGrouping= new HashMap<>() {{ put("Single", 1); put("Dual", 2); put("Triple", 3); put("Quadruple", 4); put("Quintuple", 5); }}; private final CameraValues CamVals; VisionProcess(CameraValues camVals){ CamVals = camVals; } private Mat Kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5)); private Mat hsvImage = new Mat(); void HSVThreshold(Mat srcImage, Mat dst, @NotNull Scalar hsvLower, @NotNull Scalar hsvUpper, boolean shouldErode, boolean shouldDilate) { Imgproc.cvtColor(srcImage, hsvImage, Imgproc.COLOR_RGB2HSV,3); Core.inRange(hsvImage, hsvLower, hsvUpper, dst); if (shouldErode){ Imgproc.erode(dst, dst, Kernel); } if (shouldDilate){ Imgproc.dilate(dst, dst, Kernel); } hsvImage.release(); } private List FoundContours = new ArrayList<>(); private Mat binaryMat = new Mat(); List FindContours(Mat src) { src.copyTo(binaryMat); FoundContours.clear(); Imgproc.findContours(binaryMat, FoundContours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1); binaryMat.release(); return FoundContours; } private List FilteredContours = new ArrayList(); List FilterContours(List InputContours, List area, List ratio, List extent, String SortMode, String TargetIntersection, String TargetGrouping) { for (MatOfPoint Contour : InputContours){ try{ var contourArea = Imgproc.contourArea(Contour); double targetArea = (contourArea / CamVals.ImageArea) * 100; if (targetArea <= area.get(0) || targetArea >= area.get(1)){ continue; } var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray())); var targetFullness = (contourArea/rect.size.area())*100; if (targetFullness <= extent.get(0) || targetArea >= extent.get(1)){ continue; } var aspectRatio = rect.size.width / rect.size.height; if (aspectRatio <= ratio.get(0) || aspectRatio >= ratio.get(1)){ continue; } FilteredContours.add(Contour); } catch (Exception ignored) { } } return FilteredContours; } private List FinalCountours = new ArrayList<>(); public List GroupTargets(List InputContours, String IntersectionPoint, String TargetGroup) { FinalCountours.clear(); if (!TargetGroup.equals("Single")){ 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++){ try{ MatOfPoint firstContour = InputContours.get(i + c); MatOfPoint secondContour = InputContours.get(i+c+1); if (IsIntersecting(firstContour, secondContour, IntersectionPoint)){ FinalContourList.addAll(secondContour.toList()); } firstContour.release(); secondContour.release(); MatOfPoint2f contour = new MatOfPoint2f(); contour.fromList(FinalContourList); if (contour.cols() !=0 && contour.rows() != 0){ RotatedRect rect = Imgproc.minAreaRect(contour); FinalCountours.add(rect); } } catch (IndexOutOfBoundsException e){ FinalContourList.clear(); break; } } } } else { for (var i = 0; i < InputContours.size(); i++){ MatOfPoint2f contour = new MatOfPoint2f(); contour.fromArray(InputContours.get(i).toArray()); if (contour.cols() !=0 && contour.rows() != 0) { RotatedRect rect = Imgproc.minAreaRect(contour); FinalCountours.add(rect); } } } return FinalCountours; } private Mat intersectMatA = new Mat(); private Mat intersectMatB = new Mat(); private boolean IsIntersecting(MatOfPoint ContourOne, MatOfPoint ContourTwo, String IntersectionPoint) { if (IntersectionPoint.equals("None")){ 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 intersectionX = (mA * x0A) - y0A - (mB * x0B) + y0B / (mA - mB); double intersectionY = (mA * (intersectionX - x0A)) + y0A; switch (IntersectionPoint){ case "Up" :{ if (intersectionY < CamVals.CenterY){ return true; } break; } case "Down": { if (intersectionY > CamVals.CenterY){ return true; } break; } case "Left": { if (intersectionX < CamVals.CenterX){ return true; } break; } case "Right": { if (intersectionX > CamVals.CenterX){ return true; } break; } } return false; } catch (Exception e){ return false; } } }