Attempt further memory fixes, begin unit tests, fix DriverMode rotation

This commit is contained in:
Banks Troutman
2019-12-01 04:39:21 -05:00
parent daa51b78b3
commit a24e633ceb
17 changed files with 186 additions and 50 deletions

View File

@@ -1,7 +1,7 @@
package com.chameleonvision.config;
import com.chameleonvision.vision.VisionProcess;
import com.chameleonvision.vision.camera.USBCameraProperties;
import com.chameleonvision.vision.camera.USBCaptureProperties;
import com.chameleonvision.vision.enums.StreamDivisor;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -31,7 +31,7 @@ public class CameraJsonConfig {
}
public CameraJsonConfig(String path, String name) {
this.fov = USBCameraProperties.DEFAULT_FOV;
this.fov = USBCaptureProperties.DEFAULT_FOV;
this.path = path;
this.name = name;
this.nickname = name;
@@ -40,7 +40,7 @@ public class CameraJsonConfig {
}
public static CameraJsonConfig fromVisionProcess(VisionProcess process) {
USBCameraProperties camProps = process.getCamera().getProperties();
USBCaptureProperties camProps = process.getCamera().getProperties();
int videomode = camProps.getCurrentVideoModeIndex();
StreamDivisor streamDivisor = process.cameraStreamer.getDivisor();
return new CameraJsonConfig(camProps.getFOV(), camProps.path, camProps.name, camProps.getNickname(), videomode, streamDivisor);

View File

@@ -84,7 +84,7 @@ public class VisionManager {
CameraJsonConfig cameraJsonConfig = config.cameraConfig;
CameraCapture camera = new USBCameraCapture(cameraJsonConfig);
USBCameraCapture camera = new USBCameraCapture(cameraJsonConfig);
VisionProcess process = new VisionProcess(camera, cameraJsonConfig.name, config.pipelines);
process.pipelineManager.driverModePipeline.settings = config.drivermode;
visionProcesses.add(new VisionProcessManageable(i, cameraJsonConfig.name, process));
@@ -165,7 +165,7 @@ public class VisionManager {
currentUIVisionProcess.pipelineManager.saveDriverModeConfig();
}
private static List<HashMap> getCameraResolutionList(CameraCapture capture) {
private static List<HashMap> getCameraResolutionList(USBCameraCapture capture) {
return capture.getProperties().getVideoModes().stream().map(Helpers::VideoModeToHashMap).collect(Collectors.toList());
}

View File

@@ -5,6 +5,7 @@ import com.chameleonvision.config.ConfigManager;
import com.chameleonvision.util.LoopingRunnable;
import com.chameleonvision.vision.camera.CameraCapture;
import com.chameleonvision.vision.camera.CameraStreamer;
import com.chameleonvision.vision.camera.USBCameraCapture;
import com.chameleonvision.vision.pipeline.*;
import com.chameleonvision.web.SocketHandler;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -24,7 +25,7 @@ import java.util.concurrent.LinkedBlockingDeque;
public class VisionProcess {
private final CameraCapture cameraCapture;
private final USBCameraCapture cameraCapture;
private final CameraStreamerRunnable streamRunnable;
private final VisionProcessRunnable visionRunnable;
public final CameraStreamer cameraStreamer;
@@ -48,7 +49,7 @@ public class VisionProcess {
private NetworkTableEntry ntValidEntry;
private ObjectMapper objectMapper = new ObjectMapper();
VisionProcess(CameraCapture cameraCapture, String name, List<CVPipelineSettings> loadedPipelineSettings) {
VisionProcess(USBCameraCapture cameraCapture, String name, List<CVPipelineSettings> loadedPipelineSettings) {
this.cameraCapture = cameraCapture;
pipelineManager = new PipelineManager(this, loadedPipelineSettings);
@@ -218,7 +219,7 @@ public class VisionProcess {
return cameraCapture.getProperties().videoModes;
}
public CameraCapture getCamera() {
public USBCameraCapture getCamera() {
return cameraCapture;
}

View File

@@ -1,10 +1,11 @@
package com.chameleonvision.vision.camera;
import com.chameleonvision.vision.image.CaptureProperties;
import com.chameleonvision.vision.image.ImageCapture;
import edu.wpi.cscore.VideoMode;
public interface CameraCapture extends ImageCapture {
USBCameraProperties getProperties();
CaptureProperties getProperties();
VideoMode getCurrentVideoMode();

View File

@@ -16,10 +16,10 @@ public class CaptureStaticProperties {
public final double verticalFocalLength;
public final VideoMode mode;
public CaptureStaticProperties(VideoMode mode, int imageWidth, int imageHeight, double fov) {
public CaptureStaticProperties(VideoMode mode, double fov) {
this.mode = mode;
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
this.imageWidth = mode.width;
this.imageHeight = mode.height;
this.fov = fov;
imageArea = this.imageWidth * this.imageHeight;
centerX = ((double) this.imageWidth / 2) - 0.5;

View File

@@ -1,6 +1,7 @@
package com.chameleonvision.vision.camera;
import com.chameleonvision.config.CameraJsonConfig;
import com.chameleonvision.vision.image.CaptureProperties;
import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.UsbCamera;
import edu.wpi.cscore.VideoException;
@@ -13,19 +14,20 @@ public class USBCameraCapture implements CameraCapture {
private final UsbCamera baseCamera;
private final CvSink cvSink;
private Mat imageBuffer = new Mat();
private USBCameraProperties properties;
private USBCaptureProperties properties;
public USBCameraCapture(CameraJsonConfig config) {
baseCamera = new UsbCamera(config.name, config.path);
cvSink = CameraServer.getInstance().getVideo(baseCamera);
properties = new USBCameraProperties(baseCamera, config);
properties = new USBCaptureProperties(baseCamera, config);
int videoMode = properties.videoModes.size() - 1 <= config.videomode ? config.videomode : 0;
setVideoMode(videoMode);
}
@Override
public USBCameraProperties getProperties() {
public USBCaptureProperties getProperties() {
return properties;
}

View File

@@ -12,7 +12,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class USBCameraProperties extends CaptureProperties {
public class USBCaptureProperties extends com.chameleonvision.vision.image.CaptureProperties {
public static final double DEFAULT_FOV = 70;
private static final int DEFAULT_EXPOSURE = 50;
private static final int DEFAULT_BRIGHTNESS = 50;
@@ -40,7 +40,7 @@ public class USBCameraProperties extends CaptureProperties {
private String nickname;
private double FOV;
USBCameraProperties(UsbCamera baseCamera, CameraJsonConfig config) {
USBCaptureProperties(UsbCamera baseCamera, CameraJsonConfig config) {
FOV = config.fov;
name = config.name;
path = config.path;
@@ -70,7 +70,7 @@ public class USBCameraProperties extends CaptureProperties {
public void setFOV(double FOV) {
if (this.FOV != FOV) {
this.FOV = FOV;
staticProperties = new CaptureStaticProperties(staticProperties.mode, staticProperties.imageWidth, staticProperties.imageHeight, FOV);
staticProperties = new CaptureStaticProperties(staticProperties.mode, FOV);
}
}
@@ -93,7 +93,7 @@ public class USBCameraProperties extends CaptureProperties {
}
void updateVideoMode(VideoMode videoMode) {
staticProperties = new CaptureStaticProperties(videoMode, videoMode.width, videoMode.height, FOV);
staticProperties = new CaptureStaticProperties(videoMode, FOV);
}
public List<VideoMode> getVideoModes() {

View File

@@ -11,8 +11,8 @@ public class CaptureProperties {
protected CaptureProperties() {
}
public CaptureProperties(Mat staticImage, double fov) {
staticProperties = new CaptureStaticProperties(new VideoMode(0, staticImage.cols(), staticImage.rows(), 99999), staticImage.cols(), staticImage.rows(), fov);
public CaptureProperties(VideoMode videoMode, double fov) {
staticProperties = new CaptureStaticProperties(videoMode, fov);
}
public CaptureStaticProperties getStaticProperties() {

View File

@@ -1,5 +1,8 @@
package com.chameleonvision.vision.image;
import com.chameleonvision.vision.camera.CameraCapture;
import com.chameleonvision.vision.camera.USBCaptureProperties;
import edu.wpi.cscore.VideoMode;
import org.apache.commons.lang3.tuple.Pair;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
@@ -7,26 +10,67 @@ import org.opencv.imgcodecs.Imgcodecs;
import java.nio.file.Files;
import java.nio.file.Path;
public class StaticImageCapture implements ImageCapture {
public class StaticImageCapture implements CameraCapture {
private final Mat image = new Mat();
private Mat image = new Mat();
private final VideoMode fakeVideoMode;
private final com.chameleonvision.vision.image.CaptureProperties properties;
public StaticImageCapture(Path imagePath) {
this(imagePath, 70);
}
public StaticImageCapture(Path imagePath, double FOV) {
if (!Files.exists(imagePath)) throw new RuntimeException("Invalid path for image!");
Mat tempMat = new Mat();
try {
tempMat = Imgcodecs.imread(imagePath.toString());
} catch (Exception e) {
System.err.println("Failed to read image!");
} finally {
tempMat.copyTo(image);
Mat loadedImage = Imgcodecs.imread(imagePath.toString());
loadedImage.copyTo(image);
if (image.cols() > 0 && image.rows() > 0) {
fakeVideoMode = new VideoMode(VideoMode.PixelFormat.kBGR, image.cols(), image.rows(), 60);
} else {
throw new RuntimeException("Failed to load image!");
}
properties = new com.chameleonvision.vision.image.CaptureProperties(fakeVideoMode, FOV);
}
@Override
public Pair<Mat, Long> getFrame() {
return Pair.of(image, System.nanoTime());
}
@Override
public CaptureProperties getProperties() {
return properties;
}
@Override
public VideoMode getCurrentVideoMode() {
return fakeVideoMode;
}
@Override
public void setExposure(int exposure) {
// do nothing
}
@Override
public void setBrightness(int brightness) {
// do nothing
}
@Override
public void setVideoMode(VideoMode mode) {
// do nothing
}
@Override
public void setVideoMode(int index) {
// do nothing
}
@Override
public void setGain(int gain) {
// do nothing
}
}

View File

@@ -1,6 +1,7 @@
package com.chameleonvision.vision.pipeline;
import com.chameleonvision.Main;
import com.chameleonvision.util.MemoryManager;
import com.chameleonvision.vision.camera.CameraCapture;
import com.chameleonvision.vision.camera.CaptureStaticProperties;
import com.chameleonvision.vision.pipeline.pipes.*;
@@ -78,6 +79,8 @@ public class CVPipeline2d extends CVPipeline<CVPipeline2dResult, CVPipeline2dSet
outputMatPipe = new OutputMatPipe(settings.isBinary);
}
private final MemoryManager memManager = new MemoryManager(120);
@Override
public CVPipeline2dResult runPipeline(Mat inputMat) {
long totalPipelineTimeNanos = 0;
@@ -181,6 +184,8 @@ public class CVPipeline2d extends CVPipeline<CVPipeline2dResult, CVPipeline2dSet
System.out.printf("full pipeline run time was %.3fms (%.2fFPS)\n", truePipelineTimeMillis, truePipelineFPS);
}
memManager.run(Main.testMode);
return new CVPipeline2dResult(collect2dTargetsResult.getLeft(), draw2dContoursResult.getLeft(), totalPipelineTimeNanos);
}

View File

@@ -7,14 +7,16 @@ import java.util.List;
public abstract class CVPipelineResult<T> {
public final List<T> targets;
public final boolean hasTarget;
public final Mat outputMat = new Mat();
public final Mat outputMat;
public final long processTime;
public long imageTimestamp = 0;
public CVPipelineResult(List<T> targets, Mat outputMat, long processTime) {
this.targets = targets;
hasTarget = targets != null && !targets.isEmpty();
outputMat.copyTo(this.outputMat);
this.outputMat = outputMat;
// outputMat.copyTo(this.outputMat);
// outputMat.release();
this.processTime = processTime;
}

View File

@@ -1,7 +1,10 @@
package com.chameleonvision.vision.pipeline;
import com.chameleonvision.Main;
import com.chameleonvision.util.MemoryManager;
import com.chameleonvision.vision.camera.CameraCapture;
import com.chameleonvision.vision.pipeline.pipes.Draw2dContoursPipe;
import com.chameleonvision.vision.pipeline.pipes.RotateFlipPipe;
import org.apache.commons.lang3.tuple.Pair;
import org.opencv.core.Mat;
import org.opencv.core.RotatedRect;
@@ -12,10 +15,13 @@ import static com.chameleonvision.vision.pipeline.DriverVisionPipeline.DriverPip
public class DriverVisionPipeline extends CVPipeline<DriverPipelineResult, CVPipelineSettings> {
private RotateFlipPipe rotateFlipPipe;
private Draw2dContoursPipe draw2dContoursPipe;
private Draw2dContoursPipe.Draw2dContoursSettings draw2dContoursSettings = new Draw2dContoursPipe.Draw2dContoursSettings();
private final List<RotatedRect> blankList = List.of();
private final MemoryManager memoryManager = new MemoryManager(50);
public DriverVisionPipeline(CVPipelineSettings settings) {
super(settings);
settings.index = -1;
@@ -24,6 +30,7 @@ public class DriverVisionPipeline extends CVPipeline<DriverPipelineResult, CVPip
@Override
public void initPipeline(CameraCapture capture) {
super.initPipeline(capture);
rotateFlipPipe = new RotateFlipPipe(settings.rotationMode, settings.flipMode);
draw2dContoursSettings.showCrosshair = true;
draw2dContoursPipe = new Draw2dContoursPipe(draw2dContoursSettings, cameraCapture.getProperties().getStaticProperties());
}
@@ -31,12 +38,17 @@ public class DriverVisionPipeline extends CVPipeline<DriverPipelineResult, CVPip
@Override
public DriverPipelineResult runPipeline(Mat inputMat) {
inputMat.copyTo(outputMat);
// inputMat.copyTo(outputMat);
rotateFlipPipe.setConfig(settings.rotationMode, settings.flipMode);
draw2dContoursPipe.setConfig(false, cameraCapture.getProperties().getStaticProperties());
draw2dContoursPipe.run(Pair.of(outputMat, blankList)).getLeft().copyTo(outputMat);
return new DriverPipelineResult(null, outputMat, 0);
Pair<Mat, Long> rotateFlipResult = rotateFlipPipe.run(inputMat);
Pair<Mat, Long> draw2dContoursResult = draw2dContoursPipe.run(Pair.of(rotateFlipResult.getLeft(), blankList));
memoryManager.run(Main.testMode);
return new DriverPipelineResult(null, draw2dContoursResult.getLeft(), 0);
}
public static class DriverPipelineResult extends CVPipelineResult<Void> {

View File

@@ -40,7 +40,8 @@ public class Draw2dContoursPipe implements Pipe<Pair<Mat, List<RotatedRect>>, Ma
long processStartNanos = System.nanoTime();
if (settings.showCrosshair || settings.showCentroid || settings.showMaximumBox || settings.showRotatedBox) {
input.getLeft().copyTo(processBuffer);
// input.getLeft().copyTo(processBuffer);
processBuffer = input.getLeft();
if (input.getRight().size() > 0) {
for (int i = 0; i < input.getRight().size(); i++) {
@@ -81,14 +82,14 @@ public class Draw2dContoursPipe implements Pipe<Pair<Mat, List<RotatedRect>>, Ma
Imgproc.line(processBuffer, yMax, yMin, Helpers.colorToScalar(settings.crosshairColor), 2);
}
processBuffer.copyTo(outputMat);
processBuffer.release();
// processBuffer.copyTo(outputMat);
// processBuffer.release();
} else {
input.getLeft().copyTo(outputMat);
// input.getLeft().copyTo(outputMat);
}
long processTime = System.nanoTime() - processStartNanos;
return Pair.of(outputMat, processTime);
return Pair.of(processBuffer, processTime);
}
public static class Draw2dContoursSettings {

View File

@@ -32,23 +32,23 @@ public class RotateFlipPipe implements Pipe<Mat, Mat> {
boolean shouldRotate = !rotation.equals(ImageRotationMode.DEG_0);
if (shouldFlip || shouldRotate) {
input.copyTo(processBuffer);
// input.copyTo(processBuffer);
if (shouldFlip) {
Core.flip(processBuffer, processBuffer, flip.value);
Core.flip(input, input, flip.value);
}
if (shouldRotate) {
Core.rotate(processBuffer, processBuffer, rotation.value);
Core.rotate(input, input, rotation.value);
}
processBuffer.copyTo(outputMat);
processBuffer.release();
// processBuffer.copyTo(outputMat);
// processBuffer.release();
} else {
input.copyTo(outputMat);
// input.copyTo(outputMat);
}
long processTime = System.nanoTime() - processStartNanos;
return Pair.of(outputMat, processTime);
return Pair.of(input, processTime);
}
}

View File

@@ -5,6 +5,7 @@ import com.chameleonvision.network.NetworkIPMode;
import com.chameleonvision.vision.VisionManager;
import com.chameleonvision.vision.VisionProcess;
import com.chameleonvision.vision.camera.CameraCapture;
import com.chameleonvision.vision.camera.USBCameraCapture;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.javalin.http.Context;
@@ -40,7 +41,7 @@ public class RequestHandler {
Map camSettings = objectMapper.readValue(ctx.body(), Map.class);
VisionProcess currentVisionProcess = VisionManager.getCurrentUIVisionProcess();
CameraCapture currentCamera = currentVisionProcess.getCamera();
USBCameraCapture currentCamera = currentVisionProcess.getCamera();
double newFOV;
try {

View File

@@ -4,6 +4,7 @@ import com.chameleonvision.config.ConfigManager;
import com.chameleonvision.vision.VisionManager;
import com.chameleonvision.vision.VisionProcess;
import com.chameleonvision.vision.camera.CameraCapture;
import com.chameleonvision.vision.camera.USBCameraCapture;
import com.chameleonvision.vision.enums.StreamDivisor;
import com.chameleonvision.vision.pipeline.CVPipeline;
import com.chameleonvision.vision.pipeline.CVPipelineSettings;
@@ -234,7 +235,7 @@ public class SocketHandler {
private static HashMap<String, Object> getOrdinalCameraSettings() {
HashMap<String, Object> tmp = new HashMap<>();
VisionProcess currentVisionProcess = VisionManager.getCurrentUIVisionProcess();
CameraCapture currentCamera = VisionManager.getCurrentUIVisionProcess().getCamera();
USBCameraCapture currentCamera = VisionManager.getCurrentUIVisionProcess().getCamera();
tmp.put("fov", currentCamera.getProperties().getFOV());
tmp.put("streamDivisor", currentVisionProcess.cameraStreamer.getDivisor().ordinal());
tmp.put("resolution", currentVisionProcess.getCamera().getProperties().getCurrentVideoModeIndex());