mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-21 01:01:41 +00:00
Added Runnables for VisionProcess threads
This commit is contained in:
@@ -16,7 +16,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -28,7 +27,6 @@ public class VisionManager {
|
||||
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()) {
|
||||
@@ -48,19 +46,26 @@ public class VisionManager {
|
||||
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());
|
||||
// }
|
||||
}
|
||||
});
|
||||
// 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());
|
||||
//// }
|
||||
// }
|
||||
// })
|
||||
// TODO: implement new camera JSON loads
|
||||
return true;
|
||||
}
|
||||
|
||||
public void PipelineSerializer(List<CVPipelineSettings> list, Path path) throws IOException {
|
||||
File pipelineFile = new File(path.toString());
|
||||
ObjectMapper objectMapper = new ObjectMapper().enableDefaultTyping();
|
||||
objectMapper.writeValue(pipelineFile,list);
|
||||
}
|
||||
|
||||
|
||||
public static void initializeProcesses() {
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@ package com.chameleonvision.classabstraction;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraProcess;
|
||||
import com.chameleonvision.classabstraction.pipeline.CVPipeline;
|
||||
import com.chameleonvision.classabstraction.pipeline.CVPipelineResult;
|
||||
import com.chameleonvision.classabstraction.pipeline.CVPipelineSettings;
|
||||
import com.chameleonvision.classabstraction.pipeline.DriverVisionPipeline;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -14,6 +16,8 @@ public class VisionProcess {
|
||||
private final List<CVPipeline> pipelines = new ArrayList<>();
|
||||
private CVPipeline currentPipeline;
|
||||
|
||||
private final CameraFrameRunnable cameraFrameRunnable;
|
||||
|
||||
private final CVPipelineSettings driverVisionSettings = new CVPipelineSettings();
|
||||
|
||||
public VisionProcess(CameraProcess cameraProcess) {
|
||||
@@ -21,6 +25,8 @@ public class VisionProcess {
|
||||
|
||||
pipelines.add(new DriverVisionPipeline(() -> driverVisionSettings));
|
||||
setPipeline(pipelines.get(0));
|
||||
|
||||
cameraFrameRunnable = new CameraFrameRunnable();
|
||||
}
|
||||
|
||||
public void setPipeline(int pipelineIndex) {
|
||||
@@ -38,4 +44,42 @@ public class VisionProcess {
|
||||
public CVPipeline getCurrentPipeline() {
|
||||
return currentPipeline;
|
||||
}
|
||||
|
||||
protected class CameraFrameRunnable implements Runnable {
|
||||
private Mat cameraFrame = new Mat();
|
||||
private long timestampMicros;
|
||||
|
||||
private final Object frameLock = new Object();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(Thread.interrupted()) {
|
||||
var camData = cameraProcess.getFrame();
|
||||
synchronized (frameLock) {
|
||||
cameraFrame = camData.getLeft();
|
||||
}
|
||||
timestampMicros = camData.getRight();
|
||||
}
|
||||
}
|
||||
|
||||
public Mat getFrame() {
|
||||
return cameraFrame;
|
||||
}
|
||||
|
||||
public long getTimestampMicros() {
|
||||
return timestampMicros;
|
||||
}
|
||||
}
|
||||
|
||||
private class VisionThread implements Runnable {
|
||||
|
||||
private CVPipelineResult result;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(!Thread.interrupted()) {
|
||||
result = currentPipeline.runPipeline(cameraFrameRunnable.getFrame());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,9 @@ public interface CameraProcess {
|
||||
|
||||
/**
|
||||
* Get the next camera frame
|
||||
* @param frame the frame to copy the image into
|
||||
* @return a Pair of the captured image and how long it took to grab the frame (in uS)
|
||||
*/
|
||||
Pair<Mat, Long> getFrame(Mat frame);
|
||||
Pair<Mat, Long> getFrame();
|
||||
|
||||
/**
|
||||
* Set the exposure of the camera
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import com.chameleonvision.vision.camera.CameraManager;
|
||||
import com.chameleonvision.vision.camera.StreamDivisor;
|
||||
import com.chameleonvision.web.ServerHandler;
|
||||
import edu.wpi.cscore.CvSource;
|
||||
@@ -11,7 +10,6 @@ import org.opencv.core.Size;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
public class CameraStreamer {
|
||||
|
||||
private final CameraProcess cameraProcess;
|
||||
private final String name;
|
||||
private StreamDivisor divisor = StreamDivisor.NONE;
|
||||
@@ -27,7 +25,6 @@ public class CameraStreamer {
|
||||
cameraProcess.getProperties().staticProperties.imageHeight / divisor.value);
|
||||
}
|
||||
|
||||
|
||||
public void setDivisor(StreamDivisor newDivisor) {
|
||||
this.divisor = newDivisor;
|
||||
var camValues = cameraProcess.getProperties();
|
||||
@@ -42,9 +39,7 @@ public class CameraStreamer {
|
||||
ServerHandler.sendFullSettings();
|
||||
}
|
||||
|
||||
public void runStream() {
|
||||
var newFrame = cameraProcess.getFrame(streamBuffer);
|
||||
var image = newFrame.getLeft();
|
||||
public void runStream(Mat image) {
|
||||
if (divisor.value != 1) {
|
||||
var camVal = cameraProcess.getProperties().staticProperties;
|
||||
var newWidth = camVal.imageWidth / divisor.value;
|
||||
|
||||
@@ -28,13 +28,12 @@ public class USBCameraProcess implements CameraProcess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Mat, Long> getFrame(Mat frame) {
|
||||
public Pair<Mat, Long> getFrame() {
|
||||
Long deltaTime;
|
||||
synchronized (cvSink) {
|
||||
deltaTime = cvSink.grabFrame(imageBuffer) * 1000L;
|
||||
imageBuffer.copyTo(frame);
|
||||
}
|
||||
return Pair.of(frame, deltaTime);
|
||||
return Pair.of(imageBuffer, deltaTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,10 +8,12 @@ public abstract class CVPipelineResult<T> {
|
||||
public final List<T> targets;
|
||||
public final boolean hasTarget;
|
||||
public final Mat outputMat = new Mat();
|
||||
public final long processTime;
|
||||
|
||||
public CVPipelineResult(List<T> targets, Mat outputMat) {
|
||||
public CVPipelineResult(List<T> targets, Mat outputMat, long processTime) {
|
||||
this.targets = targets;
|
||||
hasTarget = targets != null && !targets.isEmpty();
|
||||
outputMat.copyTo(this.outputMat);
|
||||
this.processTime = processTime;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user