diff --git a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/FrameProvider.java b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/FrameProvider.java index 37cd24078..1827df9f7 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/FrameProvider.java +++ b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/FrameProvider.java @@ -2,4 +2,6 @@ package com.chameleonvision.common.vision.frame; public interface FrameProvider { Frame getFrame(); + + FrameStaticProperties getFrameProperties(); } diff --git a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/FrameStaticProperties.java b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/FrameStaticProperties.java new file mode 100644 index 000000000..640acfbcb --- /dev/null +++ b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/FrameStaticProperties.java @@ -0,0 +1,61 @@ +package com.chameleonvision.common.vision.frame; + +import edu.wpi.cscore.VideoMode; +import org.apache.commons.math3.fraction.Fraction; +import org.apache.commons.math3.util.FastMath; + +/** Represents the properties of a frame. */ +public class FrameStaticProperties { + 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; + + /** + * Instantiates a new Frame static properties. + * + * @param mode The Video Mode of the camera. + * @param fov The fov of the image. + */ + public FrameStaticProperties(VideoMode mode, double fov) { + this(mode.width, mode.height, fov); + } + + /** + * Instantiates a new Frame static properties. + * + * @param imageWidth The width of the image. + * @param imageHeight The width of the image. + * @param fov The fov of the image. + */ + public FrameStaticProperties(int imageWidth, int imageHeight, double fov) { + 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(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 = this.imageWidth / (2 * FastMath.tan(horizontalView / 2)); + verticalFocalLength = this.imageHeight / (2 * FastMath.tan(verticalView / 2)); + } +} diff --git a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/FileFrameProvider.java b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/FileFrameProvider.java index 2209df245..4e39704e2 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/FileFrameProvider.java +++ b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/FileFrameProvider.java @@ -2,11 +2,91 @@ package com.chameleonvision.common.vision.frame.provider; import com.chameleonvision.common.vision.frame.Frame; import com.chameleonvision.common.vision.frame.FrameProvider; -import org.apache.commons.lang3.NotImplementedException; +import com.chameleonvision.common.vision.frame.FrameStaticProperties; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.opencv.core.Mat; +import org.opencv.imgcodecs.Imgcodecs; +/** +* A {@link FrameProvider} that will read and provide an image from a {@link java.nio.file.Path +* path}. +*/ public class FileFrameProvider implements FrameProvider { + private Frame m_frame; + private Path m_path; + + private double m_fov; + private FrameStaticProperties m_properties; + + private boolean m_reloadImage; + + /** + * Instantiates a new FileFrameProvider. + * + * @param path The path of the image to read from. + * @param fov The fov of the image. + */ + public FileFrameProvider(Path path, double fov) { + if (!Files.exists(path)) throw new RuntimeException("Invalid path for image!"); + m_path = path; + m_fov = fov; + + loadImage(); + } + + /** + * Instantiates a new File frame provider. + * + * @param pathAsString The path of the image to read from as a string. + * @param fov The fov of the image. + */ + public FileFrameProvider(String pathAsString, double fov) { + this(Paths.get(pathAsString), fov); + } + + private void loadImage() { + Mat image = Imgcodecs.imread(m_path.toString()); + + if (image.cols() > 0 && image.rows() > 0) { + m_properties = new FrameStaticProperties(image.width(), image.height(), m_fov); + m_frame = new Frame(image); + } else { + throw new RuntimeException("Image loading failed!"); + } + } + + /** + * Set image reloading. If true this will reload the image from the path set in the constructor + * every time {@link FileFrameProvider#getFrame()} is called. + * + * @param reloadImage True to enable image reloading. + */ + public void setImageReloading(boolean reloadImage) { + m_reloadImage = reloadImage; + } + + /** + * Returns if image reloading is enabled. + * + * @return True if image reloading is enabled. + */ + public boolean isImageReloading() { + return m_reloadImage; + } + + @Override + public FrameStaticProperties getFrameProperties() { + return m_properties; + } + @Override public Frame getFrame() { - throw new NotImplementedException(""); + if (m_reloadImage) { + loadImage(); + } + + return m_frame; } } diff --git a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/NetworkFrameProvider.java b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/NetworkFrameProvider.java index ad63a283c..b111bde37 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/NetworkFrameProvider.java +++ b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/NetworkFrameProvider.java @@ -2,6 +2,7 @@ package com.chameleonvision.common.vision.frame.provider; import com.chameleonvision.common.vision.frame.Frame; import com.chameleonvision.common.vision.frame.FrameProvider; +import com.chameleonvision.common.vision.frame.FrameStaticProperties; import org.apache.commons.lang3.NotImplementedException; public class NetworkFrameProvider implements FrameProvider { @@ -9,4 +10,9 @@ public class NetworkFrameProvider implements FrameProvider { public Frame getFrame() { throw new NotImplementedException(""); } + + @Override + public FrameStaticProperties getFrameProperties() { + throw new NotImplementedException(""); + } } diff --git a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/USBFrameProvider.java b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/USBFrameProvider.java index e942429d4..f5bdbed62 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/USBFrameProvider.java +++ b/chameleon-server/src/main/java/com/chameleonvision/common/vision/frame/provider/USBFrameProvider.java @@ -2,6 +2,7 @@ package com.chameleonvision.common.vision.frame.provider; import com.chameleonvision.common.vision.frame.Frame; import com.chameleonvision.common.vision.frame.FrameProvider; +import com.chameleonvision.common.vision.frame.FrameStaticProperties; import org.apache.commons.lang3.NotImplementedException; public class USBFrameProvider implements FrameProvider { @@ -9,4 +10,9 @@ public class USBFrameProvider implements FrameProvider { public Frame getFrame() { throw new NotImplementedException(""); } + + @Override + public FrameStaticProperties getFrameProperties() { + throw new NotImplementedException(""); + } }