mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Begin further work on abstraction layout in separate package
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
public interface CameraProcess {
|
||||
Pair<Mat, Long> getFrame();
|
||||
|
||||
void setExposure(int exposure);
|
||||
void setBrightness(int brightness);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class CameraProperties {
|
||||
private static final double DEFAULT_FOV = 70;
|
||||
private static final int DEFAULT_EXPOSURE = 50;
|
||||
private static final int DEFAULT_BRIGHTNESS = 50;
|
||||
private static final int MINIMUM_FPS = 30;
|
||||
private static final int MINIMUM_WIDTH = 320;
|
||||
private static final int MINIMUM_HEIGHT = 200;
|
||||
private static final int MAX_INIT_MS = 1500;
|
||||
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> kPixelFormatPredicate = (videoMode -> ALLOWED_PIXEL_FORMATS.contains(videoMode.pixelFormat));
|
||||
|
||||
public CameraStaticProperties staticProperties;
|
||||
public final double FOV;
|
||||
public final List<VideoMode> videoModes;
|
||||
|
||||
public CameraProperties(UsbCamera baseCamera, double fov) {
|
||||
FOV = fov;
|
||||
|
||||
videoModes = filterVideoModes(baseCamera.enumerateVideoModes());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private List<VideoMode> filterVideoModes(VideoMode[] videoModes) {
|
||||
Predicate<VideoMode> fullPredicate = kMinFPSPredicate.and(kMinSizePredicate).and(kPixelFormatPredicate);
|
||||
Stream<VideoMode> validModes = Arrays.stream(videoModes).filter(fullPredicate);
|
||||
return validModes.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void updateVideoMode(VideoMode videoMode) {
|
||||
staticProperties = new CameraStaticProperties(videoMode.width, videoMode.height, FOV);
|
||||
}
|
||||
|
||||
public double CalculatePitch(double PixelY, double centerY) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import org.apache.commons.math3.fraction.Fraction;
|
||||
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 double CenterX;
|
||||
public final double CenterY;
|
||||
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;
|
||||
|
||||
// pinhole model calculations
|
||||
double diagonalView = FastMath.toRadians(FOV);
|
||||
Fraction aspectFraction = new Fraction(ImageWidth, 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));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
public interface CameraStreamer {
|
||||
void streamFrame(Mat frame);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
|
||||
public class USBCamera {
|
||||
private final UsbCamera baseCamera;
|
||||
private final CameraProperties properties;
|
||||
|
||||
public USBCamera(UsbCamera camera) {
|
||||
baseCamera = camera;
|
||||
VideoMode vidMode = new VideoMode(VideoMode.PixelFormat.kYUYV, 640, 480, 60);
|
||||
properties = new CameraProperties(baseCamera, 75);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param <R> Pipeline result type
|
||||
*/
|
||||
public abstract class CVPipeline<R> {
|
||||
private CVPipelineSettings settings;
|
||||
private Mat inputMat;
|
||||
protected Mat outputMat;
|
||||
|
||||
public CVPipeline(CVPipelineSettings settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
abstract void initPipeline();
|
||||
abstract R runPipeline(Mat inputMat);
|
||||
abstract Mat getOutputMat();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
public class CVPipeline2dSettings extends CVPipelineSettings {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
public abstract class CVPipeline3dSettings extends CVPipelineSettings {
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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 abstract class CVPipelineSettings {
|
||||
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;
|
||||
double m = 1;
|
||||
double b = 0;
|
||||
List<Number> point = Arrays.asList(0,0);
|
||||
CalibrationMode calibrationMode = CalibrationMode.None;
|
||||
String nickname = "";
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
public class DriverVisionPipeline extends CVPipeline<Void> {
|
||||
public DriverVisionPipeline(CVPipelineSettings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
void initPipeline() {
|
||||
// set exposure/brightness of camera?
|
||||
}
|
||||
|
||||
@Override
|
||||
Void runPipeline(Mat inputMat) {
|
||||
this.outputMat = inputMat;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
Mat getOutputMat() {
|
||||
return this.outputMat;
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class CameraManager {
|
||||
public static HashMap<String, USBCamera> getAllCamerasByName() {
|
||||
return allCamerasByName;
|
||||
}
|
||||
public static List<String> getAllCameraByNickname(){
|
||||
public static List<String> getAllCameraByNickname() {
|
||||
var cameras = getAllCamerasByName();
|
||||
return cameras.values().stream().map(USBCamera::getNickname).collect(Collectors.toList());
|
||||
}
|
||||
@@ -101,6 +101,7 @@ public class CameraManager {
|
||||
if (curCam == null) throw new CameraException(CameraException.CameraExceptionType.BAD_CAMERA);
|
||||
return curCam;
|
||||
}
|
||||
|
||||
public static Integer getCurrentCameraIndex() throws CameraException {
|
||||
if (allCamerasByName.size() == 0) throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA);
|
||||
List<String> arr = new ArrayList<>(allCamerasByName.keySet());
|
||||
@@ -118,6 +119,7 @@ public class CameraManager {
|
||||
SettingsManager.generalSettings.currentCamera = cameraName;
|
||||
SettingsManager.updateCameraSetting(cameraName, getCurrentCamera().getCurrentPipelineIndex());
|
||||
}
|
||||
|
||||
public static void setCurrentCamera(int cameraIndex) throws CameraException {
|
||||
List<String> s = new ArrayList<String>(allCamerasByName.keySet());
|
||||
setCurrentCamera(s.get(cameraIndex));
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.chameleonvision.vision.camera;
|
||||
import org.apache.commons.math3.fraction.Fraction;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class CameraValues {
|
||||
public final int ImageWidth;
|
||||
public final int ImageHeight;
|
||||
@@ -11,20 +10,14 @@ public class CameraValues {
|
||||
public final double ImageArea;
|
||||
public final double CenterX;
|
||||
public final double CenterY;
|
||||
public final double DiagonalView;
|
||||
public final double DiagonalAspect;
|
||||
public final Fraction AspectFraction;
|
||||
public final int HorizontalRatio;
|
||||
public final int VerticalRatio;
|
||||
public final double HorizontalView;
|
||||
public final double VerticalView;
|
||||
public final double HorizontalFocalLength;
|
||||
public final double VerticalFocalLength;
|
||||
private final double HorizontalFocalLength;
|
||||
private final double VerticalFocalLength;
|
||||
|
||||
public CameraValues(USBCamera USBCamera) {
|
||||
this(USBCamera.getVideoMode().width, USBCamera.getVideoMode().height, USBCamera.getFOV());
|
||||
}
|
||||
|
||||
|
||||
public CameraValues(int imageWidth, int imageHeight, double fov) {
|
||||
ImageWidth = imageWidth;
|
||||
ImageHeight = imageHeight;
|
||||
@@ -32,21 +25,25 @@ public class CameraValues {
|
||||
ImageArea = ImageWidth * ImageHeight;
|
||||
CenterX = ((double) ImageWidth / 2) - 0.5;
|
||||
CenterY = ((double) ImageHeight / 2) - 0.5;
|
||||
DiagonalView = FastMath.toRadians(FOV);
|
||||
AspectFraction = new Fraction(ImageWidth, ImageHeight);
|
||||
HorizontalRatio = AspectFraction.getNumerator();
|
||||
VerticalRatio = AspectFraction.getDenominator();
|
||||
DiagonalAspect = FastMath.hypot(HorizontalRatio, VerticalRatio);
|
||||
HorizontalView = FastMath.atan(FastMath.tan(DiagonalView / 2) * (HorizontalRatio / DiagonalAspect)) * 2;
|
||||
VerticalView = FastMath.atan(FastMath.tan(DiagonalView / 2) * (VerticalRatio / DiagonalAspect)) * 2;
|
||||
HorizontalFocalLength = ImageWidth / (2 * FastMath.tan(HorizontalView /2));
|
||||
VerticalFocalLength = ImageHeight / (2 * FastMath.tan(VerticalView /2));
|
||||
|
||||
// pinhole model calculations
|
||||
double diagonalView = FastMath.toRadians(FOV);
|
||||
Fraction aspectFraction = new Fraction(ImageWidth, 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));
|
||||
}
|
||||
public double CalculatePitch(double PixelY, double centerY){
|
||||
double pitch = FastMath.toDegrees(FastMath.atan((PixelY - centerY) / VerticalFocalLength));
|
||||
|
||||
public double CalculatePitch(double PixelY, double centerY) {
|
||||
double pitch = FastMath.toDegrees(FastMath.atan((PixelY - centerY) / VerticalFocalLength));
|
||||
return (pitch * -1);
|
||||
}
|
||||
public double CalculateYaw(double PixelX, double centerX){
|
||||
|
||||
public double CalculateYaw(double PixelX, double centerX) {
|
||||
return FastMath.toDegrees(FastMath.atan((PixelX - centerX) / HorizontalFocalLength));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user