Clean up front end, remove decision margin and error bits, remove target family selector (#652)

* clean up front end ui

* address changes

* Further tweaks to camera default gains to help make sure users get a good first impression

* even more saner defaults

* Even even more camera sane defaults

* lint

* lint pt 2

* unit test fixup

Co-authored-by: Chris <chrisgerth010592@gmail.com>
This commit is contained in:
Mohammad Durrani
2022-12-31 18:29:36 -05:00
committed by GitHub
parent d0bf64af6c
commit 1ab5b66829
10 changed files with 168 additions and 213 deletions

View File

@@ -1,196 +1,166 @@
<template>
<div>
<v-select
v-model="selectedFamily"
dark
color="accent"
item-color="secondary"
label="Select target family"
:items="familyList"
@input="handlePipelineUpdate('tagFamily', familyList.indexOf(selectedFamily))"
/>
<v-select
v-model="selectedModel"
dark
color="accent"
item-color="secondary"
label="Select a target model"
:items="targetList"
item-text="name"
item-value="data"
@input="handlePipelineUpdate('targetModel', targetList.indexOf(selectedModel) + 6)"
v-model="selectedFamily"
dark
color="accent"
item-color="secondary"
label="Select target family"
:items="familyList"
@input="handlePipelineUpdate('tagFamily', familyList.indexOf(selectedFamily))"
/>
<CVslider
v-model="decimate"
class="pt-2"
slider-cols="8"
name="Decimate"
min="1"
max="8"
step="1.0"
tooltip="Increases FPS at the expense of range by reducing image resolution initially"
@input="handlePipelineData('decimate')"
v-model="decimate"
class="pt-2"
slider-cols="8"
name="Decimate"
min="1"
max="8"
step="1.0"
tooltip="Increases FPS at the expense of range by reducing image resolution initially"
@input="handlePipelineData('decimate')"
/>
<CVslider
v-model="blur"
class="pt-2"
slider-cols="8"
name="Blur"
min="0"
max="5"
step=".01"
tooltip="Gaussian blur added to the image, high FPS cost for slightly decreased noise"
@input="handlePipelineData('blur')"
v-model="blur"
class="pt-2"
slider-cols="8"
name="Blur"
min="0"
max="5"
step=".01"
tooltip="Gaussian blur added to the image, high FPS cost for slightly decreased noise"
@input="handlePipelineData('blur')"
/>
<CVslider
v-model="threads"
class="pt-2"
slider-cols="8"
name="Threads"
min="1"
max="8"
step="1"
tooltip="Number of threads spawned by the AprilTag detector"
@input="handlePipelineData('threads')"
v-model="threads"
class="pt-2"
slider-cols="8"
name="Threads"
min="1"
max="8"
step="1"
tooltip="Number of threads spawned by the AprilTag detector"
@input="handlePipelineData('threads')"
/>
<CVswitch
v-model="refineEdges"
class="pt-2"
slider-cols="8"
name="Refine Edges"
tooltip="Further refines the apriltag corner position initial estimate, suggested left on"
@input="handlePipelineData('refineEdges')"
v-model="refineEdges"
class="pt-2"
slider-cols="8"
name="Refine Edges"
tooltip="Further refines the apriltag corner position initial estimate, suggested left on"
@input="handlePipelineData('refineEdges')"
/>
<CVslider
v-model="hammingDist"
class="pt-2 pb-4"
slider-cols="8"
name="Max error bits"
min="0"
max="10"
step="1"
tooltip="Maximum number of error bits to correct; potential tags with more will be thrown out. For smaller tags (like 16h5), set this as low as possible."
@input="handlePipelineData('hammingDist')"
v-model="decisionMargin"
class="pt-2 pb-4"
slider-cols="8"
name="Decision Margin Cutoff"
min="0"
max="250"
step="1"
tooltip="Tags with a 'margin' (decoding quality score) less than this wil be rejected. Increase this to reduce the number of false positive detections"
@input="handlePipelineData('decisionMargin')"
/>
<CVslider
v-model="decisionMargin"
class="pt-2 pb-4"
slider-cols="8"
name="Decision Margin Cutoff"
min="0"
max="250"
step="1"
tooltip="Tags with a 'margin' (decoding quality score) less than this wil be rejected. Increase this to reduce the number of false positive detections"
@input="handlePipelineData('decisionMargin')"
/>
<CVslider
v-model="numIterations"
class="pt-2 pb-4"
slider-cols="8"
name="Pose Estimation Iterations"
min="0"
max="500"
step="1"
tooltip="Number of iterations the pose estimation algorithm will run, 50-100 is a good starting point"
@input="handlePipelineData('numIterations')"
v-model="numIterations"
class="pt-2 pb-4"
slider-cols="8"
name="Pose Estimation Iterations"
min="0"
max="500"
step="1"
tooltip="Number of iterations the pose estimation algorithm will run, 50-100 is a good starting point"
@input="handlePipelineData('numIterations')"
/>
</div>
</template>
<script>
import CVslider from '../../components/common/cv-slider'
import CVswitch from '../../components/common/cv-switch'
import CVslider from '../../components/common/cv-slider'
import CVswitch from '../../components/common/cv-switch'
export default {
name: "AprilTag",
components: {
CVslider,
CVswitch,
},
data() {
return {
familyList: ["tag36h11", "tag25h9", "tag16h5"],
// Selected model is offset (ew) by 6 from the photon ordinal, as we only wanna show the 36h11 and 16h5 options
targetList: ['6.5in (36h11) AprilTag', '6in (16h5) AprilTag'], //Keep in sync with TargetModel.java
}
},
computed: {
selectedModel: {
get() {
let ret = this.$store.getters.currentPipelineSettings.targetModel - 6
return this.targetList[ret];
},
set(val) {
this.$store.commit("mutatePipeline", {"targetModel": this.targetList.indexOf(val) + 6})
}
},
selectedFamily: {
get() {
let ret = this.$store.getters.currentPipelineSettings.tagFamily
return this.familyList[ret];
},
set(val) {
this.$store.commit("mutatePipeline", {"tagFamily": this.familyList.indexOf(val)})
}
},
decimate: {
get() {
return this.$store.getters.currentPipelineSettings.decimate
},
set(val) {
this.$store.commit("mutatePipeline", {"decimate": val});
}
},
hammingDist: {
get() {
return this.$store.getters.currentPipelineSettings.hammingDist
},
set(val) {
this.$store.commit("mutatePipeline", {"hammingDist": val});
}
},
decisionMargin: {
get() {
return this.$store.getters.currentPipelineSettings.decisionMargin
},
set(val) {
this.$store.commit("mutatePipeline", {"decisionMargin": val});
}
},
numIterations: {
get() {
return this.$store.getters.currentPipelineSettings.numIterations
},
set(val) {
this.$store.commit("mutatePipeline", {"numIterations": val});
}
},
blur: {
get() {
return this.$store.getters.currentPipelineSettings.blur
},
set(val) {
this.$store.commit("mutatePipeline", {"blur": val});
}
},
threads: {
get() {
return this.$store.getters.currentPipelineSettings.threads
},
set(val) {
this.$store.commit("mutatePipeline", {"threads": val});
}
},
refineEdges: {
get() {
return this.$store.getters.currentPipelineSettings.refineEdges
},
set(val) {
this.$store.commit("mutatePipeline", {"refineEdges": val});
}
},
},
methods: {
}
export default {
name: "AprilTag",
components: {
CVslider,
CVswitch,
},
data() {
return {
familyList: ["tag36h11", "tag25h9", "tag16h5"],
// Selected model is offset (ew) by 6 from the photon ordinal, as we only wanna show the 36h11 and 16h5 options
targetList: ['6in (16h5) AprilTag'], //Keep in sync with TargetModel.java
}
},
computed: {
selectedModel: {
get() {
let ret = this.$store.getters.currentPipelineSettings.targetModel - 6
return this.targetList[ret];
},
set(val) {
this.$store.commit("mutatePipeline", {"targetModel": this.targetList.indexOf(val) + 6})
}
},
selectedFamily: {
get() {
let ret = this.$store.getters.currentPipelineSettings.tagFamily
return this.familyList[ret];
},
set(val) {
this.$store.commit("mutatePipeline", {"tagFamily": this.familyList.indexOf(val)})
}
},
decimate: {
get() {
return this.$store.getters.currentPipelineSettings.decimate
},
set(val) {
this.$store.commit("mutatePipeline", {"decimate": val});
}
},
decisionMargin: {
get() {
return this.$store.getters.currentPipelineSettings.decisionMargin
},
set(val) {
this.$store.commit("mutatePipeline", {"decisionMargin": val});
}
},
numIterations: {
get() {
return this.$store.getters.currentPipelineSettings.numIterations
},
set(val) {
this.$store.commit("mutatePipeline", {"numIterations": val});
}
},
blur: {
get() {
return this.$store.getters.currentPipelineSettings.blur
},
set(val) {
this.$store.commit("mutatePipeline", {"blur": val});
}
},
threads: {
get() {
return this.$store.getters.currentPipelineSettings.threads
},
set(val) {
this.$store.commit("mutatePipeline", {"threads": val});
}
},
refineEdges: {
get() {
return this.$store.getters.currentPipelineSettings.refineEdges
},
set(val) {
this.$store.commit("mutatePipeline", {"refineEdges": val});
}
},
},
methods: {
}
}
</script>

View File

@@ -69,28 +69,7 @@ public class AprilTagPipeline extends CVPipeline<CVPipelineResult, AprilTagPipel
// target model for the draw 3d targets pipeline to work...
// for now, hard code tag width based on enum value
double tagWidth;
// This needs
switch (settings.targetModel) {
case k200mmAprilTag:
{
tagWidth = Units.inchesToMeters(3.25 * 2);
break;
}
case k6in_16h5:
{
tagWidth = Units.inchesToMeters(3 * 2);
break;
}
default:
{
// guess at 200mm?? If it's zero everything breaks, but it should _never_ be zero. Unless
// users select the wrong model...
tagWidth = 0.16;
break;
}
}
double tagWidth = Units.inchesToMeters(3 * 2); // for 6in 16h5 tag.
// AprilTagDetectorParams aprilTagDetectionParams =
// new AprilTagDetectorParams(

View File

@@ -24,17 +24,15 @@ import org.photonvision.vision.target.TargetModel;
@JsonTypeName("AprilTagPipelineSettings")
public class AprilTagPipelineSettings extends AdvancedPipelineSettings {
public AprilTagFamily tagFamily = AprilTagFamily.kTag36h11;
public AprilTagFamily tagFamily = AprilTagFamily.kTag16h5;
public int decimate = 1;
public double blur = 0;
public int threads = 1;
public int threads = 4; // Multiple threads seems to be better performance on most platforms
public boolean debug = false;
public boolean refineEdges = true;
public int numIterations = 200;
// TODO is this a legit, reasonable default?
public int hammingDist = 1;
public int decisionMargin = 30;
public int hammingDist = 0;
public int decisionMargin = 35;
// 3d settings
@@ -42,7 +40,9 @@ public class AprilTagPipelineSettings extends AdvancedPipelineSettings {
super();
pipelineType = PipelineType.AprilTag;
outputShowMultipleTargets = true;
targetModel = TargetModel.k200mmAprilTag;
targetModel = TargetModel.k6in_16h5;
cameraExposure = 20;
cameraAutoExposure = false;
ledMode = false;
}

View File

@@ -40,14 +40,14 @@ public class CVPipelineSettings implements Cloneable {
public String pipelineNickname = "New Pipeline";
public boolean cameraAutoExposure = false;
// manual exposure only used if cameraAutoExposure if false
public double cameraExposure = 100;
public double cameraExposure = 20;
public int cameraBrightness = 50;
// Currently only used by a few cameras (notably the zero-copy Pi Camera driver) with the Gain
// quirk
public int cameraGain = 50;
public int cameraGain = 75;
// Currently only used by the zero-copy Pi Camera driver
public int cameraRedGain = 18;
public int cameraBlueGain = 24;
public int cameraRedGain = 11;
public int cameraBlueGain = 20;
public int cameraVideoModeIndex = 0;
public FrameDivisor streamingFrameDivisor = FrameDivisor.NONE;
public boolean ledMode = false;

View File

@@ -30,7 +30,7 @@ public class Calibration3dPipelineSettings extends AdvancedPipelineSettings {
public Calibration3dPipelineSettings() {
super();
this.cameraAutoExposure = true;
this.inputShouldShow = true;
this.outputShouldShow = true;
}

View File

@@ -45,6 +45,7 @@ public class ColoredShapePipelineSettings extends AdvancedPipelineSettings {
public ColoredShapePipelineSettings() {
super();
pipelineType = PipelineType.ColoredShape;
cameraExposure = 20;
}
@Override

View File

@@ -31,5 +31,6 @@ public class DriverModePipelineSettings extends CVPipelineSettings {
pipelineIndex = PipelineManager.DRIVERMODE_INDEX;
pipelineType = PipelineType.DriverMode;
inputShouldShow = true;
cameraAutoExposure = true;
}
}

View File

@@ -27,5 +27,7 @@ public class ReflectivePipelineSettings extends AdvancedPipelineSettings {
public ReflectivePipelineSettings() {
super();
pipelineType = PipelineType.Reflective;
cameraExposure = 6;
cameraGain = 20;
}
}

View File

@@ -104,14 +104,14 @@ public class VisionModule {
if (cameraQuirks.hasQuirk(CameraQuirk.Gain)) {
pipelineManager.userPipelineSettings.forEach(
it -> {
if (it.cameraGain == -1) it.cameraGain = 20; // Sane default
if (it.cameraGain == -1) it.cameraGain = 75; // Sane default
});
}
if (cameraQuirks.hasQuirk(CameraQuirk.AWBGain)) {
pipelineManager.userPipelineSettings.forEach(
it -> {
if (it.cameraRedGain == -1) it.cameraRedGain = 16; // Sane defaults
if (it.cameraBlueGain == -1) it.cameraBlueGain = 16;
if (it.cameraRedGain == -1) it.cameraRedGain = 11; // Sane defaults
if (it.cameraBlueGain == -1) it.cameraBlueGain = 20;
});
}
@@ -401,7 +401,7 @@ public class VisionModule {
}
if (cameraQuirks.hasQuirk(CameraQuirk.Gain)) {
// If the gain is disabled for some reason, re-enable it
if (pipelineSettings.cameraGain == -1) pipelineSettings.cameraGain = 20;
if (pipelineSettings.cameraGain == -1) pipelineSettings.cameraGain = 75;
visionSource.getSettables().setGain(Math.max(0, pipelineSettings.cameraGain));
} else {
pipelineSettings.cameraGain = -1;
@@ -409,8 +409,8 @@ public class VisionModule {
if (cameraQuirks.hasQuirk(CameraQuirk.AWBGain)) {
// If the AWB gains are disabled for some reason, re-enable it
if (pipelineSettings.cameraRedGain == -1) pipelineSettings.cameraRedGain = 16;
if (pipelineSettings.cameraBlueGain == -1) pipelineSettings.cameraBlueGain = 16;
if (pipelineSettings.cameraRedGain == -1) pipelineSettings.cameraRedGain = 11;
if (pipelineSettings.cameraBlueGain == -1) pipelineSettings.cameraBlueGain = 20;
visionSource.getSettables().setRedGain(Math.max(0, pipelineSettings.cameraRedGain));
visionSource.getSettables().setBlueGain(Math.max(0, pipelineSettings.cameraBlueGain));
} else {

View File

@@ -24,6 +24,7 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.photonvision.common.util.TestUtils;
import org.photonvision.vision.apriltag.AprilTagFamily;
import org.photonvision.vision.camera.QuirkyCamera;
import org.photonvision.vision.frame.provider.FileFrameProvider;
import org.photonvision.vision.pipeline.result.CVPipelineResult;
@@ -46,6 +47,7 @@ public class AprilTagTest {
pipeline.getSettings().cornerDetectionAccuracyPercentage = 4;
pipeline.getSettings().cornerDetectionUseConvexHulls = true;
pipeline.getSettings().targetModel = TargetModel.k200mmAprilTag;
pipeline.getSettings().tagFamily = AprilTagFamily.kTag36h11;
var frameProvider =
new FileFrameProvider(