2019-11-23 11:55:20 -05:00
|
|
|
package com.chameleonvision.vision;
|
2019-11-10 11:47:56 -05:00
|
|
|
|
2019-11-23 11:55:20 -05:00
|
|
|
import com.chameleonvision.config.ConfigManager;
|
|
|
|
|
import com.chameleonvision.util.LoopingRunnable;
|
2019-11-25 05:34:04 -05:00
|
|
|
import com.chameleonvision.vision.camera.CameraCapture;
|
2019-11-23 11:55:20 -05:00
|
|
|
import com.chameleonvision.vision.camera.CameraStreamer;
|
|
|
|
|
import com.chameleonvision.vision.pipeline.*;
|
2019-11-22 14:20:23 -08:00
|
|
|
import com.chameleonvision.web.ServerHandler;
|
2019-11-27 21:46:07 +02:00
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
2019-11-16 11:10:55 -08:00
|
|
|
import edu.wpi.cscore.VideoMode;
|
2019-11-23 20:13:01 -08:00
|
|
|
import edu.wpi.first.networktables.*;
|
2019-11-23 08:22:20 -08:00
|
|
|
import edu.wpi.first.wpiutil.CircularBuffer;
|
2019-11-26 02:55:05 -05:00
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
2019-11-15 16:01:50 -05:00
|
|
|
import org.opencv.core.Mat;
|
2019-11-10 11:47:56 -05:00
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
2019-11-22 14:20:23 -08:00
|
|
|
import java.util.HashMap;
|
2019-11-10 11:47:56 -05:00
|
|
|
import java.util.List;
|
2019-11-26 17:57:51 -05:00
|
|
|
import java.util.concurrent.BlockingQueue;
|
|
|
|
|
import java.util.concurrent.LinkedBlockingDeque;
|
2019-11-10 11:47:56 -05:00
|
|
|
|
2019-11-26 22:18:29 -08:00
|
|
|
|
2019-11-10 11:47:56 -05:00
|
|
|
public class VisionProcess {
|
|
|
|
|
|
2019-11-25 05:34:04 -05:00
|
|
|
private final CameraCapture cameraCapture;
|
2019-11-10 11:47:56 -05:00
|
|
|
private final List<CVPipeline> pipelines = new ArrayList<>();
|
2019-11-16 14:30:44 -05:00
|
|
|
private final CameraStreamerRunnable streamRunnable;
|
2019-11-16 10:17:33 -08:00
|
|
|
private final VisionProcessRunnable visionRunnable;
|
2019-11-23 04:05:37 -05:00
|
|
|
public final CameraStreamer cameraStreamer;
|
|
|
|
|
|
2019-11-10 11:47:56 -05:00
|
|
|
private CVPipeline currentPipeline;
|
2019-11-22 14:20:23 -08:00
|
|
|
private int currentPipelineIndex = 0;
|
2019-11-10 11:47:56 -05:00
|
|
|
|
2019-11-26 17:57:51 -05:00
|
|
|
private CVPipeline driverModePipeline = new DriverVisionPipeline(new CVPipelineSettings());
|
2019-11-10 11:47:56 -05:00
|
|
|
|
2019-11-21 21:49:25 -08:00
|
|
|
private volatile CVPipelineResult lastPipelineResult;
|
|
|
|
|
|
2019-11-26 23:03:07 -05:00
|
|
|
private BlockingQueue<Mat> streamFrameQueue = new LinkedBlockingDeque<>(1);
|
2019-11-26 17:57:51 -05:00
|
|
|
|
2019-11-22 14:20:23 -08:00
|
|
|
// network table stuff
|
2019-11-26 02:55:05 -05:00
|
|
|
private final NetworkTable defaultTable;
|
2019-11-23 04:05:37 -05:00
|
|
|
private NetworkTableEntry ntPipelineEntry;
|
|
|
|
|
private NetworkTableEntry ntDriverModeEntry;
|
2019-11-22 14:20:23 -08:00
|
|
|
private int ntDriveModeListenerID;
|
|
|
|
|
private int ntPipelineListenerID;
|
|
|
|
|
private NetworkTableEntry ntYawEntry;
|
|
|
|
|
private NetworkTableEntry ntPitchEntry;
|
|
|
|
|
private NetworkTableEntry ntAuxListEntry;
|
2019-11-23 04:05:37 -05:00
|
|
|
private NetworkTableEntry ntAreaEntry;
|
2019-11-22 14:20:23 -08:00
|
|
|
private NetworkTableEntry ntTimeStampEntry;
|
|
|
|
|
private NetworkTableEntry ntValidEntry;
|
2019-11-27 21:46:07 +02:00
|
|
|
private ObjectMapper objectMapper;
|
2019-11-22 14:20:23 -08:00
|
|
|
|
2019-11-25 05:34:04 -05:00
|
|
|
VisionProcess(CameraCapture cameraCapture, String name) {
|
|
|
|
|
this.cameraCapture = cameraCapture;
|
2019-11-10 11:47:56 -05:00
|
|
|
|
2019-11-23 04:05:37 -05:00
|
|
|
pipelines.add(new CVPipeline2d("New Pipeline"));
|
2019-11-23 20:02:21 -05:00
|
|
|
setPipeline(0, false);
|
2019-11-15 16:01:50 -05:00
|
|
|
|
2019-11-16 10:17:33 -08:00
|
|
|
// Thread to put frames on the dashboard
|
2019-11-25 05:34:04 -05:00
|
|
|
this.cameraStreamer = new CameraStreamer(cameraCapture, name);
|
2019-11-21 22:08:10 -08:00
|
|
|
this.streamRunnable = new CameraStreamerRunnable(30, cameraStreamer);
|
2019-11-16 10:17:33 -08:00
|
|
|
|
|
|
|
|
// Thread to process vision data
|
|
|
|
|
this.visionRunnable = new VisionProcessRunnable();
|
2019-11-23 20:13:01 -08:00
|
|
|
|
|
|
|
|
// network table
|
2019-11-25 05:34:04 -05:00
|
|
|
defaultTable = NetworkTableInstance.getDefault().getTable("/chameleon-vision/" + cameraCapture.getProperties().name);
|
2019-11-21 05:32:19 -05:00
|
|
|
}
|
2019-11-16 10:17:33 -08:00
|
|
|
|
2019-11-21 05:32:19 -05:00
|
|
|
public void start() {
|
2019-11-26 02:55:05 -05:00
|
|
|
System.out.println("Starting NetworkTables.");
|
2019-11-23 20:13:01 -08:00
|
|
|
initNT(defaultTable);
|
2019-11-21 05:32:19 -05:00
|
|
|
System.out.println("Starting vision thread.");
|
|
|
|
|
new Thread(visionRunnable).start();
|
|
|
|
|
System.out.println("Starting stream thread.");
|
|
|
|
|
new Thread(streamRunnable).start();
|
2019-11-10 11:47:56 -05:00
|
|
|
}
|
|
|
|
|
|
2019-11-22 14:20:23 -08:00
|
|
|
/**
|
|
|
|
|
* Removes the old value change listeners
|
|
|
|
|
* calls {@link #initNT}
|
|
|
|
|
*
|
|
|
|
|
* @param newTable passed to {@link #initNT}
|
|
|
|
|
*/
|
|
|
|
|
public void resetNT(NetworkTable newTable) {
|
|
|
|
|
ntDriverModeEntry.removeListener(ntDriveModeListenerID);
|
|
|
|
|
ntPipelineEntry.removeListener(ntPipelineListenerID);
|
|
|
|
|
initNT(newTable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initNT(NetworkTable newTable) {
|
|
|
|
|
ntPipelineEntry = newTable.getEntry("pipeline");
|
|
|
|
|
ntDriverModeEntry = newTable.getEntry("driver_mode");
|
|
|
|
|
ntPitchEntry = newTable.getEntry("pitch");
|
|
|
|
|
ntYawEntry = newTable.getEntry("yaw");
|
2019-11-23 04:05:37 -05:00
|
|
|
ntAreaEntry = newTable.getEntry("area");
|
2019-11-22 14:20:23 -08:00
|
|
|
ntTimeStampEntry = newTable.getEntry("timestamp");
|
|
|
|
|
ntValidEntry = newTable.getEntry("is_valid");
|
2019-11-24 20:57:48 -08:00
|
|
|
ntAuxListEntry = newTable.getEntry("aux_targets");
|
2019-11-22 14:20:23 -08:00
|
|
|
ntDriveModeListenerID = ntDriverModeEntry.addListener(this::setDriverMode, EntryListenerFlags.kUpdate);
|
|
|
|
|
ntPipelineListenerID = ntPipelineEntry.addListener(this::setPipeline, EntryListenerFlags.kUpdate);
|
|
|
|
|
ntDriverModeEntry.setBoolean(false);
|
|
|
|
|
ntPipelineEntry.setNumber(0);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-23 04:05:37 -05:00
|
|
|
private void setDriverMode(EntryNotification driverModeEntryNotification) {
|
|
|
|
|
setDriverMode(driverModeEntryNotification.value.getBoolean());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setDriverMode(boolean driverMode) {
|
|
|
|
|
if (driverMode) {
|
|
|
|
|
setPipelineInternal(driverModePipeline);
|
|
|
|
|
} else {
|
2019-11-23 20:02:21 -05:00
|
|
|
setPipeline(currentPipelineIndex, true);
|
2019-11-23 04:05:37 -05:00
|
|
|
}
|
2019-11-22 14:20:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Method called by the nt entry listener to update the next pipeline.
|
|
|
|
|
* @param notification the notification
|
|
|
|
|
*/
|
|
|
|
|
private void setPipeline(EntryNotification notification) {
|
|
|
|
|
var wantedPipelineIndex = (int) notification.value.getDouble();
|
|
|
|
|
|
|
|
|
|
if (wantedPipelineIndex >= pipelines.size()) {
|
|
|
|
|
ntPipelineEntry.setNumber(currentPipelineIndex);
|
|
|
|
|
} else {
|
|
|
|
|
currentPipelineIndex = wantedPipelineIndex;
|
2019-11-23 20:02:21 -05:00
|
|
|
setPipeline(wantedPipelineIndex, true);
|
2019-11-22 14:20:23 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-23 20:02:21 -05:00
|
|
|
public void setPipeline(int pipelineIndex, boolean updateUI) {
|
2019-11-10 11:47:56 -05:00
|
|
|
CVPipeline newPipeline = pipelines.get(pipelineIndex);
|
|
|
|
|
if (newPipeline != null) {
|
2019-11-22 14:20:23 -08:00
|
|
|
setPipelineInternal(newPipeline);
|
2019-11-23 04:05:37 -05:00
|
|
|
currentPipelineIndex = pipelineIndex;
|
|
|
|
|
|
|
|
|
|
// update the configManager
|
2019-11-25 05:34:04 -05:00
|
|
|
if(ConfigManager.settings.currentCamera.equals(cameraCapture.getProperties().name)) {
|
2019-11-23 04:05:37 -05:00
|
|
|
ConfigManager.settings.currentPipeline = pipelineIndex;
|
2019-11-23 20:02:21 -05:00
|
|
|
|
|
|
|
|
if (updateUI) {
|
|
|
|
|
HashMap<String, Object> pipeChange = new HashMap<>();
|
|
|
|
|
pipeChange.put("currentPipeline", pipelineIndex);
|
|
|
|
|
ServerHandler.broadcastMessage(pipeChange);
|
|
|
|
|
ServerHandler.sendFullSettings();
|
|
|
|
|
}
|
2019-11-23 04:05:37 -05:00
|
|
|
}
|
2019-11-22 14:20:23 -08:00
|
|
|
}
|
2019-11-10 11:47:56 -05:00
|
|
|
}
|
|
|
|
|
|
2019-11-22 14:20:23 -08:00
|
|
|
private void setPipelineInternal(CVPipeline pipeline) {
|
2019-11-10 11:47:56 -05:00
|
|
|
currentPipeline = pipeline;
|
2019-11-25 05:34:04 -05:00
|
|
|
currentPipeline.initPipeline(cameraCapture);
|
2019-11-10 11:47:56 -05:00
|
|
|
}
|
|
|
|
|
|
2019-11-22 14:20:23 -08:00
|
|
|
private void updateUI(CVPipelineResult data) {
|
2019-11-25 05:34:04 -05:00
|
|
|
if(cameraCapture.getProperties().name.equals(ConfigManager.settings.currentCamera)) {
|
2019-11-22 14:20:23 -08:00
|
|
|
HashMap<String, Object> WebSend = new HashMap<>();
|
|
|
|
|
HashMap<String, Object> point = new HashMap<>();
|
|
|
|
|
HashMap<String, Object> calculated = new HashMap<>();
|
|
|
|
|
List<Double> center = new ArrayList<>();
|
|
|
|
|
if (data.hasTarget) {
|
|
|
|
|
if(data instanceof CVPipeline2d.CVPipeline2dResult) {
|
|
|
|
|
CVPipeline2d.CVPipeline2dResult result = (CVPipeline2d.CVPipeline2dResult) data;
|
2019-11-23 04:05:37 -05:00
|
|
|
CVPipeline2d.Target2d bestTarget = result.targets.get(0);
|
2019-11-22 14:20:23 -08:00
|
|
|
center.add(bestTarget.rawPoint.center.x);
|
|
|
|
|
center.add(bestTarget.rawPoint.center.y);
|
|
|
|
|
calculated.put("pitch", bestTarget.pitch);
|
|
|
|
|
calculated.put("yaw", bestTarget.yaw);
|
2019-11-27 21:46:07 +02:00
|
|
|
calculated.put("area", bestTarget.area);
|
2019-11-23 04:05:37 -05:00
|
|
|
} else if (data instanceof CVPipeline3d.CVPipeline3dResult) {
|
|
|
|
|
// TODO: (2.1) 3d stuff in UI
|
2019-11-22 14:20:23 -08:00
|
|
|
} else {
|
|
|
|
|
center.add(0.0);
|
|
|
|
|
center.add(0.0);
|
|
|
|
|
calculated.put("pitch", 0);
|
|
|
|
|
calculated.put("yaw", 0);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
center.add(0.0);
|
|
|
|
|
center.add(0.0);
|
|
|
|
|
calculated.put("pitch", 0);
|
|
|
|
|
calculated.put("yaw", 0);
|
|
|
|
|
}
|
|
|
|
|
point.put("fps", visionRunnable.fps);
|
|
|
|
|
point.put("calculated", calculated);
|
|
|
|
|
point.put("rawPoint", center);
|
|
|
|
|
WebSend.put("point", point);
|
|
|
|
|
ServerHandler.broadcastMessage(WebSend);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateNetworkTableData(CVPipelineResult data) {
|
|
|
|
|
ntValidEntry.setBoolean(data.hasTarget);
|
|
|
|
|
if(data.hasTarget && !(data instanceof DriverVisionPipeline.DriverPipelineResult)) {
|
|
|
|
|
if(data instanceof CVPipeline2d.CVPipeline2dResult) {
|
|
|
|
|
|
|
|
|
|
//noinspection unchecked
|
2019-11-23 04:05:37 -05:00
|
|
|
List<CVPipeline2d.Target2d> targets = (List<CVPipeline2d.Target2d>) data.targets;
|
2019-11-26 02:55:05 -05:00
|
|
|
ntTimeStampEntry.setDouble(data.imageTimestamp);
|
2019-11-22 14:20:23 -08:00
|
|
|
ntPitchEntry.setDouble(targets.get(0).pitch);
|
|
|
|
|
ntYawEntry.setDouble(targets.get(0).yaw);
|
2019-11-23 04:05:37 -05:00
|
|
|
ntAreaEntry.setDouble(targets.get(0).area);
|
2019-11-27 21:46:07 +02:00
|
|
|
try {
|
|
|
|
|
ntAreaEntry.setString(objectMapper.writeValueAsString(targets));
|
|
|
|
|
} catch (JsonProcessingException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
2019-11-23 04:05:37 -05:00
|
|
|
} else if (data instanceof CVPipeline3d.CVPipeline3dResult) {
|
|
|
|
|
// TODO: (2.1) 3d stuff...
|
2019-11-22 14:20:23 -08:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ntPitchEntry.setDouble(0.0);
|
|
|
|
|
ntYawEntry.setDouble(0.0);
|
2019-11-23 04:05:37 -05:00
|
|
|
ntAreaEntry.setDouble(0.0);
|
2019-11-22 14:20:23 -08:00
|
|
|
ntTimeStampEntry.setDouble(0.0);
|
2019-11-26 02:55:05 -05:00
|
|
|
ntAuxListEntry.setString("");
|
2019-11-22 14:20:23 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-16 11:10:55 -08:00
|
|
|
public void setVideoMode(VideoMode newMode) {
|
2019-11-25 05:34:04 -05:00
|
|
|
cameraCapture.setVideoMode(newMode);
|
2019-11-16 11:10:55 -08:00
|
|
|
cameraStreamer.setNewVideoMode(newMode);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-23 04:05:37 -05:00
|
|
|
public List<CVPipeline> getPipelines() {
|
|
|
|
|
return pipelines;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-10 11:47:56 -05:00
|
|
|
public CVPipeline getCurrentPipeline() {
|
|
|
|
|
return currentPipeline;
|
|
|
|
|
}
|
2019-11-15 16:01:50 -05:00
|
|
|
|
2019-11-23 04:05:37 -05:00
|
|
|
public int getCurrentPipelineIndex() {
|
|
|
|
|
return currentPipelineIndex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void addPipeline() {
|
|
|
|
|
// TODO: (2.1) add to UI option between 2d and 3d pipeline
|
|
|
|
|
pipelines.add(new CVPipeline2d());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void addPipeline(CVPipeline pipeline) {
|
|
|
|
|
pipelines.add(pipeline);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-26 17:57:51 -05:00
|
|
|
public void addPipeline(CVPipelineSettings settings) {
|
|
|
|
|
if (settings instanceof CVPipeline2dSettings) {
|
|
|
|
|
pipelines.add(new CVPipeline2d((CVPipeline2dSettings) settings));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-25 05:34:04 -05:00
|
|
|
public CameraCapture getCamera() {
|
|
|
|
|
return cameraCapture;
|
2019-11-23 04:05:37 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean getDriverMode() {
|
|
|
|
|
return (currentPipeline == driverModePipeline);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-26 17:57:51 -05:00
|
|
|
public void setDriverModeSettings(CVPipelineSettings settings) {
|
|
|
|
|
|
|
|
|
|
driverModePipeline.settings = settings;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-23 04:05:37 -05:00
|
|
|
public CVPipelineSettings getDriverModeSettings() {
|
|
|
|
|
return driverModePipeline.settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public CVPipeline getPipelineByIndex(int pipelineIndex) {
|
|
|
|
|
return pipelines.get(pipelineIndex);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-16 10:17:33 -08:00
|
|
|
/**
|
|
|
|
|
* VisionProcessRunnable will process images as quickly as possible
|
|
|
|
|
*/
|
|
|
|
|
private class VisionProcessRunnable implements Runnable {
|
2019-11-15 16:01:50 -05:00
|
|
|
|
2019-11-23 08:23:49 -08:00
|
|
|
volatile Double fps = 0.0;
|
2019-11-23 08:22:20 -08:00
|
|
|
private CircularBuffer fpsAveragingBuffer = new CircularBuffer(7);
|
2019-11-16 10:17:33 -08:00
|
|
|
private Mat streamBuffer = new Mat();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
2019-11-23 08:22:20 -08:00
|
|
|
var lastUpdateTimeNanos = System.nanoTime();
|
2019-11-16 10:17:33 -08:00
|
|
|
while(!Thread.interrupted()) {
|
2019-11-21 22:04:17 -08:00
|
|
|
|
2019-11-26 02:55:05 -05:00
|
|
|
// blocking call, will block until camera has a new frame.
|
|
|
|
|
Pair<Mat, Long> camData = cameraCapture.getFrame();
|
2019-11-21 22:04:17 -08:00
|
|
|
|
2019-11-26 02:55:05 -05:00
|
|
|
Mat camFrame = camData.getLeft();
|
|
|
|
|
if (camFrame.cols() > 0 && camFrame.rows() > 0) {
|
|
|
|
|
CVPipelineResult result = currentPipeline.runPipeline(camFrame);
|
2019-11-22 14:20:23 -08:00
|
|
|
|
2019-11-24 19:31:45 -05:00
|
|
|
if (result != null) {
|
2019-11-26 02:55:05 -05:00
|
|
|
result.setTimestamp(camData.getRight());
|
|
|
|
|
lastPipelineResult = result;
|
2019-11-24 19:31:45 -05:00
|
|
|
updateNetworkTableData(lastPipelineResult);
|
|
|
|
|
updateUI(lastPipelineResult);
|
|
|
|
|
}
|
2019-11-21 05:32:19 -05:00
|
|
|
}
|
2019-11-23 08:22:20 -08:00
|
|
|
|
2019-11-26 17:57:51 -05:00
|
|
|
try {
|
|
|
|
|
streamFrameQueue.add(lastPipelineResult.outputMat);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("Vision running faster than stream");
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-23 08:22:20 -08:00
|
|
|
var deltaTimeNanos = lastUpdateTimeNanos - System.nanoTime();
|
|
|
|
|
fpsAveragingBuffer.addFirst(1.0 / (deltaTimeNanos * 1E-09));
|
|
|
|
|
lastUpdateTimeNanos = System.nanoTime();
|
|
|
|
|
fps = getAverageFPS();
|
2019-11-16 10:17:33 -08:00
|
|
|
}
|
|
|
|
|
}
|
2019-11-23 08:22:20 -08:00
|
|
|
|
2019-11-26 02:55:05 -05:00
|
|
|
double getAverageFPS() {
|
2019-11-23 08:22:20 -08:00
|
|
|
var temp = 0.0;
|
|
|
|
|
for(int i = 0; i < 7; i++) {
|
|
|
|
|
temp += fpsAveragingBuffer.get(i);
|
|
|
|
|
}
|
|
|
|
|
temp /= 7.0;
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-16 10:17:33 -08:00
|
|
|
}
|
|
|
|
|
|
2019-11-26 23:03:07 -05:00
|
|
|
private class CameraStreamerRunnable extends LoopingRunnable {
|
2019-11-16 10:17:33 -08:00
|
|
|
|
2019-11-26 02:55:05 -05:00
|
|
|
final CameraStreamer streamer;
|
2019-11-16 10:17:33 -08:00
|
|
|
|
2019-11-21 22:08:10 -08:00
|
|
|
private CameraStreamerRunnable(int cameraFPS, CameraStreamer streamer) {
|
|
|
|
|
// add 2 FPS to allow for a bit of overhead
|
2019-11-26 17:57:51 -05:00
|
|
|
super(1000L/(cameraFPS + 2));
|
2019-11-16 10:17:33 -08:00
|
|
|
this.streamer = streamer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2019-11-16 14:30:44 -05:00
|
|
|
protected void process() {
|
2019-11-26 23:03:07 -05:00
|
|
|
try {
|
|
|
|
|
if (!streamFrameQueue.isEmpty()) {
|
|
|
|
|
Mat latestMat = streamFrameQueue.take();
|
|
|
|
|
if (!latestMat.empty()) {
|
|
|
|
|
streamer.runStream(latestMat);
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("stream mat empty");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
2019-11-16 10:17:33 -08:00
|
|
|
}
|
|
|
|
|
}
|
2019-11-10 11:47:56 -05:00
|
|
|
}
|