mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Added enums, msgpack - new ui intergration
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package com.chameleonvision.vision;
|
||||
|
||||
public enum Orientation {
|
||||
Normal,Inverted//TODO add 90 and 270 deg rotation?
|
||||
}
|
||||
@@ -6,20 +6,20 @@ import java.util.List;
|
||||
public class Pipeline {
|
||||
public int exposure = 50;
|
||||
public int brightness = 50;
|
||||
public String orientation = "Normal";
|
||||
public Orientation orientation = Orientation.Normal;
|
||||
public List<Integer> hue = Arrays.asList(50, 180);
|
||||
public List<Integer> saturation = Arrays.asList(50, 255);
|
||||
public List<Integer> value = Arrays.asList(50, 255);
|
||||
public boolean erode = false;
|
||||
public boolean dilate = false;
|
||||
public List<Integer> area = Arrays.asList(0, 100);
|
||||
public List<Double> ratio = Arrays.asList(0D, 20D);
|
||||
public List<Float> area = Arrays.asList(0f, 100f);
|
||||
public List<Float> ratio = Arrays.asList(0f, 20f);
|
||||
public List<Integer> extent = Arrays.asList(0, 100);
|
||||
public int is_binary = 0;
|
||||
public String sort_mode = "Largest";
|
||||
public String target_group = "Single";
|
||||
public String target_intersection = "Up";
|
||||
public boolean isBinary = false;
|
||||
public SortMode sortMode = SortMode.Largest;
|
||||
public TargetGroup targetGroup = TargetGroup.Single;
|
||||
public TargetIntersection targetIntersection = TargetIntersection.Up;
|
||||
public double M = 1;
|
||||
public double B = 0;
|
||||
public boolean is_calibrated = false;
|
||||
public boolean isCalibrated = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.chameleonvision.vision;
|
||||
|
||||
public enum SortMode {
|
||||
Largest,Smallest,Highest,Lowest,Rightmost,Leftmost,Centermost
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.chameleonvision.vision;
|
||||
|
||||
public enum TargetGroup {
|
||||
Single,Dual,Triple,Quadruple,Quintuple
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.chameleonvision.vision;
|
||||
|
||||
public enum TargetIntersection {
|
||||
None,Up,Down,Left,Right
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import java.util.stream.IntStream;
|
||||
|
||||
public class Camera {
|
||||
|
||||
private static final double DEFAULT_FOV = 60.8;
|
||||
private static final float DEFAULT_FOV = 60.8f;
|
||||
private static final int MINIMUM_FPS = 30;
|
||||
private static final int MINIMUM_WIDTH = 320;
|
||||
private static final int MINIMUM_HEIGHT = 200;
|
||||
@@ -29,7 +29,7 @@ public class Camera {
|
||||
private final CvSink cvSink;
|
||||
private final Object cvSourceLock = new Object();
|
||||
private CvSource cvSource;
|
||||
private double FOV;
|
||||
private float FOV;
|
||||
private CameraValues camVals;
|
||||
private CamVideoMode camVideoMode;
|
||||
private int currentPipelineIndex;
|
||||
@@ -39,23 +39,23 @@ public class Camera {
|
||||
this(cameraName, DEFAULT_FOV);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, double fov) {
|
||||
public Camera(String cameraName, float fov) {
|
||||
this(cameraName,CameraManager.AllUsbCameraInfosByName.get(cameraName), fov);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov) {
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, float fov) {
|
||||
this(cameraName ,usbCamInfo, fov, new HashMap<>(), 0);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, double fov, int videoModeIndex) {
|
||||
public Camera(String cameraName, float fov, int videoModeIndex) {
|
||||
this(cameraName, fov, new HashMap<>(), videoModeIndex);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, double fov, HashMap<Integer, Pipeline> pipelines, int videoModeIndex) {
|
||||
public Camera(String cameraName, float fov, HashMap<Integer, Pipeline> pipelines, int videoModeIndex) {
|
||||
this(cameraName, CameraManager.AllUsbCameraInfosByName.get(cameraName), fov, pipelines, videoModeIndex);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, double fov, HashMap<Integer, Pipeline> pipelines, int videoModeIndex) {
|
||||
public Camera(String cameraName, UsbCameraInfo usbCamInfo, float fov, HashMap<Integer, Pipeline> pipelines, int videoModeIndex) {
|
||||
FOV = fov;
|
||||
name = cameraName;
|
||||
path = usbCamInfo.path;
|
||||
@@ -158,11 +158,11 @@ public class Camera {
|
||||
.orElse(-1);
|
||||
}
|
||||
|
||||
public double getFOV() {
|
||||
public float getFOV() {
|
||||
return FOV;
|
||||
}
|
||||
|
||||
public void setFOV(double fov) {
|
||||
public void setFOV(float fov) {
|
||||
FOV = fov;
|
||||
camVals = new CameraValues(this);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public class CameraDeserializer implements JsonDeserializer<Camera> {
|
||||
@Override
|
||||
public Camera deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
|
||||
var jsonObj = jsonElement.getAsJsonObject();
|
||||
var camFOV = jsonObj.get("FOV").getAsDouble();
|
||||
var camFOV = jsonObj.get("FOV").getAsFloat();
|
||||
var camName = jsonObj.get("name").getAsString();
|
||||
var videoModeIndex = jsonObj.get("resolution").getAsInt();
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.apache.commons.math3.util.FastMath;
|
||||
public class CameraValues {
|
||||
public final int ImageWidth;
|
||||
public final int ImageHeight;
|
||||
public final double FOV;
|
||||
public final float FOV;
|
||||
public final double ImageArea;
|
||||
public final double CenterX;
|
||||
public final double CenterY;
|
||||
@@ -24,7 +24,7 @@ public class CameraValues {
|
||||
this(camera.getVideoMode().width, camera.getVideoMode().height, camera.getFOV());
|
||||
}
|
||||
|
||||
public CameraValues(int imageWidth, int imageHeight, double fov) {
|
||||
public CameraValues(int imageWidth, int imageHeight, float fov) {
|
||||
ImageWidth = imageWidth;
|
||||
ImageHeight = imageHeight;
|
||||
FOV = fov;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.chameleonvision.vision.process;
|
||||
|
||||
import com.chameleonvision.vision.SortMode;
|
||||
import com.chameleonvision.vision.TargetGroup;
|
||||
import com.chameleonvision.vision.TargetIntersection;
|
||||
import com.chameleonvision.vision.camera.CameraValues;
|
||||
import com.chameleonvision.util.MathHandler;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
@@ -14,13 +17,6 @@ import java.util.*;
|
||||
public class CVProcess {
|
||||
|
||||
private final CameraValues cameraValues;
|
||||
private HashMap<String, Integer> targetGrouping = new HashMap<>() {{
|
||||
put("Single", 1);
|
||||
put("Dual", 2);
|
||||
put("Triple", 3);
|
||||
put("Quadruple", 4);
|
||||
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();
|
||||
@@ -58,7 +54,7 @@ public class CVProcess {
|
||||
return foundContours;
|
||||
}
|
||||
|
||||
List<MatOfPoint> filterContours(List<MatOfPoint> inputContours, List<Integer> area, List<Double> ratio, List<Integer> extent) {
|
||||
List<MatOfPoint> filterContours(List<MatOfPoint> inputContours, List<Float> area, List<Float> ratio, List<Integer> extent) {
|
||||
for (MatOfPoint Contour : inputContours) {
|
||||
try {
|
||||
double contourArea = Imgproc.contourArea(Contour);
|
||||
@@ -97,34 +93,34 @@ public class CVProcess {
|
||||
Moments m = Imgproc.moments(c);
|
||||
return (m.get_m10()/m.get_m00());
|
||||
}
|
||||
RotatedRect sortTargetsToOne(List<RotatedRect> inputRects, String sortMode) {
|
||||
RotatedRect sortTargetsToOne(List<RotatedRect> inputRects, SortMode sortMode) {
|
||||
switch (sortMode) {
|
||||
case "Largest":
|
||||
case Largest:
|
||||
return Collections.max(inputRects, Comparator.comparing(rect -> rect.size.area()));
|
||||
case "Smallest":
|
||||
case Smallest:
|
||||
return Collections.min(inputRects, Comparator.comparing(rect -> rect.size.area()));
|
||||
case "Highest":
|
||||
case Highest:
|
||||
return Collections.min(inputRects, Comparator.comparing(rect -> rect.center.y));
|
||||
case "Lowest":
|
||||
case Lowest:
|
||||
return Collections.max(inputRects, Comparator.comparing(rect -> rect.center.y));
|
||||
case "Leftmost":
|
||||
case Leftmost:
|
||||
return Collections.min(inputRects, Comparator.comparing(rect -> rect.center.x));
|
||||
case "Rightmost":
|
||||
case Rightmost:
|
||||
return Collections.max(inputRects, Comparator.comparing(rect -> rect.center.x));
|
||||
case "Centermost":
|
||||
case Centermost:
|
||||
return Collections.min(inputRects, sortByCentermostComparator);
|
||||
default:
|
||||
return inputRects.get(0); // default to whatever the first contour is, but this should never happen
|
||||
}
|
||||
}
|
||||
|
||||
List<RotatedRect> groupTargets(List<MatOfPoint> inputContours, String intersectionPoint, String targetGroup) {
|
||||
List<RotatedRect> groupTargets(List<MatOfPoint> inputContours, TargetIntersection intersectionPoint, TargetGroup targetGroup) {
|
||||
finalCountours.clear();
|
||||
if (!targetGroup.equals("Single")) {
|
||||
if (!targetGroup.equals(TargetGroup.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++) {
|
||||
for (var c = 0; c < targetGroup.ordinal(); c++) {
|
||||
try {
|
||||
MatOfPoint firstContour = inputContours.get(i + c);
|
||||
MatOfPoint secondContour = inputContours.get(i + c + 1);
|
||||
@@ -163,8 +159,8 @@ public class CVProcess {
|
||||
return finalCountours;
|
||||
}
|
||||
|
||||
private boolean isIntersecting(MatOfPoint ContourOne, MatOfPoint ContourTwo, String IntersectionPoint) {
|
||||
if (IntersectionPoint.equals("None")) {
|
||||
private boolean isIntersecting(MatOfPoint ContourOne, MatOfPoint ContourTwo, TargetIntersection intersectionPoint) {
|
||||
if (intersectionPoint.equals(TargetIntersection.None)) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
@@ -182,26 +178,26 @@ public class CVProcess {
|
||||
double intersectionY = (mA * (intersectionX - x0A)) + y0A;
|
||||
double massX = (x0A + x0B) / 2;
|
||||
double massY = (y0A + y0B) / 2;
|
||||
switch (IntersectionPoint) {
|
||||
case "Up": {
|
||||
switch (intersectionPoint) {
|
||||
case Up: {
|
||||
if (intersectionY < massY) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Down": {
|
||||
case Down: {
|
||||
if (intersectionY > massY) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Left": {
|
||||
case Left: {
|
||||
if (intersectionX < massX) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Right": {
|
||||
case Right: {
|
||||
if (intersectionX > massX) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.chameleonvision.vision.process;
|
||||
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.Orientation;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.vision.camera.Camera;
|
||||
import com.chameleonvision.web.ServerHandler;
|
||||
@@ -135,7 +136,7 @@ public class VisionProcess implements Runnable {
|
||||
if (currentPipeline == null) {
|
||||
return pipelineResult;
|
||||
}
|
||||
if (!currentPipeline.orientation.equals("Normal")) {
|
||||
if (currentPipeline.orientation.equals(Orientation.Inverted)) {
|
||||
Core.flip(inputImage, inputImage, -1);
|
||||
}
|
||||
if (ntDriverModeEntry.getBoolean(false)) {
|
||||
@@ -147,7 +148,7 @@ public class VisionProcess implements Runnable {
|
||||
|
||||
cvProcess.hsvThreshold(inputImage, hsvThreshMat, hsvLower, hsvUpper, currentPipeline.erode, currentPipeline.dilate);
|
||||
|
||||
if (currentPipeline.is_binary == 1) {
|
||||
if (currentPipeline.isBinary == true) {
|
||||
Imgproc.cvtColor(hsvThreshMat, outputImage, Imgproc.COLOR_GRAY2BGR, 3);
|
||||
} else {
|
||||
inputImage.copyTo(outputImage);
|
||||
@@ -156,13 +157,13 @@ public class VisionProcess implements Runnable {
|
||||
if (foundContours.size() > 0) {
|
||||
filteredContours = cvProcess.filterContours(foundContours, currentPipeline.area, currentPipeline.ratio, currentPipeline.extent);
|
||||
if (filteredContours.size() > 0) {
|
||||
groupedContours = cvProcess.groupTargets(filteredContours, currentPipeline.target_intersection, currentPipeline.target_group);
|
||||
groupedContours = cvProcess.groupTargets(filteredContours, currentPipeline.targetIntersection, currentPipeline.targetGroup);
|
||||
if (groupedContours.size() > 0) {
|
||||
var finalRect = cvProcess.sortTargetsToOne(groupedContours, currentPipeline.sort_mode);
|
||||
var finalRect = cvProcess.sortTargetsToOne(groupedContours, currentPipeline.sortMode);
|
||||
// System.out.printf("Largest Contour Area: %.2f\n", finalRect.size.area());
|
||||
pipelineResult.RawPoint = finalRect;
|
||||
pipelineResult.IsValid = true;
|
||||
if (!currentPipeline.is_calibrated) {
|
||||
if (!currentPipeline.isCalibrated) {
|
||||
pipelineResult.CalibratedX = camera.getCamVals().CenterX;
|
||||
pipelineResult.CalibratedY = camera.getCamVals().CenterY;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user