mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Rename StreamDivisor enum and work on CameraStreamer
This commit is contained in:
@@ -6,8 +6,22 @@ import org.opencv.core.Mat;
|
||||
public interface CameraProcess {
|
||||
CameraProperties getProperties();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Set the exposure of the camera
|
||||
* @param exposure the new exposure to set the camera to
|
||||
*/
|
||||
void setExposure(int exposure);
|
||||
|
||||
/**
|
||||
* Set the exposure of the camera
|
||||
* @param brightness the new brightness to set the camera to
|
||||
*/
|
||||
void setBrightness(int brightness);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class CameraProperties {
|
||||
private static final List<VideoMode.PixelFormat> ALLOWED_PIXEL_FORMATS = Arrays.asList(VideoMode.PixelFormat.kYUYV, VideoMode.PixelFormat.kMJPEG);
|
||||
|
||||
private static final Predicate<VideoMode> kMinFPSPredicate = (videoMode -> videoMode.fps >= MINIMUM_FPS);
|
||||
private static final Predicate<VideoMode> kMinSizePredicate = (videoMode -> videoMode.width >= MINIMUM_FPS && videoMode.height >= MINIMUM_FPS);
|
||||
private static final Predicate<VideoMode> kMinSizePredicate = (videoMode -> videoMode.width >= MINIMUM_WIDTH && videoMode.height >= MINIMUM_HEIGHT);
|
||||
private static final Predicate<VideoMode> kPixelFormatPredicate = (videoMode -> ALLOWED_PIXEL_FORMATS.contains(videoMode.pixelFormat));
|
||||
|
||||
public CameraStaticProperties staticProperties;
|
||||
@@ -46,11 +46,11 @@ public class CameraProperties {
|
||||
}
|
||||
|
||||
public double CalculatePitch(double PixelY, double centerY) {
|
||||
double pitch = FastMath.toDegrees(FastMath.atan((PixelY - centerY) / staticProperties.VerticalFocalLength));
|
||||
double pitch = FastMath.toDegrees(FastMath.atan((PixelY - centerY) / staticProperties.verticalFocalLength));
|
||||
return (pitch * -1);
|
||||
}
|
||||
|
||||
public double CalculateYaw(double PixelX, double centerX) {
|
||||
return FastMath.toDegrees(FastMath.atan((PixelX - centerX) / staticProperties.HorizontalFocalLength));
|
||||
return FastMath.toDegrees(FastMath.atan((PixelX - centerX) / staticProperties.horizontalFocalLength));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,32 +5,32 @@ import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
public class CameraStaticProperties {
|
||||
|
||||
public final int ImageWidth;
|
||||
public final int ImageHeight;
|
||||
public final double FOV;
|
||||
public final double ImageArea;
|
||||
public final int imageWidth;
|
||||
public final int imageHeight;
|
||||
public final double fov;
|
||||
public final double imageArea;
|
||||
public final double centerX;
|
||||
public final double centerY;
|
||||
public final double HorizontalFocalLength;
|
||||
public final double VerticalFocalLength;
|
||||
public final double horizontalFocalLength;
|
||||
public final double verticalFocalLength;
|
||||
|
||||
public CameraStaticProperties(int imageWidth, int imageHeight, double fov) {
|
||||
ImageWidth = imageWidth;
|
||||
ImageHeight = imageHeight;
|
||||
FOV = fov;
|
||||
ImageArea = ImageWidth * ImageHeight;
|
||||
centerX = ((double) ImageWidth / 2) - 0.5;
|
||||
centerY = ((double) ImageHeight / 2) - 0.5;
|
||||
this.imageWidth = imageWidth;
|
||||
this.imageHeight = imageHeight;
|
||||
this.fov = fov;
|
||||
imageArea = this.imageWidth * this.imageHeight;
|
||||
centerX = ((double) this.imageWidth / 2) - 0.5;
|
||||
centerY = ((double) this.imageHeight / 2) - 0.5;
|
||||
|
||||
// pinhole model calculations
|
||||
double diagonalView = FastMath.toRadians(FOV);
|
||||
Fraction aspectFraction = new Fraction(ImageWidth, ImageHeight);
|
||||
double diagonalView = FastMath.toRadians(this.fov);
|
||||
Fraction aspectFraction = new Fraction(this.imageWidth, this.imageHeight);
|
||||
int horizontalRatio = aspectFraction.getNumerator();
|
||||
int verticalRatio = aspectFraction.getDenominator();
|
||||
double diagonalAspect = FastMath.hypot(horizontalRatio, verticalRatio);
|
||||
double horizontalView = FastMath.atan(FastMath.tan(diagonalView / 2) * (horizontalRatio / diagonalAspect)) * 2;
|
||||
double verticalView = FastMath.atan(FastMath.tan(diagonalView / 2) * (verticalRatio / diagonalAspect)) * 2;
|
||||
HorizontalFocalLength = ImageWidth / (2 * FastMath.tan(horizontalView /2));
|
||||
VerticalFocalLength = ImageHeight / (2 * FastMath.tan(verticalView /2));
|
||||
horizontalFocalLength = this.imageWidth / (2 * FastMath.tan(horizontalView /2));
|
||||
verticalFocalLength = this.imageHeight / (2 * FastMath.tan(verticalView /2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,58 @@
|
||||
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;
|
||||
import edu.wpi.first.cameraserver.CameraServer;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
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;
|
||||
private CvSource cvSource;
|
||||
private final Object streamBufferLock = new Object();
|
||||
private Mat streamBuffer = new Mat();
|
||||
|
||||
public CameraStreamer(CameraProcess cameraProcess, String name) {
|
||||
this.cameraProcess = cameraProcess;
|
||||
this.name = name;
|
||||
this.cvSource = CameraServer.getInstance().putVideo(name,
|
||||
cameraProcess.getProperties().staticProperties.imageWidth / divisor.value,
|
||||
cameraProcess.getProperties().staticProperties.imageHeight / divisor.value);
|
||||
}
|
||||
|
||||
|
||||
public void setDivisor(StreamDivisor newDivisor) {
|
||||
this.divisor = newDivisor;
|
||||
var camValues = cameraProcess.getProperties();
|
||||
var newWidth = camValues.staticProperties.imageWidth / newDivisor.value;
|
||||
var newHeight = camValues.staticProperties.imageHeight / newDivisor.value;
|
||||
synchronized (streamBufferLock) {
|
||||
this.streamBuffer = new Mat(newWidth, newHeight, CvType.CV_8UC3);
|
||||
this.cvSource = CameraServer.getInstance().putVideo(this.name,
|
||||
cameraProcess.getProperties().staticProperties.imageWidth / divisor.value,
|
||||
cameraProcess.getProperties().staticProperties.imageHeight / divisor.value);
|
||||
}
|
||||
ServerHandler.sendFullSettings();
|
||||
}
|
||||
|
||||
public void runStream() {
|
||||
var newFrame = cameraProcess.getFrame(streamBuffer);
|
||||
var image = newFrame.getLeft();
|
||||
if (divisor.value != 1) {
|
||||
var camVal = cameraProcess.getProperties().staticProperties;
|
||||
var newWidth = camVal.imageWidth / divisor.value;
|
||||
var newHeight = camVal.imageHeight / divisor.value;
|
||||
Size newSize = new Size(newWidth, newHeight);
|
||||
Imgproc.resize(image, image, newSize);
|
||||
}
|
||||
cvSource.putFrame(image);
|
||||
}
|
||||
|
||||
public interface CameraStreamer {
|
||||
void streamFrame(Mat frame);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,12 @@ public class USBCameraProcess implements CameraProcess {
|
||||
|
||||
@Override
|
||||
public Pair<Mat, Long> getFrame(Mat frame) {
|
||||
var timestamp = System.nanoTime();
|
||||
cvSink.grabFrame(imageBuffer);
|
||||
imageBuffer.copyTo(frame);
|
||||
return Pair.of(frame, timestamp - System.nanoTime());
|
||||
Long deltaTime;
|
||||
synchronized (cvSink) {
|
||||
deltaTime = cvSink.grabFrame(imageBuffer) * 1000L;
|
||||
imageBuffer.copyTo(frame);
|
||||
}
|
||||
return Pair.of(frame, deltaTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -61,11 +61,11 @@ public class Collect2dTargetsPipe implements Pipe<List<RotatedRect>, List<CVPipe
|
||||
}
|
||||
|
||||
private double calculatePitch(double pixelY, double centerY) {
|
||||
double pitch = FastMath.toDegrees(FastMath.atan((pixelY - centerY) / camProps.VerticalFocalLength));
|
||||
double pitch = FastMath.toDegrees(FastMath.atan((pixelY - centerY) / camProps.verticalFocalLength));
|
||||
return (pitch * -1);
|
||||
}
|
||||
|
||||
private double calculateYaw(double pixelX, double centerX) {
|
||||
return FastMath.toDegrees(FastMath.atan((pixelX - centerX) / camProps.HorizontalFocalLength));
|
||||
return FastMath.toDegrees(FastMath.atan((pixelX - centerX) / camProps.horizontalFocalLength));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class FilterContoursPipe implements Pipe<List<MatOfPoint>, List<MatOfPoin
|
||||
for (MatOfPoint Contour : input) {
|
||||
try {
|
||||
double contourArea = Imgproc.contourArea(Contour);
|
||||
double AreaRatio = (contourArea / camProps.ImageArea) * 100;
|
||||
double AreaRatio = (contourArea / camProps.imageArea) * 100;
|
||||
double minArea = (MathHandler.sigmoid(area.get(0)));
|
||||
double maxArea = (MathHandler.sigmoid(area.get(1)));
|
||||
if (AreaRatio < minArea || AreaRatio > maxArea) {
|
||||
|
||||
@@ -31,7 +31,7 @@ public class CameraDeserializer implements JsonDeserializer<USBCamera> {
|
||||
boolean isDriver = isDriverObj != null && isDriverObj.getAsBoolean();
|
||||
int driverExposure = driverExposureObj == null ? USBCamera.DEFAULT_EXPOSURE : driverExposureObj.getAsInt();
|
||||
int driverBrightness = driverBrightnessObj == null ? USBCamera.DEFAULT_BRIGHTNESS : driverBrightnessObj.getAsInt();
|
||||
StreamDivisor divisor = divisorObj == null ? StreamDivisor.none : StreamDivisor.values()[divisorObj.getAsInt()];
|
||||
StreamDivisor divisor = divisorObj == null ? StreamDivisor.NONE : StreamDivisor.values()[divisorObj.getAsInt()];
|
||||
|
||||
var pipelines = jsonObj.get("pipelines");
|
||||
List<Pipeline> actualPipelines = new ArrayList<>();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.chameleonvision.vision.camera;
|
||||
|
||||
public enum StreamDivisor {
|
||||
none(1),
|
||||
half(2),
|
||||
quarter(4),
|
||||
sixth(6);
|
||||
NONE(1),
|
||||
HALF(2),
|
||||
QUARTER(4),
|
||||
SIXTH(6);
|
||||
|
||||
public final Integer value;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.stream.IntStream;
|
||||
public class USBCamera {
|
||||
|
||||
private static final double DEFAULT_FOV = 60.8;
|
||||
private static final StreamDivisor DEFAULT_STREAMDIVISOR = StreamDivisor.none;
|
||||
private static final StreamDivisor DEFAULT_STREAMDIVISOR = StreamDivisor.NONE;
|
||||
public static final int DEFAULT_EXPOSURE = 50;
|
||||
public static final int DEFAULT_BRIGHTNESS = 50;
|
||||
private static final int MINIMUM_FPS = 30;
|
||||
|
||||
Reference in New Issue
Block a user