mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Begin work on VisionProcess, refinement of CVPipeline interactions
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
package com.chameleonvision.classabstraction;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.USBCameraProcess;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.util.FileHelper;
|
||||
import com.chameleonvision.vision.camera.CameraDeserializer;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
import edu.wpi.cscore.UsbCameraInfo;
|
||||
import org.opencv.videoio.VideoCapture;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class VisionManager {
|
||||
|
||||
private static final Path CamConfigPath = Paths.get(SettingsManager.SettingsPath.toString(), "cameras");
|
||||
|
||||
public static final LinkedHashMap<String, UsbCameraInfo> UsbCameraInfosByCameraName = new LinkedHashMap<>();
|
||||
public static final LinkedHashMap<String, VisionProcess> VisionProcessesByCameraName = new LinkedHashMap<>();
|
||||
|
||||
|
||||
public static boolean initializeSources() {
|
||||
int suffix = 0;
|
||||
for (UsbCameraInfo info : UsbCamera.enumerateUsbCameras()) {
|
||||
VideoCapture cap = new VideoCapture(info.dev);
|
||||
if (cap.isOpened()) {
|
||||
cap.release();
|
||||
String name = info.name;
|
||||
while (UsbCameraInfosByCameraName.containsKey(name)) {
|
||||
suffix++;
|
||||
name = String.format("%s (%d)", name, suffix);
|
||||
}
|
||||
UsbCameraInfosByCameraName.put(name, info);
|
||||
}
|
||||
}
|
||||
|
||||
if (UsbCameraInfosByCameraName.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileHelper.CheckPath(CamConfigPath);
|
||||
UsbCameraInfosByCameraName.forEach((cameraName, cameraInfo) -> {
|
||||
Path cameraConfigPath = Paths.get(CamConfigPath.toString(), String.format("%s.json", cameraName));
|
||||
File cameraConfigFile = new File(cameraConfigPath.toString());
|
||||
if (cameraConfigFile.exists() && cameraConfigFile.length() != 0) {
|
||||
try {
|
||||
Gson gson = new GsonBuilder()().registerTypeAdapter(USBCameraProcess.class, new CameraDeserializer())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
public static void initializeProcesses() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.chameleonvision.classabstraction;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraProcess;
|
||||
import com.chameleonvision.classabstraction.pipeline.CVPipeline;
|
||||
import com.chameleonvision.classabstraction.pipeline.CVPipelineSettings;
|
||||
import com.chameleonvision.classabstraction.pipeline.DriverVisionPipeline;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class VisionProcess {
|
||||
|
||||
private final CameraProcess cameraProcess;
|
||||
private final List<CVPipeline> pipelines = new ArrayList<>();
|
||||
private CVPipeline currentPipeline;
|
||||
|
||||
private final CVPipelineSettings driverVisionSettings = new CVPipelineSettings();
|
||||
|
||||
public VisionProcess(CameraProcess cameraProcess) {
|
||||
this.cameraProcess = cameraProcess;
|
||||
|
||||
pipelines.add(new DriverVisionPipeline(() -> driverVisionSettings));
|
||||
setPipeline(pipelines.get(0));
|
||||
}
|
||||
|
||||
public void setPipeline(int pipelineIndex) {
|
||||
CVPipeline newPipeline = pipelines.get(pipelineIndex);
|
||||
if (newPipeline != null) {
|
||||
setPipeline(newPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPipeline(CVPipeline pipeline) {
|
||||
currentPipeline = pipeline;
|
||||
currentPipeline.initPipeline(cameraProcess);
|
||||
}
|
||||
|
||||
public CVPipeline getCurrentPipeline() {
|
||||
return currentPipeline;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
public class CameraConfig {
|
||||
public double FOV;
|
||||
public String Path;
|
||||
public String Name;
|
||||
public String Nickname;
|
||||
public com.chameleonvision.vision.camera.StreamDivisor StreamDivisor;
|
||||
// public
|
||||
}
|
||||
@@ -14,11 +14,11 @@ public class USBCameraProcess implements CameraProcess {
|
||||
private Mat imageBuffer = new Mat();
|
||||
public final CameraProperties properties;
|
||||
|
||||
public USBCameraProcess(UsbCamera camera, double fov) {
|
||||
public USBCameraProcess(UsbCamera camera, CameraConfig config) {
|
||||
baseCamera = camera;
|
||||
cvSink = CameraServer.getInstance().getVideo(baseCamera);
|
||||
VideoMode vidMode = new VideoMode(VideoMode.PixelFormat.kYUYV, 640, 480, 60);
|
||||
properties = new CameraProperties(baseCamera, fov);
|
||||
properties = new CameraProperties(baseCamera, config.FOV);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,7 +41,7 @@ public class USBCameraProcess implements CameraProcess {
|
||||
try {
|
||||
baseCamera.setExposureManual(exposure);
|
||||
} catch (VideoException e) {
|
||||
System.err.println("USBCameraProcess Does not support exposure change");
|
||||
System.err.println("Current camera does not support exposure change");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class USBCameraProcess implements CameraProcess {
|
||||
try {
|
||||
baseCamera.setBrightness(brightness);
|
||||
} catch (VideoException e) {
|
||||
System.err.println("USBCameraProcess Does not support brightness change");
|
||||
System.err.println("Current camera does not support brightness change");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,29 @@ package com.chameleonvision.classabstraction.pipeline;
|
||||
import com.chameleonvision.classabstraction.camera.CameraProcess;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <R> Pipeline result type
|
||||
*/
|
||||
public abstract class CVPipeline<R extends CVPipelineResult, S extends CVPipelineSettings> {
|
||||
protected S settings;
|
||||
private Mat inputMat;
|
||||
protected Mat outputMat;
|
||||
CameraProcess cameraProcess;
|
||||
final Supplier<S> settingsSupplier;
|
||||
|
||||
public CVPipeline(S settings) {
|
||||
this.settings = settings;
|
||||
public CVPipeline(Supplier<S> settingsSupplier) {
|
||||
this.settingsSupplier = settingsSupplier;
|
||||
}
|
||||
|
||||
abstract void initPipeline(CameraProcess camera);
|
||||
abstract R runPipeline(Mat inputMat);
|
||||
public S getSettings() {
|
||||
return settingsSupplier.get();
|
||||
}
|
||||
|
||||
public void initPipeline(CameraProcess camera) {
|
||||
cameraProcess = camera;
|
||||
cameraProcess.setExposure((int) getSettings().exposure);
|
||||
cameraProcess.setBrightness((int) getSettings().brightness);
|
||||
}
|
||||
abstract public R runPipeline(Mat inputMat);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraProcess;
|
||||
import com.chameleonvision.classabstraction.camera.CameraStaticProperties;
|
||||
import com.chameleonvision.classabstraction.pipeline.pipes.*;
|
||||
import com.chameleonvision.vision.ImageRotation;
|
||||
@@ -9,29 +8,26 @@ import org.opencv.core.*;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.chameleonvision.classabstraction.pipeline.CVPipeline2d.*;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class CVPipeline2d extends CVPipeline<CVPipeline2d.CVPipeline2dResult, CVPipeline2d.CVPipeline2dSettings> {
|
||||
|
||||
private CameraProcess cameraProcess;
|
||||
public class CVPipeline2d extends CVPipeline<CVPipeline2dResult, CVPipeline2dSettings> {
|
||||
|
||||
private Mat rawCameraMat = new Mat();
|
||||
private Mat hsvOutputMat = new Mat();
|
||||
|
||||
public CVPipeline2d(CVPipeline2dSettings settings) {
|
||||
super(settings);
|
||||
public CVPipeline2d(Supplier<CVPipeline2dSettings> settingsSupplier) {
|
||||
super(settingsSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
void initPipeline(CameraProcess cam) {
|
||||
cameraProcess = cam;
|
||||
}
|
||||
|
||||
@Override
|
||||
CVPipeline2d.CVPipeline2dResult runPipeline(Mat inputMat) {
|
||||
public CVPipeline2dResult runPipeline(Mat inputMat) {
|
||||
long totalProcessTimeNanos = 0;
|
||||
StringBuilder procTimeStringBuilder = new StringBuilder();
|
||||
|
||||
var settings = settingsSupplier.get();
|
||||
CameraStaticProperties camProps = cameraProcess.getProperties().staticProperties;
|
||||
|
||||
inputMat.copyTo(rawCameraMat);
|
||||
@@ -123,16 +119,9 @@ public class CVPipeline2d extends CVPipeline<CVPipeline2d.CVPipeline2dResult, CV
|
||||
return new CVPipeline2dResult(collect2dTargetsResult.getLeft(), draw2dContoursResult.getLeft());
|
||||
}
|
||||
|
||||
public static class CVPipeline2dSettings extends CVPipelineSettings {
|
||||
double dualTargetCalibrationM = 1;
|
||||
double dualTargetCalibrationB = 0;
|
||||
}
|
||||
|
||||
public static class CVPipeline2dResult extends CVPipelineResult<Target> {
|
||||
public CVPipeline2dResult(List<Target> targets, Mat outputMat) {
|
||||
this.targets = targets;
|
||||
this.hasTarget = !targets.isEmpty();
|
||||
this.outputMat = outputMat;
|
||||
super(targets, outputMat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
import com.chameleonvision.vision.CalibrationMode;
|
||||
import com.chameleonvision.vision.SortMode;
|
||||
import com.chameleonvision.vision.TargetGroup;
|
||||
import com.chameleonvision.vision.TargetIntersection;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class CVPipeline2dSettings extends CVPipelineSettings {
|
||||
public List<Number> hue = Arrays.asList(50, 180);
|
||||
public List<Number> saturation = Arrays.asList(50, 255);
|
||||
public List<Number> value = Arrays.asList(50, 255);
|
||||
public boolean erode = false;
|
||||
public boolean dilate = false;
|
||||
public List<Number> area = Arrays.asList(0.0, 100.0);
|
||||
public List<Number> ratio = Arrays.asList(0.0, 20.0);
|
||||
public List<Number> extent = Arrays.asList(0, 100);
|
||||
public Number speckle = 5;
|
||||
public boolean isBinary = false;
|
||||
public SortMode sortMode = SortMode.Largest;
|
||||
public TargetGroup targetGroup = TargetGroup.Single;
|
||||
public TargetIntersection targetIntersection = TargetIntersection.Up;
|
||||
public List<Number> point = Arrays.asList(0, 0);
|
||||
public CalibrationMode calibrationMode = CalibrationMode.None;
|
||||
public double dualTargetCalibrationM = 1;
|
||||
public double dualTargetCalibrationB = 0;
|
||||
}
|
||||
@@ -1,33 +1,33 @@
|
||||
//package com.chameleonvision.classabstraction.pipeline;
|
||||
//
|
||||
//import org.opencv.core.Mat;
|
||||
//
|
||||
//public class CVPipeline3d extends CVPipeline<CVPipeline3d.CVPipeline3dResult> {
|
||||
//
|
||||
// public CVPipeline3d(CVPipelineSettings settings) {
|
||||
// super(settings);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// void initPipeline() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// CVPipeline3d.CVPipeline3dResult runPipeline(Mat inputMat) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// Mat getOutputMat() {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public static class CVPipeline3dSettings extends CVPipelineSettings {
|
||||
// }
|
||||
//
|
||||
// public static class CVPipeline3dResult {
|
||||
//
|
||||
// }
|
||||
//
|
||||
//}
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraProcess;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.chameleonvision.classabstraction.pipeline.CVPipeline3d.*;
|
||||
|
||||
public class CVPipeline3d extends CVPipeline<CVPipeline3dResult, CVPipeline3dSettings> {
|
||||
|
||||
public CVPipeline3d(Supplier<CVPipeline3dSettings> settingsSupplier) {
|
||||
super(settingsSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CVPipeline3dResult runPipeline(Mat inputMat) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static class CVPipeline3dResult extends CVPipelineResult<Target3d> {
|
||||
public CVPipeline3dResult(List<Target3d> targets, Mat outputMat) {
|
||||
super(targets, outputMat);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Target3d {
|
||||
// TODO: Define 3d-specific target data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
public class CVPipeline3dSettings extends CVPipeline2dSettings {
|
||||
// TODO:
|
||||
}
|
||||
@@ -5,7 +5,13 @@ import org.opencv.core.Mat;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class CVPipelineResult<T> {
|
||||
List<T> targets;
|
||||
boolean hasTarget;
|
||||
Mat outputMat;
|
||||
public final List<T> targets;
|
||||
public final boolean hasTarget;
|
||||
public final Mat outputMat = new Mat();
|
||||
|
||||
public CVPipelineResult(List<T> targets, Mat outputMat) {
|
||||
this.targets = targets;
|
||||
hasTarget = targets != null && !targets.isEmpty();
|
||||
outputMat.copyTo(this.outputMat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,29 +2,10 @@ package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
import com.chameleonvision.vision.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public abstract class CVPipelineSettings {
|
||||
ImageFlipMode flipMode = ImageFlipMode.NONE;
|
||||
List<Number> hue = Arrays.asList(50, 180);
|
||||
List<Number> saturation = Arrays.asList(50, 255);
|
||||
List<Number> value = Arrays.asList(50, 255);
|
||||
boolean erode = false;
|
||||
boolean dilate = false;
|
||||
List<Number> area = Arrays.asList(0.0, 100.0);
|
||||
List<Number> ratio = Arrays.asList(0.0, 20.0);
|
||||
List<Number> extent = Arrays.asList(0, 100);
|
||||
Number speckle = 5;
|
||||
boolean isBinary = false;
|
||||
SortMode sortMode = SortMode.Largest;
|
||||
TargetGroup targetGroup = TargetGroup.Single;
|
||||
TargetIntersection targetIntersection = TargetIntersection.Up;
|
||||
List<Number> point = Arrays.asList(0,0);
|
||||
CalibrationMode calibrationMode = CalibrationMode.None;
|
||||
|
||||
String nickname = "";
|
||||
double exposure = 50.0;
|
||||
double brightness = 50.0;
|
||||
public class CVPipelineSettings {
|
||||
public ImageFlipMode flipMode = ImageFlipMode.NONE;
|
||||
public String nickname = "";
|
||||
public double exposure = 50.0;
|
||||
public double brightness = 50.0;
|
||||
}
|
||||
|
||||
@@ -3,26 +3,34 @@ package com.chameleonvision.classabstraction.pipeline;
|
||||
import com.chameleonvision.classabstraction.camera.CameraProcess;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
public class DriverVisionPipeline extends CVPipeline<DriverVisionPipeline.DriverPipelineResult, CVPipelineSettings> {
|
||||
public DriverVisionPipeline(CVPipelineSettings settings) {
|
||||
super(settings);
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.chameleonvision.classabstraction.pipeline.DriverVisionPipeline.*;
|
||||
|
||||
public class DriverVisionPipeline extends CVPipeline<DriverPipelineResult, CVPipelineSettings> {
|
||||
|
||||
public DriverVisionPipeline(Supplier<CVPipelineSettings> settingsSupplier) {
|
||||
super(settingsSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
void initPipeline(CameraProcess camera) {
|
||||
// TODO: set camera to driver mode
|
||||
public void initPipeline(CameraProcess camera) {
|
||||
camera.setBrightness((int) getSettings().brightness);
|
||||
camera.setExposure((int) getSettings().exposure);
|
||||
}
|
||||
|
||||
@Override
|
||||
DriverPipelineResult runPipeline(Mat inputMat) {
|
||||
return new DriverPipelineResult(inputMat);
|
||||
public DriverPipelineResult runPipeline(Mat inputMat) {
|
||||
|
||||
inputMat.copyTo(outputMat);
|
||||
|
||||
return new DriverPipelineResult(null, inputMat);
|
||||
}
|
||||
|
||||
public static class DriverPipelineResult extends CVPipelineResult<Void> {
|
||||
public DriverPipelineResult(Mat outputMat) {
|
||||
this.hasTarget = false;
|
||||
this.targets = null;
|
||||
outputMat.copyTo(this.outputMat);
|
||||
public DriverPipelineResult(List<Void> targets, Mat outputMat) {
|
||||
super(targets, outputMat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user