From 038e84ce0dc36f86b3c007d655603b2e2953f25f Mon Sep 17 00:00:00 2001 From: Banks Troutman Date: Sat, 21 Sep 2019 13:05:00 -0400 Subject: [PATCH] Various cleanup, slowed down UI FPS counter --- .../settings/SettingsManager.java | 12 +++--- .../vision/GeneralSettings.java | 2 - .../vision/camera/CamVideoMode.java | 1 + .../chameleonvision/vision/camera/Camera.java | 7 +--- .../vision/camera/CameraDeserializer.java | 1 - .../vision/camera/CameraManager.java | 12 ++++-- .../vision/camera/CameraSerializer.java | 1 - .../vision/camera/CameraValues.java | 1 + .../vision/process/CameraProcess.java | 33 +++++++++------ .../vision/process/VisionProcess.java | 42 +------------------ .../java/com/chameleonvision/web/Server.java | 11 ----- .../chameleonvision/web/ServerHandler.java | 12 +++--- 12 files changed, 45 insertions(+), 90 deletions(-) diff --git a/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java b/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java index c99557e7d..76d6b28da 100644 --- a/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java +++ b/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java @@ -12,23 +12,21 @@ import java.io.FileWriter; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.HashMap; public class SettingsManager { public static final Path SettingsPath = Paths.get(System.getProperty("user.dir"), "Settings"); public static com.chameleonvision.vision.GeneralSettings GeneralSettings; - public static HashMap CameraPorts = new HashMap<>(); private SettingsManager() {} public static void initialize() { initGeneralSettings(); NetworkSettings netSettings = new NetworkSettings(); - netSettings.hostname=GeneralSettings.hostname; - netSettings.gateway=GeneralSettings.gateway; - netSettings.netmask=GeneralSettings.netmask; - netSettings.connectionType=GeneralSettings.connection_type; - netSettings.ip=GeneralSettings.ip; + netSettings.hostname = GeneralSettings.hostname; + netSettings.gateway = GeneralSettings.gateway; + netSettings.netmask = GeneralSettings.netmask; + netSettings.connectionType = GeneralSettings.connection_type; + netSettings.ip = GeneralSettings.ip; netSettings.run(); var allCameras = CameraManager.getAllCamerasByName(); diff --git a/Main/src/main/java/com/chameleonvision/vision/GeneralSettings.java b/Main/src/main/java/com/chameleonvision/vision/GeneralSettings.java index b8d9ee485..2fb587b32 100644 --- a/Main/src/main/java/com/chameleonvision/vision/GeneralSettings.java +++ b/Main/src/main/java/com/chameleonvision/vision/GeneralSettings.java @@ -9,6 +9,4 @@ public class GeneralSettings { public String hostname = "Chameleon-vision"; public String curr_camera = ""; public Integer curr_pipeline = null; - - } diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CamVideoMode.java b/Main/src/main/java/com/chameleonvision/vision/camera/CamVideoMode.java index e2a295c40..23555197b 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CamVideoMode.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CamVideoMode.java @@ -2,6 +2,7 @@ package com.chameleonvision.vision.camera; import edu.wpi.cscore.VideoMode; +@SuppressWarnings("WeakerAccess") public class CamVideoMode { public final int fps; public final int width; diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java b/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java index a5f22da48..581b43f52 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/Camera.java @@ -1,6 +1,5 @@ package com.chameleonvision.vision.camera; -import com.chameleonvision.settings.SettingsManager; import com.chameleonvision.vision.Pipeline; import edu.wpi.cscore.*; import edu.wpi.first.cameraserver.CameraServer; @@ -70,7 +69,7 @@ public class Camera { cvSink = cs.getVideo(UsbCam); cvSource = cs.putVideo(name, camVals.ImageWidth, camVals.ImageHeight); var s = (MjpegServer) cs.getServer("serve_" + name); - SettingsManager.CameraPorts.put(name, s.getPort()); + CameraManager.CameraPorts.put(name, s.getPort()); } public void setCamVideoMode(int videoMode) { @@ -160,10 +159,6 @@ public class Camera { return cvSink.grabFrame(image); } - public long grabFrame(Mat image, double timeout) { - return cvSink.grabFrame(image, timeout); - } - public CameraValues getCamVals() { return camVals; } diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java index 326edfc5f..afb1b7155 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraDeserializer.java @@ -15,7 +15,6 @@ public class CameraDeserializer implements JsonDeserializer { public Camera deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException { var jsonObj = jsonElement.getAsJsonObject(); var camFOV = jsonObj.get("FOV").getAsDouble(); - var camPath = jsonObj.get("path").getAsString(); var camName = jsonObj.get("name").getAsString(); var pipelines = jsonObj.get("pipelines"); diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java index e83eb3f95..0f7f5ec65 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraManager.java @@ -39,7 +39,11 @@ public class CameraManager { private static HashMap AllCamerasByName = new HashMap<>(); - public static HashMap getAllCamerasByName() { return AllCamerasByName; } + public static HashMap getAllCamerasByName() { + return AllCamerasByName; + } + + public static HashMap CameraPorts = new HashMap<>(); public static boolean initializeCameras() { if (AllUsbCameraInfosByName.size() == 0) return false; @@ -77,7 +81,8 @@ public class CameraManager { } public static void setCurrentCamera(String cameraName) throws CameraException { - if (!AllCamerasByName.containsKey(cameraName)) throw new CameraException(CameraException.CameraExceptionType.BAD_CAMERA); + if (!AllCamerasByName.containsKey(cameraName)) + throw new CameraException(CameraException.CameraExceptionType.BAD_CAMERA); SettingsManager.GeneralSettings.curr_camera = cameraName; SettingsManager.updateCameraSetting(cameraName, getCurrentCamera().getCurrentPipelineIndex()); } @@ -90,7 +95,8 @@ public class CameraManager { } public static void setCurrentPipeline(int pipelineNumber) throws CameraException { - if (!getCurrentCamera().getPipelines().containsKey(pipelineNumber)) throw new CameraException(CameraException.CameraExceptionType.BAD_PIPELINE); + if (!getCurrentCamera().getPipelines().containsKey(pipelineNumber)) + throw new CameraException(CameraException.CameraExceptionType.BAD_PIPELINE); getCurrentCamera().setCurrentPipelineIndex(pipelineNumber); SettingsManager.updatePipelineSetting(pipelineNumber); } diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java index ab138f1f7..dc712bb26 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraSerializer.java @@ -14,7 +14,6 @@ public class CameraSerializer implements JsonSerializer { var pipelines = context.serialize(camera.getPipelines()); obj.add("pipelines", pipelines); - var videoModeIndex = camera.getVideoModeIndex(); obj.addProperty("resolution", camera.getVideoModeIndex()); obj.add("camVideoMode", context.serialize(camera.getVideoMode())); diff --git a/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java b/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java index a6d11e8a1..d9b0dc0e0 100644 --- a/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java +++ b/Main/src/main/java/com/chameleonvision/vision/camera/CameraValues.java @@ -3,6 +3,7 @@ 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; diff --git a/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java index 60aae4fd3..2d073076a 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/CameraProcess.java @@ -1,11 +1,9 @@ package com.chameleonvision.vision.process; -import com.chameleonvision.MemoryManager; import com.chameleonvision.settings.SettingsManager; import com.chameleonvision.vision.Pipeline; import com.chameleonvision.vision.camera.Camera; -import com.chameleonvision.vision.camera.CameraValues; -import com.chameleonvision.web.Server; +import com.chameleonvision.web.ServerHandler; import edu.wpi.first.networktables.*; import org.opencv.core.*; import org.opencv.imgproc.Imgproc; @@ -28,8 +26,6 @@ public class CameraProcess implements Runnable { private NetworkTableEntry ntTimeStampEntry; private NetworkTableEntry ntValidEntry; - private MemoryManager memManager = new MemoryManager(125); - // chameleon specific private Pipeline currentPipeline; private VisionProcess visionProcess; @@ -67,7 +63,7 @@ public class CameraProcess implements Runnable { camera.setBrightness(pipeline.brightness); HashMap pipeChange = new HashMap<>(); pipeChange.put("curr_pipeline",ntPipelineIndex); - Server.handler.broadcastMessage(pipeChange); + ServerHandler.broadcastMessage(pipeChange); } else { ntPipelineEntry.setString("pipeline" + camera.getCurrentPipelineIndex()); @@ -169,8 +165,11 @@ public class CameraProcess implements Runnable { public void run() { // processing time tracking long startTime; + long fpsLastTime = 0; double processTimeMs; double fps = 0; + double uiFps = 0; + int maxFps = camera.getVideoMode().fps; new Thread(streamProcess).start(); @@ -178,16 +177,23 @@ public class CameraProcess implements Runnable { while (!Thread.interrupted()) { startTime = System.nanoTime(); - if ((startTime - lastFrameEndNanosec) * 1e-6 >= 1000.0/camera.getVideoMode().fps) { - - + if ((startTime - lastFrameEndNanosec) * 1e-6 >= 1000.0/maxFps + 3) { // 3 additional fps to allow for overhead FoundContours.clear(); FilteredContours.clear(); GroupedContours.clear(); + // update FPS for ui only every 0.5 seconds + if ((startTime - fpsLastTime) * 1e-6 >= 500) { + if (fps >= maxFps) { + uiFps = maxFps; + } else { + uiFps = fps; + } + fpsLastTime = System.nanoTime(); + } + currentPipeline = camera.getCurrentPipeline(); // start fps counter right before grabbing input frame - startTime = System.nanoTime(); TimeStamp = camera.grabFrame(cameraInputMat); if (cameraInputMat.cols() == 0 && cameraInputMat.rows() == 0) { continue; @@ -211,10 +217,10 @@ public class CameraProcess implements Runnable { point.put("pitch", 0); point.put("yaw", 0); } - point.put("fps", fps); + point.put("fps", uiFps); WebSend.put("point", point); WebSend.put("raw_point", center); - Server.handler.broadcastMessage(WebSend); + ServerHandler.broadcastMessage(WebSend); } //camera.putFrame(streamOutputMat); @@ -227,7 +233,8 @@ public class CameraProcess implements Runnable { lastFrameEndNanosec = System.nanoTime(); processTimeMs = (lastFrameEndNanosec - startTime) * 1e-6; fps = 1000 / processTimeMs; - System.out.printf("%s - Process time: %.2fms, FPS: %.2f, FoundContours: %d, FilteredContours: %d, GroupedContours: %d\n", cameraName, processTimeMs, fps, FoundContours.size(), FilteredContours.size(), GroupedContours.size()); + + System.out.printf("%s - Process time: %-5.2fms, FPS: %-5.2f, FoundContours: %d, FilteredContours: %d, GroupedContours: %d\n", cameraName, processTimeMs, fps, FoundContours.size(), FilteredContours.size(), GroupedContours.size()); } } } diff --git a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java index 82cd302f3..6d7b2a1ec 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/VisionProcess.java @@ -8,6 +8,7 @@ import org.opencv.imgproc.*; import java.util.*; +@SuppressWarnings("WeakerAccess") public class VisionProcess { private HashMapTargetGrouping= new HashMap<>() {{ @@ -49,7 +50,7 @@ public class VisionProcess { return FoundContours; } - private List FilteredContours = new ArrayList(); + private List FilteredContours = new ArrayList<>(); List FilterContours(List InputContours, List area, List ratio, List extent) { for (MatOfPoint Contour : InputContours){ try{ @@ -74,15 +75,6 @@ public class VisionProcess { return FilteredContours; } - private static Comparator SortByLargestComparator = (rect1, rect2) -> Double.compare(rect2.size.area(), rect1.size.area()); - private static Comparator SortBySmallestComparator = SortByLargestComparator.reversed(); - - private static Comparator SortByHighestComparator = (rect1, rect2) -> Double.compare(rect2.center.y, rect1.center.y); - private static Comparator SortByLowestComparator = SortByHighestComparator.reversed(); - - private static Comparator SortByLeftmostComparator = Comparator.comparingDouble(rect -> rect.center.x); - private static Comparator SortByRightmostComparator = SortByLeftmostComparator.reversed(); - private double calcDistance(RotatedRect rect) { return FastMath.sqrt(FastMath.pow(CamVals.CenterX - rect.center.x, 2) + FastMath.pow(CamVals.CenterY - rect.center.y, 2)); } @@ -105,41 +97,11 @@ public class VisionProcess { return Collections.max(inputRects, Comparator.comparing(rect -> rect.center.x)); case "Centermost": return Collections.min(inputRects, SortByCentermostComparator); -// return inputRects.stream().sorted(SortByCentermostComparator).collect(Collectors.toList()).get(0); default: return inputRects.get(0); // default to whatever the first contour is, but this should never happen } } - - void SortTargets(List inputRects, String sortMode) { - switch (sortMode) { - case "Largest": - inputRects.sort(SortByLargestComparator); - break; - case "Smallest": - inputRects.sort(SortBySmallestComparator); - break; - case "Highest": - inputRects.sort(SortByHighestComparator); - break; - case "Lowest": - inputRects.sort(SortByLowestComparator); - break; - case "Leftmost": - inputRects.sort(SortByLeftmostComparator); - break; - case "Rightmost": - inputRects.sort(SortByRightmostComparator); - break; - case "Centermost": - inputRects.sort(SortByCentermostComparator); - break; - default: - break; - } - } - private List FinalCountours = new ArrayList<>(); List GroupTargets(List InputContours, String IntersectionPoint, String TargetGroup) { FinalCountours.clear(); diff --git a/Main/src/main/java/com/chameleonvision/web/Server.java b/Main/src/main/java/com/chameleonvision/web/Server.java index 6a77be2ca..bc83257ca 100644 --- a/Main/src/main/java/com/chameleonvision/web/Server.java +++ b/Main/src/main/java/com/chameleonvision/web/Server.java @@ -1,18 +1,7 @@ package com.chameleonvision.web; -import com.chameleonvision.CameraException; import com.chameleonvision.settings.SettingsManager; -import com.chameleonvision.vision.camera.CameraManager; -import edu.wpi.cscore.VideoException; import io.javalin.Javalin; -import io.javalin.websocket.WsContext; - -import java.lang.reflect.Field; -import java.util.*; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.springframework.beans.BeanUtils; public class Server { diff --git a/Main/src/main/java/com/chameleonvision/web/ServerHandler.java b/Main/src/main/java/com/chameleonvision/web/ServerHandler.java index b3c2a3df6..ab45c09bb 100644 --- a/Main/src/main/java/com/chameleonvision/web/ServerHandler.java +++ b/Main/src/main/java/com/chameleonvision/web/ServerHandler.java @@ -23,11 +23,11 @@ public class ServerHandler { private static List users; - public ServerHandler() { - this.users = new ArrayList<>(); + ServerHandler() { + users = new ArrayList<>(); } - public void onConnect(WsConnectContext context) { + void onConnect(WsConnectContext context) { users.add(context); sendFullSettings(); } @@ -36,7 +36,7 @@ public class ServerHandler { users.remove(context); } - public void onMessage(WsMessageContext data) throws CameraException { + void onMessage(WsMessageContext data) throws CameraException { broadcastMessage(data.message(), data); JSONObject jsonObject = new JSONObject(data.message()); @@ -83,7 +83,7 @@ public class ServerHandler { String newCamera = (String) value; System.out.printf("Changing camera to %s\n", newCamera); CameraManager.setCurrentCamera(newCamera); - broadcastMessage(new HashMap(){}.put("port",SettingsManager.CameraPorts.get(SettingsManager.GeneralSettings.curr_camera))); + broadcastMessage(new HashMap(){}.put("port",CameraManager.CameraPorts.get(SettingsManager.GeneralSettings.curr_camera))); broadcastMessage(CameraManager.getCurrentCamera()); //TODO CHECK JSON FOR CAMERA CHANGE break; @@ -183,7 +183,7 @@ public class ServerHandler { fullSettings.put("resolutionList", CameraManager.getResolutionList()); fullSettings.put("resolution", currentCamera.getVideoModeIndex()); fullSettings.put("FOV", currentCamera.getFOV()); - fullSettings.put("port", SettingsManager.CameraPorts.get(SettingsManager.GeneralSettings.curr_camera)); + fullSettings.put("port", CameraManager.CameraPorts.get(SettingsManager.GeneralSettings.curr_camera)); } catch (CameraException e) { System.err.println("No camera found!"); //TODO: add message to ui to inform that there are no cameras