mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-29 02:21:41 +00:00
Moved CvSink/CvSource to Camera class
This commit is contained in:
@@ -1,13 +1,9 @@
|
||||
package com.chameleonvision;
|
||||
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.camera.Camera;
|
||||
import com.chameleonvision.vision.camera.CameraManager;
|
||||
import com.chameleonvision.vision.process.CameraProcess;
|
||||
import com.chameleonvision.web.Server;
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
package com.chameleonvision.settings;
|
||||
|
||||
import com.chameleonvision.FileHelper;
|
||||
import com.chameleonvision.CameraException;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
|
||||
import com.chameleonvision.vision.camera.Camera;
|
||||
import com.chameleonvision.vision.GeneralSettings;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.vision.camera.CameraManager;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import edu.wpi.cscore.*;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class SettingsManager {
|
||||
private static SettingsManager instance;
|
||||
@@ -25,10 +19,11 @@ public class SettingsManager {
|
||||
private SettingsManager() {
|
||||
InitiateGeneralSettings();
|
||||
|
||||
if (!Cameras.containsKey(GeneralSettings.curr_camera) && Cameras.size() > 0) {
|
||||
String camName = Cameras.keySet().stream().findFirst().get();
|
||||
GeneralSettings.curr_camera = camName;
|
||||
GeneralSettings.curr_pipeline = CameraManager.getCamera(camName).getCurrentPipelineIndex();
|
||||
var allCameras = CameraManager.getAllCamerasByName();
|
||||
if (!allCameras.containsKey(GeneralSettings.curr_camera) && allCameras.size() > 0) {
|
||||
var cam = allCameras.entrySet().stream().findFirst().get().getValue();
|
||||
GeneralSettings.curr_camera = cam.name;
|
||||
GeneralSettings.curr_pipeline = cam.getCurrentPipelineIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,10 +38,7 @@ public class SettingsManager {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static HashMap<String, Camera> Cameras = new HashMap<>();
|
||||
public static HashMap<String, UsbCamera> UsbCameras = new HashMap<>();
|
||||
public static com.chameleonvision.vision.GeneralSettings GeneralSettings;
|
||||
public static HashMap<String, String> CamerasCurrentPipeline = new HashMap<>();
|
||||
// public static HashMap<String, String> CameraPorts = new HashMap<>();//TODO Implement ports
|
||||
public static final Path SettingsPath = Paths.get(System.getProperty("user.dir"), "Settings");
|
||||
|
||||
@@ -60,20 +52,7 @@ public class SettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Access Methods
|
||||
public List<String> GetResolutionList() throws CameraException {
|
||||
if (!GeneralSettings.curr_camera.equals("")) {
|
||||
List<String> list = new ArrayList<>();
|
||||
var cam = CameraManager.getCamera(GeneralSettings.curr_camera).UsbCam;
|
||||
for (var res : cam.enumerateVideoModes()) {
|
||||
list.add(String.format("%s X %s at %s fps", res.width, res.height, res.fps));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA);
|
||||
}
|
||||
|
||||
public void updateCameraSetting(String cameraName, int pipelineNumber) {
|
||||
GeneralSettings.curr_camera = cameraName;
|
||||
GeneralSettings.curr_pipeline = pipelineNumber;
|
||||
@@ -83,31 +62,17 @@ public class SettingsManager {
|
||||
GeneralSettings.curr_pipeline = pipelineNumber;
|
||||
}
|
||||
|
||||
|
||||
//Savers
|
||||
public void SaveSettings() {
|
||||
CameraManager.saveCameras();
|
||||
SaveGeneralSettings();
|
||||
}
|
||||
|
||||
private void SaveCameras() {
|
||||
for (Map.Entry<String, Camera> entry : Cameras.entrySet()) {
|
||||
try {
|
||||
Gson gson = new Gson();
|
||||
FileWriter writer = new FileWriter(Paths.get(CameraManager.CamConfigPath.toString(), String.format("%s.json", entry.getKey())).toString());
|
||||
gson.toJson(entry.getValue(), writer);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveGeneralSettings() {
|
||||
try {
|
||||
FileWriter writer = new FileWriter(Paths.get(SettingsPath.toString(), "Settings.json").toString());
|
||||
new Gson().toJson(GeneralSettings, writer);
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
FileWriter writer = new FileWriter(Paths.get(SettingsPath.toString(), "settings.json").toString());
|
||||
gson.toJson(GeneralSettings, writer);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -1,132 +1,148 @@
|
||||
package com.chameleonvision.vision.camera;
|
||||
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
import edu.wpi.cscore.UsbCameraInfo;
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
import edu.wpi.cscore.*;
|
||||
import edu.wpi.first.cameraserver.CameraServer;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Camera {
|
||||
|
||||
private static double defaultFOV = 60.8;
|
||||
private static double defaultFOV = 60.8;
|
||||
|
||||
public final String name;
|
||||
public final String path;
|
||||
public final String name;
|
||||
public final String path;
|
||||
|
||||
public final UsbCamera UsbCam;
|
||||
private final UsbCameraInfo UsbCamInfo;
|
||||
private final VideoMode[] availableVideoModes;
|
||||
public final UsbCamera UsbCam;
|
||||
private final UsbCameraInfo UsbCamInfo;
|
||||
private final VideoMode[] availableVideoModes;
|
||||
private final CvSink cvSink;
|
||||
private final CvSource cvSource;
|
||||
|
||||
private double FOV;
|
||||
private double FOV;
|
||||
|
||||
private CameraValues camVals;
|
||||
private CamVideoMode camVideoMode;
|
||||
private CameraValues camVals;
|
||||
private CamVideoMode camVideoMode;
|
||||
|
||||
private int currentPipelineIndex;
|
||||
private HashMap<Integer, Pipeline> pipelines = new HashMap<>();
|
||||
private int currentPipelineIndex;
|
||||
private HashMap<Integer, Pipeline> pipelines = new HashMap<>();
|
||||
|
||||
public Camera(String cameraName) {
|
||||
this(cameraName, defaultFOV);
|
||||
public Camera(String cameraName) {
|
||||
this(cameraName, defaultFOV);
|
||||
}
|
||||
|
||||
public Camera(UsbCameraInfo usbCamInfo) {
|
||||
this(usbCamInfo, defaultFOV);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, double fov) {
|
||||
this(CameraManager.AllUsbCameraInfosByName.get(cameraName), fov);
|
||||
}
|
||||
|
||||
public Camera(UsbCameraInfo usbCamInfo, double fov) {
|
||||
UsbCamInfo = usbCamInfo;
|
||||
FOV = fov;
|
||||
name = usbCamInfo.name;
|
||||
path = usbCamInfo.path;
|
||||
|
||||
UsbCam = new UsbCamera(name, path);
|
||||
|
||||
// set up video mode
|
||||
availableVideoModes = UsbCam.enumerateVideoModes();
|
||||
setCamVideoMode(new CamVideoMode(availableVideoModes[0]));
|
||||
|
||||
CameraServer cs = CameraServer.getInstance();
|
||||
cvSink = cs.getVideo(UsbCam);
|
||||
cvSource = cs.putVideo(name, camVals.ImageWidth, camVals.ImageHeight);
|
||||
}
|
||||
|
||||
public void setCamVideoMode(int videoMode) {
|
||||
setCamVideoMode(UsbCam.enumerateVideoModes()[videoMode]);
|
||||
}
|
||||
|
||||
private void setCamVideoMode(VideoMode videoMode) {
|
||||
setCamVideoMode(new CamVideoMode(videoMode));
|
||||
}
|
||||
|
||||
private void setCamVideoMode(CamVideoMode camVideoMode) {
|
||||
this.camVideoMode = camVideoMode;
|
||||
UsbCam.setPixelFormat(camVideoMode.getActualPixelFormat());
|
||||
UsbCam.setFPS(camVideoMode.fps);
|
||||
UsbCam.setResolution(camVideoMode.width, camVideoMode.height);
|
||||
camVals = new CameraValues(this);
|
||||
// TODO: Automatically restart CameraProcess when resolution changes (not FPS)
|
||||
}
|
||||
|
||||
public void addPipeline() {
|
||||
addPipeline(pipelines.size());
|
||||
}
|
||||
|
||||
private void addPipeline(int pipelineNumber) {
|
||||
if (pipelines.containsKey(pipelineNumber)) return;
|
||||
pipelines.put(pipelineNumber, new Pipeline());
|
||||
}
|
||||
|
||||
public Pipeline getCurrentPipeline() {
|
||||
return pipelines.get(currentPipelineIndex);
|
||||
}
|
||||
|
||||
public int getCurrentPipelineIndex() {
|
||||
return currentPipelineIndex;
|
||||
}
|
||||
|
||||
public void setCurrentPipelineIndex(int pipelineNumber) {
|
||||
if (pipelineNumber - 1 > pipelines.size()) return;
|
||||
currentPipelineIndex = pipelineNumber;
|
||||
}
|
||||
public HashMap<Integer, Pipeline> getPipelines() {
|
||||
return pipelines;
|
||||
}
|
||||
|
||||
public CamVideoMode getVideoMode() {
|
||||
return camVideoMode;
|
||||
}
|
||||
|
||||
public int getVideoModeIndex() {
|
||||
return IntStream.range(0, availableVideoModes.length)
|
||||
.filter(i -> camVideoMode.isEqualToVideoMode(availableVideoModes[i]))
|
||||
.findFirst()
|
||||
.orElse(-1);
|
||||
}
|
||||
|
||||
public double getFOV() {
|
||||
return FOV;
|
||||
}
|
||||
|
||||
public void setFOV(double fov) {
|
||||
FOV = fov;
|
||||
camVals = new CameraValues(this);
|
||||
}
|
||||
|
||||
public int getBrightness() {
|
||||
return getCurrentPipeline().brightness;
|
||||
}
|
||||
|
||||
public void setBrightness(int brightness) {
|
||||
getCurrentPipeline().brightness = brightness;
|
||||
UsbCam.setBrightness(brightness);
|
||||
}
|
||||
|
||||
public void setExposure(int exposure) {
|
||||
getCurrentPipeline().exposure = exposure;
|
||||
UsbCam.setExposureManual(exposure);
|
||||
}
|
||||
|
||||
public long grabFrame(Mat image) {
|
||||
return cvSink.grabFrame(image);
|
||||
}
|
||||
|
||||
public Camera(UsbCameraInfo usbCamInfo) {
|
||||
this(usbCamInfo, defaultFOV);
|
||||
public long grabFrame(Mat image, double timeout) {
|
||||
return cvSink.grabFrame(image, timeout);
|
||||
}
|
||||
|
||||
public Camera(String cameraName, double fov) {
|
||||
this(CameraManager.AllUsbCameraInfosByName.get(cameraName), fov);
|
||||
public void putFrame(Mat image) {
|
||||
cvSource.putFrame(image);
|
||||
}
|
||||
|
||||
public Camera(UsbCameraInfo usbCamInfo, double fov) {
|
||||
UsbCamInfo = usbCamInfo;
|
||||
FOV = fov;
|
||||
name = usbCamInfo.name;
|
||||
path = usbCamInfo.path;
|
||||
|
||||
UsbCam = new UsbCamera(name, path);
|
||||
|
||||
// set up video mode
|
||||
availableVideoModes = UsbCam.enumerateVideoModes();
|
||||
setCamVideoMode(new CamVideoMode(availableVideoModes[0]));
|
||||
}
|
||||
|
||||
public void setCamVideoMode(int videoMode) {
|
||||
setCamVideoMode(UsbCam.enumerateVideoModes()[videoMode]);
|
||||
}
|
||||
|
||||
private void setCamVideoMode(VideoMode videoMode) {
|
||||
setCamVideoMode(new CamVideoMode(videoMode));
|
||||
}
|
||||
|
||||
private void setCamVideoMode(CamVideoMode camVideoMode) {
|
||||
this.camVideoMode = camVideoMode;
|
||||
UsbCam.setPixelFormat(camVideoMode.getActualPixelFormat());
|
||||
UsbCam.setFPS(camVideoMode.fps);
|
||||
UsbCam.setResolution(camVideoMode.width, camVideoMode.height);
|
||||
camVals = new CameraValues(this);
|
||||
// TODO: Automatically restart CameraProcess when resolution changes (not FPS)
|
||||
}
|
||||
|
||||
public void addPipeline() {
|
||||
addPipeline(pipelines.size());
|
||||
}
|
||||
|
||||
private void addPipeline(int pipelineNumber) {
|
||||
if (pipelines.containsKey(pipelineNumber)) return;
|
||||
pipelines.put(pipelineNumber, new Pipeline());
|
||||
}
|
||||
|
||||
public void setCurrentPipelineIndex(int pipelineNumber) {
|
||||
if (pipelineNumber - 1 > pipelines.size()) return;
|
||||
currentPipelineIndex = pipelineNumber;
|
||||
}
|
||||
|
||||
public Pipeline getCurrentPipeline() {
|
||||
return pipelines.get(currentPipelineIndex);
|
||||
}
|
||||
|
||||
public int getCurrentPipelineIndex() {
|
||||
return currentPipelineIndex;
|
||||
}
|
||||
|
||||
public HashMap<Integer, Pipeline> getPipelines() {
|
||||
return pipelines;
|
||||
}
|
||||
|
||||
public CamVideoMode getVideoMode() {
|
||||
return camVideoMode;
|
||||
}
|
||||
|
||||
public int getVideoModeIndex() {
|
||||
return IntStream.range(0, availableVideoModes.length)
|
||||
.filter(i -> camVideoMode.isEqualToVideoMode(availableVideoModes[i]))
|
||||
.findFirst()
|
||||
.orElse(-1);
|
||||
}
|
||||
|
||||
public void setFOV(double fov) {
|
||||
FOV = fov;
|
||||
camVals = new CameraValues(this);
|
||||
}
|
||||
|
||||
public double getFOV() {
|
||||
return FOV;
|
||||
}
|
||||
|
||||
public void setBrightness(int brightness) {
|
||||
getCurrentPipeline().brightness = brightness;
|
||||
UsbCam.setBrightness(brightness);
|
||||
}
|
||||
|
||||
public int getBrightness() {
|
||||
return getCurrentPipeline().brightness;
|
||||
}
|
||||
|
||||
public void setExposure(int exposure) {
|
||||
getCurrentPipeline().exposure = exposure;
|
||||
UsbCam.setExposureManual(exposure);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,20 +23,23 @@ import java.util.List;
|
||||
|
||||
public class CameraManager {
|
||||
|
||||
public static final Path CamConfigPath = Paths.get(SettingsManager.SettingsPath.toString(), "Cams");
|
||||
private static final Path CamConfigPath = Paths.get(SettingsManager.SettingsPath.toString(), "Cams");
|
||||
|
||||
// TODO: Fix suffix for camera
|
||||
// TODO: throw a camera Exeption if no camera is connected
|
||||
// TODO: throw a camera Exception if no camera is connected
|
||||
static HashMap<String, UsbCameraInfo> AllUsbCameraInfosByName = new HashMap<>() {{
|
||||
var suffix = 0;
|
||||
for (var info : UsbCamera.enumerateUsbCameras()) {
|
||||
var cap = new VideoCapture(info.name);
|
||||
if (cap.isOpened()) {
|
||||
cap.release();
|
||||
var name = String.format("%s(%s)", info.name, suffix);
|
||||
put(name, info);
|
||||
}
|
||||
var name = info.name;
|
||||
while (this.containsKey(name)) {
|
||||
suffix++;
|
||||
}
|
||||
name = String.format("%s(%s)", info.name, suffix);
|
||||
}
|
||||
put(name, info);
|
||||
}
|
||||
}};
|
||||
|
||||
@@ -78,7 +81,7 @@ public class CameraManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Camera getCamera(String cameraName) {
|
||||
private static Camera getCamera(String cameraName) {
|
||||
return AllCamerasByName.get(cameraName);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package com.chameleonvision.vision.process;
|
||||
|
||||
import com.chameleonvision.CameraException;
|
||||
import com.chameleonvision.MemoryManager;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.camera.Camera;
|
||||
import com.chameleonvision.vision.camera.CameraManager;
|
||||
import com.chameleonvision.vision.camera.CameraValues;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.vision.camera.Camera;
|
||||
import com.chameleonvision.vision.camera.CameraValues;
|
||||
import com.chameleonvision.web.Server;
|
||||
import edu.wpi.cscore.CvSink;
|
||||
import edu.wpi.cscore.CvSource;
|
||||
import edu.wpi.first.networktables.*;
|
||||
import edu.wpi.first.cameraserver.CameraServer;
|
||||
import edu.wpi.first.networktables.*;
|
||||
import org.opencv.core.*;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
@@ -40,10 +38,6 @@ public class CameraProcess implements Runnable {
|
||||
private VisionProcess visionProcess;
|
||||
private CameraValues camVals;
|
||||
|
||||
// cscore
|
||||
private CvSink cvSink;
|
||||
private CvSource cvPublish;
|
||||
|
||||
// pipeline process items
|
||||
private List<MatOfPoint> FoundContours = new ArrayList<>();
|
||||
private List<MatOfPoint> FilteredContours = new ArrayList<>();
|
||||
@@ -103,11 +97,6 @@ public class CameraProcess implements Runnable {
|
||||
// camera settings
|
||||
camVals = new CameraValues(camera);
|
||||
visionProcess = new VisionProcess(camVals);
|
||||
|
||||
// cscore setup
|
||||
CameraServer cs = CameraServer.getInstance();
|
||||
cvSink = cs.getVideo(camera.UsbCam);
|
||||
cvPublish = cs.putVideo(cameraName, camVals.ImageWidth, camVals.ImageHeight);
|
||||
}
|
||||
|
||||
private void drawContour(Mat inputMat, RotatedRect contourRect) {
|
||||
@@ -192,7 +181,7 @@ public class CameraProcess implements Runnable {
|
||||
currentPipeline = camera.getCurrentPipeline();
|
||||
// start fps counter right before grabbing input frame
|
||||
startTime = System.nanoTime();
|
||||
TimeStamp = cvSink.grabFrame(cameraInputMat);
|
||||
TimeStamp = camera.grabFrame(cameraInputMat);
|
||||
if (cameraInputMat.cols() == 0 && cameraInputMat.rows() == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -210,10 +199,10 @@ public class CameraProcess implements Runnable {
|
||||
point.put("yaw", pipelineResult.Yaw);
|
||||
point.put("fps", fps);
|
||||
WebSend.put("point", point);
|
||||
WebSend.put("raw_point",center);
|
||||
WebSend.put("raw_point", center);
|
||||
Server.broadcastMessage(WebSend);
|
||||
}
|
||||
cvPublish.putFrame(streamOutputMat);
|
||||
camera.putFrame(streamOutputMat);
|
||||
// calculate FPS after publishing output frame
|
||||
processTimeMs = (System.nanoTime() - startTime) * 1e-6;
|
||||
fps = 1000 / processTimeMs;
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.png><title>Chameleon Vision</title><link href=/css/app.8be123c7.css rel=preload as=style><link href=/js/app.fd9292a1.js rel=preload as=script><link href=/js/chunk-vendors.a3ecb371.js rel=preload as=script><link href=/css/app.8be123c7.css rel=stylesheet></head><body><noscript><strong>We're sorry but Chameleon Vision doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.a3ecb371.js></script><script src=/js/app.fd9292a1.js></script></body></html>
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/favicon.png><title>Chameleon Vision</title><link href=/css/app.ac4ea4d9.css rel=preload as=style><link href=/js/app.38c2f8d8.js rel=preload as=script><link href=/js/chunk-vendors.60cc7e7e.js rel=preload as=script><link href=/css/app.ac4ea4d9.css rel=stylesheet></head><body><noscript><strong>We're sorry but Chameleon Vision doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.60cc7e7e.js></script><script src=/js/app.38c2f8d8.js></script></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user