Convert input/output image save to integers (#664)

Changes image saving technique to use integers, not booleans
This commit is contained in:
Chris Gerth
2022-12-30 21:48:28 -06:00
committed by GitHub
parent 8028d1887c
commit d0bf64af6c
4 changed files with 46 additions and 50 deletions

View File

@@ -17,20 +17,18 @@
package org.photonvision.vision.frame.consumer;
import edu.wpi.first.networktables.BooleanEntry;
import edu.wpi.first.networktables.IntegerEntry;
import edu.wpi.first.networktables.NetworkTable;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import org.opencv.imgcodecs.Imgcodecs;
import org.photonvision.common.configuration.ConfigManager;
import org.photonvision.common.dataflow.networktables.NetworkTablesManager;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
import org.photonvision.common.util.TimedTaskManager;
import org.photonvision.vision.opencv.CVMat;
public class FileSaveFrameConsumer implements Consumer<CVMat> {
@@ -44,29 +42,27 @@ public class FileSaveFrameConsumer implements Consumer<CVMat> {
private NetworkTable subTable;
private final NetworkTable rootTable;
private final Logger logger;
private boolean prevCommand = false;
private long imgSaveCountInternal = 0;
private String camNickname;
private String fnamePrefix;
private final long CMD_RESET_TIME_MS = 500;
private final BooleanEntry entry;
// Helps prevent race conditions between user set & auto-reset logic
private ReentrantLock lock;
private IntegerEntry entry;
public FileSaveFrameConsumer(String camNickname, String streamPrefix) {
this.lock = new ReentrantLock();
this.fnamePrefix = camNickname + "_" + streamPrefix;
this.ntEntryName = streamPrefix + NT_SUFFIX;
this.rootTable = NetworkTablesManager.getInstance().kRootTable;
updateCameraNickname(camNickname);
entry = subTable.getBooleanTopic(ntEntryName).getEntry(false);
this.logger = new Logger(FileSaveFrameConsumer.class, this.camNickname, LogGroup.General);
}
public void accept(CVMat image) {
if (image != null && image.getMat() != null && !image.getMat().empty()) {
if (lock.tryLock()) {
boolean curCommand = entry.get(false);
if (curCommand && !prevCommand) {
var curCommand = entry.get(); // default to just our current count
if (curCommand >= 0) {
// Only do something if we got a valid current command
if (imgSaveCountInternal < curCommand) {
// Save one frame.
// Create the filename
Date now = new Date();
String savefile =
FILE_PATH
@@ -78,42 +74,32 @@ public class FileSaveFrameConsumer implements Consumer<CVMat> {
+ tf.format(now)
+ FILE_EXTENSION;
// write to file
Imgcodecs.imwrite(savefile, image.getMat());
// Help the user a bit - set the NT entry back to false after 500ms
TimedTaskManager.getInstance().addOneShotTask(this::resetCommand, CMD_RESET_TIME_MS);
// Count one more image saved
imgSaveCountInternal++;
logger.info("Saved new image at " + savefile);
} else if (!curCommand) {
// If the entry is currently false, set it again. This will make sure it shows up on the
// dashboard.
entry.set(false);
} else if (imgSaveCountInternal > curCommand) {
imgSaveCountInternal = curCommand;
}
prevCommand = curCommand;
lock.unlock();
}
}
}
private void resetCommand() {
lock.lock();
this.subTable.getEntry(ntEntryName).setBoolean(false);
lock.unlock();
}
private void removeEntries() {
if (this.subTable != null) {
if (this.subTable.containsKey(ntEntryName)) {
this.subTable.getEntry(ntEntryName).close();
}
}
}
public void updateCameraNickname(String newCameraNickname) {
removeEntries();
// Remove existing entries
if (this.subTable != null) {
if (this.subTable.containsKey(ntEntryName)) {
this.subTable.getEntry(ntEntryName).close();
}
}
// Recreate and re-init network tables structure
this.camNickname = newCameraNickname;
this.subTable = rootTable.getSubTable(this.camNickname);
resetCommand();
this.subTable.getEntry(ntEntryName).setInteger(imgSaveCountInternal);
this.entry = subTable.getIntegerTopic(ntEntryName).getEntry(-1); // Default negative
}
}

View File

@@ -56,7 +56,7 @@ public class PhotonCamera {
DoubleArrayPublisher targetPoseEntry;
DoublePublisher targetSkewEntry;
StringSubscriber versionEntry;
BooleanPublisher inputSaveImgEntry, outputSaveImgEntry;
IntegerEntry inputSaveImgEntry, outputSaveImgEntry;
IntegerEntry pipelineIndexEntry, ledModeEntry;
IntegerSubscriber heartbeatEntry;
@@ -111,8 +111,8 @@ public class PhotonCamera {
path = rootTable.getPath();
rawBytesEntry = rootTable.getRawTopic("rawBytes").subscribe("rawBytes", new byte[] {});
driverModeEntry = rootTable.getBooleanTopic("driverMode").getEntry(false);
inputSaveImgEntry = rootTable.getBooleanTopic("inputSaveImgCmd").getEntry(false);
outputSaveImgEntry = rootTable.getBooleanTopic("outputSaveImgCmd").getEntry(false);
inputSaveImgEntry = rootTable.getIntegerTopic("inputSaveImgCmd").getEntry(0);
outputSaveImgEntry = rootTable.getIntegerTopic("outputSaveImgCmd").getEntry(0);
pipelineIndexEntry = rootTable.getIntegerTopic("pipelineIndex").getEntry(0);
heartbeatEntry = rootTable.getIntegerTopic("heartbeat").subscribe(-1);
ledModeEntry = mainTable.getIntegerTopic("ledMode").getEntry(-1);
@@ -181,7 +181,7 @@ public class PhotonCamera {
* /opt/photonvision/photonvision_config/imgSaves frequently to prevent issues.
*/
public void takeInputSnapshot() {
inputSaveImgEntry.set(true);
inputSaveImgEntry.set(inputSaveImgEntry.get() + 1);
}
/**
@@ -191,7 +191,7 @@ public class PhotonCamera {
* /opt/photonvision/photonvision_config/imgSaves frequently to prevent issues.
*/
public void takeOutputSnapshot() {
outputSaveImgEntry.set(true);
outputSaveImgEntry.set(outputSaveImgEntry.get() + 1);
}
/**

View File

@@ -41,9 +41,13 @@ PhotonCamera::PhotonCamera(std::shared_ptr<nt::NetworkTableInstance> instance,
rawBytesEntry(rootTable->GetRawTopic("rawBytes").Subscribe("raw", {})),
driverModeEntry(rootTable->GetBooleanTopic("driverMode").Publish()),
inputSaveImgEntry(
rootTable->GetBooleanTopic("inputSaveImgCmd").Publish()),
rootTable->GetIntegerTopic("inputSaveImgCmd").Publish()),
inputSaveImgSubscriber(
rootTable->GetIntegerTopic("inputSaveImgCmd").Subscribe(0)),
outputSaveImgEntry(
rootTable->GetBooleanTopic("outputSaveImgCmd").Publish()),
rootTable->GetIntegerTopic("outputSaveImgCmd").Publish()),
outputSaveImgSubscriber(
rootTable->GetIntegerTopic("outputSaveImgCmd").Subscribe(0)),
pipelineIndexEntry(rootTable->GetIntegerTopic("pipelineIndex").Publish()),
ledModeEntry(mainTable->GetIntegerTopic("ledMode").Publish()),
versionEntry(mainTable->GetStringTopic("version").Subscribe("")),
@@ -89,9 +93,13 @@ void PhotonCamera::SetDriverMode(bool driverMode) {
driverModeEntry.Set(driverMode);
}
void PhotonCamera::TakeInputSnapshot() { inputSaveImgEntry.Set(true); }
void PhotonCamera::TakeInputSnapshot() {
inputSaveImgEntry.Set(inputSaveImgSubscriber.Get() + 1);
}
void PhotonCamera::TakeOutputSnapshot() { outputSaveImgEntry.Set(true); }
void PhotonCamera::TakeOutputSnapshot() {
outputSaveImgEntry.Set(outputSaveImgSubscriber.Get() + 1);
}
bool PhotonCamera::GetDriverMode() const { return driverModeSubscriber.Get(); }

View File

@@ -166,8 +166,10 @@ class PhotonCamera {
std::shared_ptr<nt::NetworkTable> rootTable;
nt::RawSubscriber rawBytesEntry;
nt::BooleanPublisher driverModeEntry;
nt::BooleanPublisher inputSaveImgEntry;
nt::BooleanPublisher outputSaveImgEntry;
nt::IntegerPublisher inputSaveImgEntry;
nt::IntegerSubscriber inputSaveImgSubscriber;
nt::IntegerPublisher outputSaveImgEntry;
nt::IntegerSubscriber outputSaveImgSubscriber;
nt::IntegerPublisher pipelineIndexEntry;
nt::IntegerPublisher ledModeEntry;
nt::StringSubscriber versionEntry;