Begin further work on abstraction layout in separate package

This commit is contained in:
Banks Troutman
2019-11-04 02:23:13 -05:00
parent 42b76dfbf9
commit 1bca800f4f
13 changed files with 232 additions and 26 deletions

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -0,0 +1,7 @@
package com.chameleonvision.classabstraction.camera;
import org.opencv.core.Mat;
public interface CameraStreamer {
void streamFrame(Mat frame);
}

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -0,0 +1,4 @@
package com.chameleonvision.classabstraction.pipeline;
public class CVPipeline2dSettings extends CVPipelineSettings {
}

View File

@@ -0,0 +1,4 @@
package com.chameleonvision.classabstraction.pipeline;
public abstract class CVPipeline3dSettings extends CVPipelineSettings {
}

View File

@@ -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 = "";
}

View File

@@ -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;
}
}

View File

@@ -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));

View File

@@ -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));
}
}