mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-20 00:51:41 +00:00
Too many changes to list
running in to bug in CameraStreamer with native exceptions
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package com.chameleonvision;
|
||||
|
||||
import com.chameleonvision.classabstraction.VisionManager;
|
||||
import com.chameleonvision.classabstraction.config.ConfigManager;
|
||||
import com.chameleonvision.network.NetworkManager;
|
||||
import com.chameleonvision.settings.GeneralSettings;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.util.Utilities;
|
||||
@@ -134,34 +136,40 @@ public class Main {
|
||||
}
|
||||
|
||||
if (testMode) {
|
||||
ConfigManager.initializeSettings();
|
||||
NetworkManager.initialize(manageNetwork);
|
||||
NetworkTableInstance.getDefault().startServer();
|
||||
|
||||
boolean visionSourcesOk = VisionManager.initializeSources();
|
||||
if (!visionSourcesOk) {
|
||||
System.out.println("No cameras connected!");
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkManager.initialize(manageNetwork);
|
||||
|
||||
boolean visionProcessesOk = VisionManager.initializeProcesses();
|
||||
if (!visionProcessesOk) {
|
||||
System.err.println("shit");
|
||||
return;
|
||||
}
|
||||
|
||||
runServer();
|
||||
VisionManager.startProcesses();
|
||||
|
||||
// runServer(true);
|
||||
} else {
|
||||
if (CameraManager.initializeCameras()) {
|
||||
SettingsManager.initialize();
|
||||
NetworkManager.initialize(manageNetwork);
|
||||
CameraManager.initializeThreads();
|
||||
runServer();
|
||||
runServer(false);
|
||||
} else {
|
||||
System.err.println("No cameras connected!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void runServer() {
|
||||
private static void runServer(boolean test) {
|
||||
GeneralSettings settings = test ? ConfigManager.settings : SettingsManager.generalSettings;
|
||||
|
||||
if (ntServerMode) {
|
||||
System.out.println("Starting NT Server");
|
||||
NetworkTableInstance.getDefault().startServer();
|
||||
@@ -170,7 +178,7 @@ public class Main {
|
||||
if (ntClientModeServer != null) {
|
||||
NetworkTableInstance.getDefault().startClient(ntClientModeServer);
|
||||
} else {
|
||||
NetworkTableInstance.getDefault().startClientTeam(SettingsManager.generalSettings.teamNumber);
|
||||
NetworkTableInstance.getDefault().startClientTeam(settings.teamNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.chameleonvision.classabstraction;
|
||||
import com.chameleonvision.classabstraction.camera.USBCameraProcess;
|
||||
import com.chameleonvision.classabstraction.config.CameraConfig;
|
||||
import com.chameleonvision.classabstraction.config.ConfigManager;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.util.FileHelper;
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
@@ -11,9 +12,7 @@ import org.opencv.videoio.VideoCapture;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class VisionManager {
|
||||
|
||||
@@ -22,6 +21,7 @@ public class VisionManager {
|
||||
private static final Path CamConfigPath = Paths.get(SettingsManager.SettingsPath.toString(), "cameras");
|
||||
|
||||
public static final LinkedHashMap<String, UsbCameraInfo> UsbCameraInfosByCameraName = new LinkedHashMap<>();
|
||||
private static final LinkedList<CameraConfig> LoadedCameraConfigs = new LinkedList<>();
|
||||
public static final LinkedHashMap<String, VisionProcess> VisionProcessesByCameraName = new LinkedHashMap<>();
|
||||
|
||||
public static boolean initializeSources() {
|
||||
@@ -46,70 +46,41 @@ public class VisionManager {
|
||||
FileHelper.CheckPath(CamConfigPath);
|
||||
|
||||
// load the config
|
||||
List<CameraConfig> loadedConfigs = ConfigManager.initializeCameraConfig(new ArrayList<>(UsbCameraInfosByCameraName.keySet()));
|
||||
loadedConfigs.forEach(config -> {
|
||||
var camera = new USBCameraProcess(
|
||||
new edu.wpi.cscore.UsbCamera(config.name, config.path),
|
||||
config
|
||||
);
|
||||
VisionProcessesByCameraName.put(config.name, new VisionProcess(camera, config.name));
|
||||
List<CameraConfig> preliminaryConfigs = new ArrayList<>();
|
||||
|
||||
UsbCameraInfosByCameraName.values().forEach((cameraInfo) -> {
|
||||
String truePath;
|
||||
|
||||
if (Platform.CurrentPlatform.isWindows()) {
|
||||
truePath = cameraInfo.path;
|
||||
} else {
|
||||
truePath = Arrays.stream(cameraInfo.otherPaths).filter(x -> x.contains("/dev/v4l/by-path")).findFirst().orElse(cameraInfo.path);
|
||||
}
|
||||
|
||||
preliminaryConfigs.add(new CameraConfig(truePath, cameraInfo.name));
|
||||
});
|
||||
|
||||
|
||||
LoadedCameraConfigs.addAll(ConfigManager.initializeCameraConfig(preliminaryConfigs));
|
||||
// UsbCameraInfosByCameraName.forEach((cameraName, cameraInfo) -> {
|
||||
// Path cameraConfigFolder = Paths.get(CamConfigPath.toString(), String.format("%s\\", cameraName));
|
||||
// Path cameraConfigPath = Paths.get(cameraConfigFolder.toString(), String.format("%s.json", cameraName));
|
||||
// Path cameraPipelinesPath = Paths.get(cameraConfigFolder.toString(), "pipelines.json");
|
||||
// Path cameraDrivermodePath = Paths.get(cameraConfigFolder.toString(), "drivermode.json");
|
||||
//
|
||||
// try {
|
||||
//
|
||||
// boolean cameraFolderExists = Files.exists(cameraConfigFolder);
|
||||
//
|
||||
// if (!cameraFolderExists) {
|
||||
// Files.createDirectory(cameraConfigFolder);
|
||||
// }
|
||||
// boolean cameraConfigExists = cameraFolderExists && Files.exists(cameraConfigPath);
|
||||
//
|
||||
// if (Files.exists(cameraConfigFolder)) {
|
||||
// if (Files.exists(cameraConfigPath)) {
|
||||
// File cameraConfigFile = new File(cameraConfigPath.toString());
|
||||
// if (cameraConfigFile.length() != 0) {
|
||||
// try {
|
||||
// Gson gson = new GsonBuilder().create();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// Files.createFile(cameraConfigPath);
|
||||
// }
|
||||
// } else {
|
||||
// Files.createDirectory(cameraConfigFolder);
|
||||
// }
|
||||
// } catch (IOException ex) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// });
|
||||
|
||||
// FileHelper.CheckPath(CamConfigPath);
|
||||
// UsbCameraInfosByCameraName.forEach((cameraName, cameraInfo) -> {
|
||||
// Path cameraConfigPath = Paths.get(CamConfigPath.toString(), String.format("%s.json", cameraName));
|
||||
// File cameraConfigFile = new File(cameraConfigPath.toString());
|
||||
// if (cameraConfigFile.exists() && cameraConfigFile.length() != 0) {
|
||||
//// try {
|
||||
//// Gson gson = new GsonBuilder().registerTypeAdapter(USBCameraProcess.class, new CameraDeserializer());
|
||||
//// }
|
||||
// }
|
||||
// })
|
||||
// TODO: implement new camera JSON loads
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean initializeProcesses() {
|
||||
|
||||
LoadedCameraConfigs.forEach(config -> {
|
||||
var camera = new USBCameraProcess(config);
|
||||
VisionProcessesByCameraName.put(config.name, new VisionProcess(camera, config.name));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void startProcesses() {
|
||||
VisionProcessesByCameraName.forEach((name, process) -> {
|
||||
process.start();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,17 +34,29 @@ public class VisionProcess {
|
||||
// Thread to grab frames from the camera
|
||||
// TODO: fix video modes!!!
|
||||
this.cameraRunnable = new CameraFrameRunnable(cameraProcess.getProperties().videoModes.get(0).fps);
|
||||
new Thread(cameraRunnable).start();
|
||||
|
||||
// Thread to put frames on the dashboard
|
||||
this.cameraStreamer = new CameraStreamer(cameraProcess, name);
|
||||
this.streamRunnable = new CameraStreamerRunnable(1000L/32, cameraStreamer);
|
||||
new Thread(streamRunnable).start();
|
||||
|
||||
// Thread to process vision data
|
||||
this.visionRunnable = new VisionProcessRunnable();
|
||||
new Thread(visionRunnable).start();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
System.out.println("Starting camera thread.");
|
||||
new Thread(cameraRunnable).start();
|
||||
while (cameraRunnable.cameraFrame == null) {
|
||||
try {
|
||||
if (cameraRunnable.cameraFrame.cols() > 0) break;
|
||||
} catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.out.println("Starting vision thread.");
|
||||
new Thread(visionRunnable).start();
|
||||
System.out.println("Starting stream thread.");
|
||||
new Thread(streamRunnable).start();
|
||||
}
|
||||
|
||||
public void setPipeline(int pipelineIndex) {
|
||||
@@ -73,7 +85,7 @@ public class VisionProcess {
|
||||
* at a specified loopTime
|
||||
*/
|
||||
protected class CameraFrameRunnable extends LoopingRunnable {
|
||||
private Mat cameraFrame = new Mat();
|
||||
private Mat cameraFrame;
|
||||
private long timestampMicros;
|
||||
|
||||
private final Object frameLock = new Object();
|
||||
@@ -95,18 +107,23 @@ public class VisionProcess {
|
||||
|
||||
// Grab camera frames
|
||||
var camData = cameraProcess.getFrame();
|
||||
synchronized (frameLock) {
|
||||
cameraFrame = camData.getLeft();
|
||||
if (camData.getLeft().cols() > 0) {
|
||||
// System.out.println("grabbing frame");
|
||||
// synchronized (frameLock) {
|
||||
cameraFrame = camData.getLeft();
|
||||
// }
|
||||
timestampMicros = camData.getRight();
|
||||
}
|
||||
timestampMicros = camData.getRight();
|
||||
}
|
||||
}
|
||||
|
||||
public Mat getFrame(Mat dst) {
|
||||
synchronized (frameLock) {
|
||||
cameraFrame.copyTo(dst);
|
||||
return dst;
|
||||
if (cameraFrame != null) {
|
||||
dst = cameraFrame;
|
||||
} else {
|
||||
System.out.println("no frame");
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
public long getTimestampMicros() {
|
||||
@@ -125,7 +142,12 @@ public class VisionProcess {
|
||||
@Override
|
||||
public void run() {
|
||||
while(!Thread.interrupted()) {
|
||||
result = currentPipeline.runPipeline(cameraRunnable.getFrame(streamBuffer));
|
||||
streamBuffer = cameraRunnable.getFrame(streamBuffer);
|
||||
if (streamBuffer.cols() > 0 && streamBuffer.rows() > 0) {
|
||||
result = currentPipeline.runPipeline(streamBuffer);
|
||||
} else {
|
||||
// System.err.println("Bad streambuffer mat");
|
||||
}
|
||||
// TODO do something with the result
|
||||
}
|
||||
}
|
||||
@@ -143,7 +165,16 @@ public class VisionProcess {
|
||||
|
||||
@Override
|
||||
protected void process() {
|
||||
streamer.runStream(cameraRunnable.getFrame(streamBuffer));
|
||||
CVPipelineResult latestResult = visionRunnable.result;
|
||||
if (latestResult != null) {
|
||||
Mat toStreamMat = visionRunnable.result.outputMat;
|
||||
streamBuffer = toStreamMat;
|
||||
streamer.runStream(toStreamMat);
|
||||
// if (toStreamMat != null && toStreamMat.cols() > 0) {
|
||||
// } else {
|
||||
// System.out.println("fuuuuck");
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import com.chameleonvision.Main;
|
||||
import com.chameleonvision.classabstraction.config.CameraConfig;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import com.chameleonvision.vision.camera.USBCamera;
|
||||
import edu.wpi.cscore.UsbCamera;
|
||||
import edu.wpi.cscore.UsbCameraInfo;
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
@@ -16,7 +13,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class CameraProperties {
|
||||
private static final double DEFAULT_FOV = 70;
|
||||
public 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;
|
||||
@@ -61,8 +58,16 @@ public class CameraProperties {
|
||||
System.out.printf("USBCameraProcess initialized in %.2fms\n", initTimeMs);
|
||||
}
|
||||
|
||||
// TODO: find way to determine if camera is a PS3Eye
|
||||
hasGain = false;
|
||||
var props = baseCamera.enumerateProperties();
|
||||
// var props = baseCamera.enumerateProperties();
|
||||
// for (var prop : props) {
|
||||
// var name = prop.getName();
|
||||
// var min = prop.getMin();
|
||||
// var max = prop.getMax();
|
||||
// var _default = prop.getDefault();
|
||||
// var kind = prop.getKind();
|
||||
// }
|
||||
|
||||
videoModes = filterVideoModes(baseCamera.enumerateVideoModes());
|
||||
}
|
||||
@@ -85,12 +90,12 @@ public class CameraProperties {
|
||||
staticProperties = new CameraStaticProperties(videoMode.width, videoMode.height, FOV);
|
||||
}
|
||||
|
||||
public double CalculatePitch(double PixelY, double centerY) {
|
||||
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) {
|
||||
public double calculateYaw(double PixelX, double centerX) {
|
||||
return FastMath.toDegrees(FastMath.atan((PixelX - centerX) / staticProperties.horizontalFocalLength));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package com.chameleonvision.classabstraction.camera;
|
||||
|
||||
import com.chameleonvision.vision.camera.StreamDivisor;
|
||||
import com.chameleonvision.web.ServerHandler;
|
||||
import edu.wpi.cscore.CvSource;
|
||||
import edu.wpi.cscore.VideoMode;
|
||||
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;
|
||||
@@ -24,6 +21,7 @@ public class CameraStreamer {
|
||||
this.cvSource = CameraServer.getInstance().putVideo(name,
|
||||
cameraProcess.getProperties().staticProperties.imageWidth / divisor.value,
|
||||
cameraProcess.getProperties().staticProperties.imageHeight / divisor.value);
|
||||
setDivisor(divisor);
|
||||
}
|
||||
|
||||
public void setDivisor(StreamDivisor newDivisor) {
|
||||
@@ -37,7 +35,7 @@ public class CameraStreamer {
|
||||
cameraProcess.getProperties().staticProperties.imageWidth / divisor.value,
|
||||
cameraProcess.getProperties().staticProperties.imageHeight / divisor.value);
|
||||
}
|
||||
ServerHandler.sendFullSettings();
|
||||
// ServerHandler.sendFullSettings();
|
||||
}
|
||||
|
||||
public void setNewVideoMode(VideoMode newVideoMode) {
|
||||
@@ -47,14 +45,16 @@ public class CameraStreamer {
|
||||
}
|
||||
|
||||
public void runStream(Mat image) {
|
||||
image.copyTo(streamBuffer);
|
||||
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(streamBuffer, streamBuffer, newSize);
|
||||
synchronized (streamBufferLock) {
|
||||
streamBuffer = image;
|
||||
}
|
||||
// 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(streamBuffer, streamBuffer, newSize);
|
||||
// }
|
||||
cvSource.putFrame(streamBuffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,10 @@ public class USBCameraProcess implements CameraProcess {
|
||||
private Mat imageBuffer = new Mat();
|
||||
private CameraProperties properties;
|
||||
|
||||
public USBCameraProcess(UsbCamera camera, CameraConfig config) {
|
||||
baseCamera = camera;
|
||||
|
||||
public USBCameraProcess(CameraConfig config) {
|
||||
baseCamera = new UsbCamera(config.name, config.path);
|
||||
cvSink = CameraServer.getInstance().getVideo(baseCamera);
|
||||
properties = new CameraProperties(baseCamera, config.fov);
|
||||
properties = new CameraProperties(baseCamera, config);
|
||||
|
||||
setVideoMode(properties.videoModes.get(0));
|
||||
}
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
package com.chameleonvision.classabstraction.config;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class CameraConfig {
|
||||
public final double fov;
|
||||
public final String path;
|
||||
public final String name;
|
||||
public final String nickname;
|
||||
|
||||
public CameraConfig(double FOV,
|
||||
String path, String name,
|
||||
String nickname) {
|
||||
this.fov = FOV;
|
||||
@JsonCreator
|
||||
public CameraConfig(
|
||||
@JsonProperty("fov") double fov,
|
||||
@JsonProperty("path") String path,
|
||||
@JsonProperty("name") String name,
|
||||
@JsonProperty("nickname") String nickname) {
|
||||
this.fov = fov;
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public CameraConfig(String path, String name) {
|
||||
this.fov = CameraProperties.DEFAULT_FOV;
|
||||
this.path = path;
|
||||
this.name = name;
|
||||
this.nickname = name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,37 +2,25 @@ package com.chameleonvision.classabstraction.config;
|
||||
|
||||
import com.chameleonvision.classabstraction.util.ProgramDirectoryUtilities;
|
||||
import com.chameleonvision.settings.GeneralSettings;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.util.FileHelper;
|
||||
import com.chameleonvision.vision.camera.CameraDeserializer;
|
||||
import com.chameleonvision.vision.camera.USBCamera;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class ConfigManager {
|
||||
private ConfigManager() {}
|
||||
|
||||
private static final Path SettingsPath = Paths.get(ProgramDirectoryUtilities.getProgramDirectory(), "settings");
|
||||
private static final Path cameraConfigPath = Paths.get(ProgramDirectoryUtilities.getProgramDirectory(), "cameras");
|
||||
private static final Path cameraConfigPath = Paths.get(SettingsPath.toString(), "cameras");
|
||||
|
||||
public static GeneralSettings settings = new GeneralSettings();
|
||||
|
||||
public static void initializeSettings() {
|
||||
boolean settingsFolderExists = Files.exists(SettingsPath);
|
||||
|
||||
if (!settingsFolderExists) {
|
||||
if (Files.notExists(SettingsPath)) {
|
||||
try {
|
||||
Files.createDirectory(SettingsPath);
|
||||
} catch (IOException e) {
|
||||
@@ -42,11 +30,10 @@ public class ConfigManager {
|
||||
|
||||
// try to load the settings file and deserialize it
|
||||
Path settingsFilePath = Paths.get(SettingsPath.toString(), "settings.json");
|
||||
boolean settingsFileExists = Files.exists(settingsFilePath);
|
||||
|
||||
if (!settingsFileExists) {
|
||||
if (Files.notExists(settingsFilePath)) {
|
||||
try {
|
||||
FileHelper.Serializer(settings, settingsFilePath);
|
||||
FileHelper.Serializer(settingsFilePath, settings);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -57,53 +44,41 @@ public class ConfigManager {
|
||||
System.err.println("Failed to load settings.json, using defaults.");
|
||||
}
|
||||
}
|
||||
|
||||
// try to load camera file and deserialize it
|
||||
// var cameraConfigs = initializeCameraConfig();
|
||||
|
||||
}
|
||||
|
||||
public static List<CameraConfig> initializeCameraConfig(List<String> cameraNames) {
|
||||
|
||||
public static List<CameraConfig> initializeCameraConfig(List<CameraConfig> preliminaryConfigs) {
|
||||
var configList = new ArrayList<CameraConfig>();
|
||||
|
||||
|
||||
// loop over all the camera names and try to create settings folders for it
|
||||
cameraNames.forEach((cameraName) -> {
|
||||
final Path cameraConfigFolder = Paths.get(cameraConfigPath.toString(), String.format("%s\\", cameraName));
|
||||
final Path cameraConfigPath = Paths.get(cameraConfigFolder.toString(), String.format("%s.json", cameraName));
|
||||
preliminaryConfigs.forEach((preliminaryConfig) -> {
|
||||
|
||||
final Path cameraConfigFolderPath = Paths.get(cameraConfigPath.toString(), String.format("%s\\", preliminaryConfig.name));
|
||||
final Path cameraConfigPath = Paths.get(cameraConfigFolderPath.toString(), "camera.json");
|
||||
|
||||
// check if the config folder exists, and if not, create it
|
||||
boolean cameraConfigFolderExists = Files.exists(cameraConfigFolder);
|
||||
|
||||
if (!cameraConfigFolderExists) {
|
||||
if (Files.notExists(cameraConfigFolderPath)) {
|
||||
try {
|
||||
Files.createDirectory(cameraConfigFolder);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// try to deserialize the file
|
||||
var camJsonFile = new File(cameraConfigPath.toString());
|
||||
if(camJsonFile.exists() && camJsonFile.length() > 0) {
|
||||
try {
|
||||
var config = FileHelper.DeSerializer(cameraConfigPath, CameraConfig.class);
|
||||
configList.add(config);
|
||||
Files.createDirectory(cameraConfigFolderPath);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
// create a default one
|
||||
configList.add(new CameraConfig(
|
||||
70.0,
|
||||
cameraConfigPath.toString(),
|
||||
cameraName,
|
||||
cameraName
|
||||
));
|
||||
CameraConfig config = preliminaryConfig;
|
||||
if(!Files.exists(cameraConfigPath)) {
|
||||
try {
|
||||
FileHelper.Serializer(cameraConfigPath, preliminaryConfig);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
config = FileHelper.DeSerializer(cameraConfigPath, CameraConfig.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
configList.add(config);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
return configList;
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.function.Supplier;
|
||||
* @param <R> Pipeline result type
|
||||
*/
|
||||
public abstract class CVPipeline<R extends CVPipelineResult, S extends CVPipelineSettings> {
|
||||
protected Mat outputMat;
|
||||
protected Mat outputMat = new Mat();
|
||||
CameraProcess cameraProcess;
|
||||
final Supplier<S> settingsSupplier;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class CVPipeline2d extends CVPipeline<CVPipeline2dResult, CVPipeline2dSet
|
||||
var settings = settingsSupplier.get();
|
||||
CameraStaticProperties camProps = cameraProcess.getProperties().staticProperties;
|
||||
|
||||
inputMat.copyTo(rawCameraMat);
|
||||
rawCameraMat = inputMat;
|
||||
|
||||
// prepare pipes
|
||||
RotateFlipPipe rotateFlipPipe = new RotateFlipPipe(ImageRotation.DEG_0, settings.flipMode);
|
||||
|
||||
@@ -7,13 +7,13 @@ import java.util.List;
|
||||
public abstract class CVPipelineResult<T> {
|
||||
public final List<T> targets;
|
||||
public final boolean hasTarget;
|
||||
public final Mat outputMat = new Mat();
|
||||
public final Mat outputMat;
|
||||
public final long processTime;
|
||||
|
||||
public CVPipelineResult(List<T> targets, Mat outputMat, long processTime) {
|
||||
this.targets = targets;
|
||||
hasTarget = targets != null && !targets.isEmpty();
|
||||
outputMat.copyTo(this.outputMat);
|
||||
this.outputMat = outputMat;
|
||||
this.processTime = processTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.chameleonvision.classabstraction.pipeline;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraProcess;
|
||||
import com.chameleonvision.classabstraction.pipeline.pipes.Draw2dContoursPipe;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.chameleonvision.classabstraction.pipeline.DriverVisionPipeline.*;
|
||||
import static com.chameleonvision.classabstraction.pipeline.DriverVisionPipeline.DriverPipelineResult;
|
||||
|
||||
public class DriverVisionPipeline extends CVPipeline<DriverPipelineResult, CVPipelineSettings> {
|
||||
|
||||
@@ -14,16 +15,18 @@ public class DriverVisionPipeline extends CVPipeline<DriverPipelineResult, CVPip
|
||||
super(settingsSupplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPipeline(CameraProcess camera) {
|
||||
camera.setBrightness((int) getSettings().brightness);
|
||||
camera.setExposure((int) getSettings().exposure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DriverPipelineResult runPipeline(Mat inputMat) {
|
||||
|
||||
inputMat.copyTo(outputMat);
|
||||
outputMat = inputMat;
|
||||
|
||||
var camProps = cameraProcess.getProperties().staticProperties;
|
||||
|
||||
Draw2dContoursPipe.Draw2dContoursSettings draw2dContoursSettings = new Draw2dContoursPipe.Draw2dContoursSettings();
|
||||
draw2dContoursSettings.showCrosshair = true;
|
||||
Draw2dContoursPipe draw2dContoursPipe = new Draw2dContoursPipe(draw2dContoursSettings, camProps);
|
||||
|
||||
outputMat = draw2dContoursPipe.run(Pair.of(outputMat, null)).getLeft();
|
||||
|
||||
return new DriverPipelineResult(null, inputMat, 0);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.chameleonvision.classabstraction.pipeline.pipes;
|
||||
|
||||
import com.chameleonvision.classabstraction.camera.CameraStaticProperties;
|
||||
import com.chameleonvision.classabstraction.util.Helpers;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.opencv.core.*;
|
||||
import org.opencv.core.Point;
|
||||
import org.opencv.core.*;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -26,37 +27,41 @@ public class Draw2dContoursPipe implements Pipe<Pair<Mat, List<RotatedRect>>, Ma
|
||||
public Pair<Mat, Long> run(Pair<Mat, List<RotatedRect>> input) {
|
||||
long processStartNanos = System.nanoTime();
|
||||
|
||||
input.getLeft().copyTo(outputMat);
|
||||
outputMat = input.getLeft();
|
||||
|
||||
for (RotatedRect r : input.getRight()) {
|
||||
if (r == null) continue;
|
||||
if (input.getRight() != null && !input.getRight().isEmpty()) {
|
||||
for (RotatedRect r : input.getRight()) {
|
||||
if (r == null) continue;
|
||||
|
||||
List<MatOfPoint> drawnContour = new ArrayList<>();
|
||||
Point[] vertices = new Point[4];
|
||||
r.points(vertices);
|
||||
MatOfPoint contour = new MatOfPoint(vertices);
|
||||
drawnContour.add(contour);
|
||||
List<MatOfPoint> drawnContour = new ArrayList<>();
|
||||
Point[] vertices = new Point[4];
|
||||
r.points(vertices);
|
||||
MatOfPoint contour = new MatOfPoint(vertices);
|
||||
drawnContour.add(contour);
|
||||
|
||||
if (settings.showCentroid) {
|
||||
Imgproc.circle(outputMat, r.center, 3, colorToScalar(settings.centroidColor));
|
||||
if (settings.showCentroid) {
|
||||
Imgproc.circle(outputMat, r.center, 3, Helpers.colorToScalar(settings.centroidColor));
|
||||
}
|
||||
|
||||
if (settings.showRotatedBox) {
|
||||
Imgproc.drawContours(outputMat, drawnContour, 0, Helpers.colorToScalar(settings.rotatedBoxColor), settings.boxOutlineSize);
|
||||
}
|
||||
|
||||
if (settings.showMaximumBox) {
|
||||
Rect box = Imgproc.boundingRect(contour);
|
||||
Imgproc.rectangle(outputMat, new Point(box.x, box.y), new Point((box.x + box.width), (box.y + box.height)), Helpers.colorToScalar(settings.maximumBoxColor), settings.boxOutlineSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.showCrosshair) {
|
||||
Point xMax = new Point(camProps.centerX + 10, camProps.centerY);
|
||||
Point xMin = new Point(camProps.centerX - 10, camProps.centerY);
|
||||
Point yMax = new Point(camProps.centerX, camProps.centerY + 10);
|
||||
Point yMin = new Point(camProps.centerX, camProps.centerY - 10);
|
||||
Imgproc.line(outputMat, xMax, xMin, colorToScalar(settings.crosshairColor), 2);
|
||||
Imgproc.line(outputMat, yMax, yMin, colorToScalar(settings.crosshairColor), 2);
|
||||
}
|
||||
|
||||
if (settings.showRotatedBox) {
|
||||
Imgproc.drawContours(outputMat, drawnContour, 0, colorToScalar(settings.rotatedBoxColor), settings.boxOutlineSize);
|
||||
}
|
||||
|
||||
if (settings.showMaximumBox) {
|
||||
Rect box = Imgproc.boundingRect(contour);
|
||||
Imgproc.rectangle(outputMat, new Point(box.x, box.y), new Point((box.x + box.width), (box.y + box.height)), colorToScalar(settings.maximumBoxColor), settings.boxOutlineSize);
|
||||
if (settings.showCrosshair) {
|
||||
Point xMax = new Point(camProps.centerX + 10, camProps.centerY);
|
||||
Point xMin = new Point(camProps.centerX - 10, camProps.centerY);
|
||||
Point yMax = new Point(camProps.centerX, camProps.centerY + 10);
|
||||
Point yMin = new Point(camProps.centerX, camProps.centerY - 10);
|
||||
if (outputMat != null && outputMat.cols() > 0) {
|
||||
Imgproc.line(outputMat, xMax, xMin, Helpers.colorToScalar(settings.crosshairColor), 2);
|
||||
Imgproc.line(outputMat, yMax, yMin, Helpers.colorToScalar(settings.crosshairColor), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +71,6 @@ public class Draw2dContoursPipe implements Pipe<Pair<Mat, List<RotatedRect>>, Ma
|
||||
return output;
|
||||
}
|
||||
|
||||
private Scalar colorToScalar(Color color) {
|
||||
return new Scalar(color.getRed(), color.getGreen(), color.getBlue());
|
||||
}
|
||||
|
||||
public static class Draw2dContoursSettings {
|
||||
public boolean showCentroid = false;
|
||||
public boolean showCrosshair = false;
|
||||
@@ -80,6 +81,5 @@ public class Draw2dContoursPipe implements Pipe<Pair<Mat, List<RotatedRect>>, Ma
|
||||
public Color crosshairColor = Color.GREEN;
|
||||
public Color rotatedBoxColor = Color.BLUE;
|
||||
public Color maximumBoxColor = Color.RED;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,7 @@ public class OutputMatPipe implements Pipe<Pair<Mat, Mat>, Mat> {
|
||||
public Pair<Mat, Long> run(Pair<Mat, Mat> input) {
|
||||
long processStartNanos = System.nanoTime();
|
||||
|
||||
if (showThresholded) {
|
||||
input.getRight().copyTo(outputMat);
|
||||
} else {
|
||||
input.getLeft().copyTo(outputMat);
|
||||
}
|
||||
outputMat = showThresholded ? input.getRight() : input.getLeft();
|
||||
|
||||
long processTime = processStartNanos - System.nanoTime();
|
||||
Pair<Mat, Long> output = Pair.of(outputMat, processTime);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.chameleonvision.classabstraction.util;
|
||||
|
||||
import org.opencv.core.Scalar;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class Helpers {
|
||||
private Helpers() {}
|
||||
|
||||
public static Scalar colorToScalar(Color color) {
|
||||
return new Scalar(color.getRed(), color.getGreen(), color.getBlue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,7 +27,8 @@ public class ProgramDirectoryUtilities
|
||||
return getCurrentJARDirectory();
|
||||
} else
|
||||
{
|
||||
return getCurrentProjectDirectory();
|
||||
return System.getProperty("user.dir");
|
||||
// return getCurrentProjectDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ import java.net.SocketException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.chameleonvision.settings.Platform.CurrentPlatform;
|
||||
|
||||
public class NetworkManager {
|
||||
private NetworkManager() {}
|
||||
|
||||
@@ -22,9 +20,11 @@ public class NetworkManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CurrentPlatform.isLinux()) {
|
||||
Platform platform = Platform.getCurrentPlatform();
|
||||
|
||||
if (platform.isLinux()) {
|
||||
networking = new LinuxNetworking();
|
||||
} else if (CurrentPlatform.isWindows()) {
|
||||
} else if (platform.isWindows()) {
|
||||
// networking = new WindowsNetworking();
|
||||
System.out.println("Windows networking is not yet supported. Running unmanaged.");
|
||||
return;
|
||||
|
||||
@@ -28,15 +28,20 @@ public class FileHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static void Serializer(Object object, Path path) throws IOException {
|
||||
public static void Serializer(Path path, Object object) throws IOException {
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(Object.class).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT).build();
|
||||
objectMapper.writeValue(new File(path.toString()), object);
|
||||
objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(path.toString()), object);
|
||||
}
|
||||
|
||||
public static <T> T DeSerializer(Path path, Class<T> ref) throws IOException {
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(Object.class).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT).build();
|
||||
return objectMapper.readValue(new File(path.toString()), ref);
|
||||
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(ref).build();
|
||||
ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv).build();
|
||||
File jsonFile = new File(path.toString());
|
||||
if (jsonFile.exists() && jsonFile.length() > 0) {
|
||||
T readObject = objectMapper.readValue(jsonFile, ref);
|
||||
return readObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user