UI patches (#905)

- Show 0 clients when NT server props are undefined
- Add Prettier 

---------

Co-authored-by: Matthew Morley <matthew.morley.ca@gmail.com>
This commit is contained in:
Sriman Achanta
2023-08-31 16:56:58 -04:00
committed by GitHub
parent de394418f6
commit 08892b9e68
55 changed files with 3323 additions and 2808 deletions

View File

@@ -11,7 +11,13 @@ import { useStateStore } from "@/stores/StateStore";
// Defer reference to store access method
const currentPipelineSettings = useCameraSettingsStore().currentPipelineSettings;
const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)) ? 9 : 8;
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>
<template>
@@ -21,7 +27,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
label="Target family"
:items="['AprilTag Family 36h11', 'AprilTag Family 25h9', 'AprilTag Family 16h5']"
:select-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({tagFamily: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ tagFamily: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.decimate"
@@ -31,7 +37,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Increases FPS at the expense of range by reducing image resolution initially"
:min="1"
:max="8"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({decimate: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ decimate: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.blur"
@@ -42,7 +48,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="5"
:step="0.1"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({blur: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ blur: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.threads"
@@ -52,14 +58,14 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Number of threads spawned by the AprilTag detector"
:min="1"
:max="8"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({threads: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ threads: value }, false)"
/>
<cv-switch
v-model="currentPipelineSettings.refineEdges"
class="pt-2"
label="Refine Edges"
tooltip="Further refines the AprilTag corner position initial estimate, suggested left on"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({refineEdges: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ refineEdges: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.decisionMargin"
@@ -69,7 +75,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Tags with a 'margin' (decoding quality score) less than this wil be rejected. Increase this to reduce the number of false positive detections"
:min="0"
:max="250"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({decisionMargin: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ decisionMargin: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.numIterations"
@@ -79,7 +85,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Number of iterations the pose estimation algorithm will run, 50-100 is a good starting point"
:min="0"
:max="500"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({numIterations: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ numIterations: value }, false)"
/>
</div>
</template>

View File

@@ -9,7 +9,13 @@ import { useStateStore } from "@/stores/StateStore";
// Defer reference to store access method
const currentPipelineSettings = useCameraSettingsStore().currentPipelineSettings;
const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)) ? 9 : 8;
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>
<template>
@@ -22,7 +28,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Increases FPS at the expense of range by reducing image resolution initially"
:min="1"
:max="8"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({decimate: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ decimate: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.numIterations"
@@ -33,7 +39,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="30"
:max="1000"
:step="5"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({numIterations: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ numIterations: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.cornerAccuracy"
@@ -44,7 +50,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0.01"
:max="100"
:step="0.01"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({cornerAccuracy: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ cornerAccuracy: value }, false)"
/>
</div>
</template>

View File

@@ -14,34 +14,46 @@ const currentPipelineSettings = useCameraSettingsStore().currentPipelineSettings
// TODO fix cv-range-slider so that store access doesn't need to be deferred
const contourArea = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourArea) as [number, number],
set: v => useCameraSettingsStore().currentPipelineSettings.contourArea = v
set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourArea = v)
});
const contourRatio = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourRatio) as [number, number],
set: v => useCameraSettingsStore().currentPipelineSettings.contourRatio = v
set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourRatio = v)
});
const contourFullness = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.contourFullness) as [number, number],
set: v => useCameraSettingsStore().currentPipelineSettings.contourFullness = v
set: (v) => (useCameraSettingsStore().currentPipelineSettings.contourFullness = v)
});
const contourPerimeter = computed<[number, number]>({
get: () => currentPipelineSettings.pipelineType === PipelineType.ColoredShape ? Object.values(currentPipelineSettings.contourPerimeter) as [number, number] : [0, 0] as [number, number],
set: v => {
if(currentPipelineSettings.pipelineType === PipelineType.ColoredShape) {
get: () =>
currentPipelineSettings.pipelineType === PipelineType.ColoredShape
? (Object.values(currentPipelineSettings.contourPerimeter) as [number, number])
: ([0, 0] as [number, number]),
set: (v) => {
if (currentPipelineSettings.pipelineType === PipelineType.ColoredShape) {
currentPipelineSettings.contourPerimeter = v;
}
}
});
const contourRadius = computed<[number, number]>({
get: () => currentPipelineSettings.pipelineType === PipelineType.ColoredShape ? Object.values(currentPipelineSettings.contourRadius) as [number, number] : [0, 0] as [number, number],
set: v => {
if(currentPipelineSettings.pipelineType === PipelineType.ColoredShape) {
get: () =>
currentPipelineSettings.pipelineType === PipelineType.ColoredShape
? (Object.values(currentPipelineSettings.contourRadius) as [number, number])
: ([0, 0] as [number, number]),
set: (v) => {
if (currentPipelineSettings.pipelineType === PipelineType.ColoredShape) {
currentPipelineSettings.contourRadius = v;
}
}
});
const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)) ? 9 : 8;
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>
<template>
@@ -53,7 +65,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="100"
:slider-cols="interactiveCols"
:step="0.01"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourArea: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourArea: value }, false)"
/>
<cv-range-slider
v-if="useCameraSettingsStore().currentPipelineType !== PipelineType.ColoredShape"
@@ -64,7 +76,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="100"
:slider-cols="interactiveCols"
:step="0.1"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourRatio: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourRatio: value }, false)"
/>
<cv-select
v-model="useCameraSettingsStore().currentPipelineSettings.contourTargetOrientation"
@@ -72,7 +84,9 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Used to determine how to calculate target landmarks, as well as aspect ratio"
:items="['Portrait', 'Landscape']"
:select-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourTargetOrientation: value}, false)"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourTargetOrientation: value }, false)
"
/>
<cv-range-slider
v-if="useCameraSettingsStore().currentPipelineType === PipelineType.ColoredShape"
@@ -82,7 +96,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="100"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourFullness: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourFullness: value }, false)"
/>
<cv-range-slider
v-if="currentPipelineSettings.pipelineType === PipelineType.ColoredShape"
@@ -92,7 +106,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
min="0"
max="4000"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourPerimeter: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourPerimeter: value }, false)"
/>
<cv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.contourSpecklePercentage"
@@ -101,7 +115,9 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="100"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourSpecklePercentage: value}, false)"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourSpecklePercentage: value }, false)
"
/>
<template v-if="currentPipelineSettings.pipelineType === PipelineType.Reflective">
<cv-slider
@@ -112,7 +128,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="4"
:step="0.1"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourFilterRangeX: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourFilterRangeX: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.contourFilterRangeY"
@@ -122,24 +138,24 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="4"
:step="0.1"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourFilterRangeY: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourFilterRangeY: value }, false)"
/>
<cv-select
v-model="useCameraSettingsStore().currentPipelineSettings.contourGroupingMode"
label="Target Grouping"
tooltip="Whether or not every two targets are paired with each other (good for e.g. 2019 targets)"
:select-cols="interactiveCols"
:items="['Single','Dual','Two or More']"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourGroupingMode: value}, false)"
:items="['Single', 'Dual', 'Two or More']"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourGroupingMode: value }, false)"
/>
<cv-select
v-model="useCameraSettingsStore().currentPipelineSettings.contourIntersection"
label="Target Intersection"
tooltip="If target grouping is in dual mode it will use this dropdown to decide how targets are grouped with adjacent targets"
:select-cols="interactiveCols"
:items="['None','Up','Down','Left','Right']"
:items="['None', 'Up', 'Down', 'Left', 'Right']"
:disabled="useCameraSettingsStore().currentPipelineSettings.contourGroupingMode === 0"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourIntersection: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourIntersection: value }, false)"
/>
</template>
<template v-else-if="currentPipelineSettings.pipelineType === PipelineType.ColoredShape">
@@ -150,7 +166,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="The shape of targets to look for"
:select-cols="interactiveCols"
:items="['Circle', 'Polygon', 'Triangle', 'Quadrilateral']"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourShape: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourShape: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.accuracyPercentage"
@@ -160,7 +176,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="100"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({accuracyPercentage: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ accuracyPercentage: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.circleDetectThreshold"
@@ -170,7 +186,9 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="1"
:max="100"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({circleDetectThreshold: value}, false)"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ circleDetectThreshold: value }, false)
"
/>
<cv-range-slider
v-model="contourRadius"
@@ -179,7 +197,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="100"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourRadius: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourRadius: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.maxCannyThresh"
@@ -188,7 +206,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="1"
:max="100"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({maxCannyThresh: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ maxCannyThresh: value }, false)"
/>
<cv-slider
v-model="currentPipelineSettings.circleAccuracy"
@@ -197,7 +215,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="1"
:max="100"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({circleAccuracy: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ circleAccuracy: value }, false)"
/>
<v-divider class="mt-3" />
</template>
@@ -206,8 +224,8 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
label="Target Sort"
tooltip="Chooses the sorting mode used to determine the 'best' targets to provide to user code"
:select-cols="interactiveCols"
:items="['Largest','Smallest','Highest','Lowest','Rightmost','Leftmost','Centermost']"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourSortMode: value}, false)"
:items="['Largest', 'Smallest', 'Highest', 'Lowest', 'Rightmost', 'Leftmost', 'Centermost']"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourSortMode: value }, false)"
/>
</div>
</template>

View File

@@ -8,26 +8,38 @@ import { useSettingsStore } from "@/stores/settings/GeneralSettingsStore";
import { useStateStore } from "@/stores/StateStore";
// Due to something with libcamera or something else IDK much about, the 90° rotations need to be disabled if the libcamera drivers are being used.
const cameraRotations = computed(() => ["Normal", "90° CW", "180°", "90° CCW"].map((v, i) => ({ name: v, value: i, disabled: useSettingsStore().gpuAccelerationEnabled ? [1, 3].includes(i) : false })));
const cameraRotations = computed(() =>
["Normal", "90° CW", "180°", "90° CCW"].map((v, i) => ({
name: v,
value: i,
disabled: useSettingsStore().gpuAccelerationEnabled ? [1, 3].includes(i) : false
}))
);
const streamDivisors = [1, 2, 4, 6];
const getFilteredStreamDivisors = (): number[] => {
const currentResolutionWidth = useCameraSettingsStore().currentVideoFormat.resolution.width;
return streamDivisors.filter(x =>
useCameraSettingsStore().isDriverMode
|| !useSettingsStore().gpuAccelerationEnabled
|| currentResolutionWidth / x < 400);
return streamDivisors.filter(
(x) =>
useCameraSettingsStore().isDriverMode ||
!useSettingsStore().gpuAccelerationEnabled ||
currentResolutionWidth / x < 400
);
};
const getNumberOfSkippedDivisors = () => streamDivisors.length - getFilteredStreamDivisors().length;
const cameraResolutions = computed(() => useCameraSettingsStore().currentCameraSettings.validVideoFormats.map(f => `${f.resolution.width} X ${f.resolution.height} at ${f.fps} FPS, ${f.pixelFormat}`));
const cameraResolutions = computed(() =>
useCameraSettingsStore().currentCameraSettings.validVideoFormats.map(
(f) => `${f.resolution.width} X ${f.resolution.height} at ${f.fps} FPS, ${f.pixelFormat}`
)
);
const handleResolutionChange = (value: number) => {
useCameraSettingsStore().changeCurrentPipelineSetting({ cameraVideoModeIndex: value }, false);
useCameraSettingsStore().changeCurrentPipelineSetting({ streamingFrameDivisor: getNumberOfSkippedDivisors() }, false);
useCameraSettingsStore().currentPipelineSettings.streamingFrameDivisor = 0;
if(!useCameraSettingsStore().isCurrentVideoFormatCalibrated) {
if (!useCameraSettingsStore().isCurrentVideoFormatCalibrated) {
useCameraSettingsStore().changeCurrentPipelineSetting({ solvePNPEnabled: false }, true);
}
};
@@ -35,14 +47,24 @@ const handleResolutionChange = (value: number) => {
const streamResolutions = computed(() => {
const streamDivisors = getFilteredStreamDivisors();
const currentResolution = useCameraSettingsStore().currentVideoFormat.resolution;
return streamDivisors
.map(x => `${Math.floor(currentResolution.width / x)} X ${Math.floor(currentResolution.height / x)}`);
return streamDivisors.map(
(x) => `${Math.floor(currentResolution.width / x)} X ${Math.floor(currentResolution.height / x)}`
);
});
const handleStreamResolutionChange = (value: number) => {
useCameraSettingsStore().changeCurrentPipelineSetting({ streamingFrameDivisor: value + getNumberOfSkippedDivisors() }, false);
useCameraSettingsStore().changeCurrentPipelineSetting(
{ streamingFrameDivisor: value + getNumberOfSkippedDivisors() },
false
);
};
const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)) ? 9 : 8;
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>
<template>
@@ -56,7 +78,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="100"
:slider-cols="interactiveCols"
:step="0.1"
@input="args => useCameraSettingsStore().changeCurrentPipelineSetting({cameraExposure: args}, false)"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraExposure: args }, false)"
/>
<cv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.cameraBrightness"
@@ -64,7 +86,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="100"
:slider-cols="interactiveCols"
@input="args => useCameraSettingsStore().changeCurrentPipelineSetting({cameraBrightness: args}, false)"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraBrightness: args }, false)"
/>
<cv-switch
v-model="useCameraSettingsStore().currentPipelineSettings.cameraAutoExposure"
@@ -72,7 +94,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
label="Auto Exposure"
:switch-cols="interactiveCols"
tooltip="Enables or Disables camera automatic adjustment for current lighting conditions"
@input="args => useCameraSettingsStore().changeCurrentPipelineSetting({cameraAutoExposure: args}, false)"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraAutoExposure: args }, false)"
/>
<cv-slider
v-if="useCameraSettingsStore().currentPipelineSettings.cameraGain >= 0"
@@ -82,7 +104,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="100"
:slider-cols="interactiveCols"
@input="args => useCameraSettingsStore().changeCurrentPipelineSetting({cameraGain: args}, false)"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraGain: args }, false)"
/>
<cv-slider
v-if="useCameraSettingsStore().currentPipelineSettings.cameraRedGain !== -1"
@@ -92,7 +114,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="100"
:slider-cols="interactiveCols"
tooltip="Controls red automatic white balance gain, which affects how the camera captures colors in different conditions"
@input="args => useCameraSettingsStore().changeCurrentPipelineSetting({cameraRedGain: args}, false)"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraRedGain: args }, false)"
/>
<cv-slider
v-if="useCameraSettingsStore().currentPipelineSettings.cameraBlueGain !== -1"
@@ -102,7 +124,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="100"
:slider-cols="interactiveCols"
tooltip="Controls blue automatic white balance gain, which affects how the camera captures colors in different conditions"
@input="args => useCameraSettingsStore().changeCurrentPipelineSetting({cameraBlueGain: args}, false)"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ cameraBlueGain: args }, false)"
/>
<cv-select
v-model="useCameraSettingsStore().currentPipelineSettings.inputImageRotationMode"
@@ -110,7 +132,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Rotates the camera stream"
:items="cameraRotations"
:select-cols="interactiveCols"
@input="args => useCameraSettingsStore().changeCurrentPipelineSetting({inputImageRotationMode: args}, false)"
@input="(args) => useCameraSettingsStore().changeCurrentPipelineSetting({ inputImageRotationMode: args }, false)"
/>
<cv-select
v-model="useCameraSettingsStore().currentPipelineSettings.cameraVideoModeIndex"
@@ -118,7 +140,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Resolution and FPS the camera should directly capture at"
:items="cameraResolutions"
:select-cols="interactiveCols"
@input="args => handleResolutionChange(args)"
@input="(args) => handleResolutionChange(args)"
/>
<cv-select
v-model="useCameraSettingsStore().currentPipelineSettings.streamingFrameDivisor"
@@ -126,7 +148,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Resolution to which camera frames are downscaled for streaming to the dashboard"
:items="streamResolutions"
:select-cols="interactiveCols"
@input="args => handleStreamResolutionChange(args)"
@input="(args) => handleStreamResolutionChange(args)"
/>
</div>
</template>

View File

@@ -16,9 +16,7 @@ const trackedTargets = computed<PhotonTarget[]>(() => useStateStore().pipelineRe
</v-row>
<v-row style="width: 100%">
<v-col style="display: flex; align-items: center; justify-content: center">
<photon3d-visualizer
:targets="trackedTargets"
/>
<photon3d-visualizer :targets="trackedTargets" />
</v-col>
</v-row>
</div>

View File

@@ -7,11 +7,15 @@ import { computed, getCurrentInstance } from "vue";
import { RobotOffsetType } from "@/types/SettingTypes";
import { useStateStore } from "@/stores/StateStore";
const isTagPipeline = computed(() => useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag || useCameraSettingsStore().currentPipelineType === PipelineType.Aruco);
const isTagPipeline = computed(
() =>
useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag ||
useCameraSettingsStore().currentPipelineType === PipelineType.Aruco
);
interface MetricItem {
header: string,
value?: string
header: string;
value?: string;
}
const offsetPoints = computed<MetricItem[]>(() => {
@@ -24,10 +28,11 @@ const offsetPoints = computed<MetricItem[]>(() => {
const firstPointArea = useCameraSettingsStore().currentPipelineSettings.offsetDualPointAArea;
const secondPoint = Object.values(useCameraSettingsStore().currentPipelineSettings.offsetDualPointB);
const secondPointArea = useCameraSettingsStore().currentPipelineSettings.offsetDualPointBArea;
return [{ header: "First Offset Point", value: `(${firstPoint[0].toFixed(2)}°, ${firstPoint[1].toFixed(2)}°)` },
{ header: "First Offset Point Area", value: `${firstPointArea.toFixed(2)}%` },
{ header: "Second Offset Point", value: `(${secondPoint[0].toFixed(2)}°, ${secondPoint[1].toFixed(2)}°)` },
{ header: "Second Offset Point Area", value: `${secondPointArea.toFixed(2)}%` }
return [
{ header: "First Offset Point", value: `(${firstPoint[0].toFixed(2)}°, ${firstPoint[1].toFixed(2)}°)` },
{ header: "First Offset Point Area", value: `${firstPointArea.toFixed(2)}%` },
{ header: "Second Offset Point", value: `(${secondPoint[0].toFixed(2)}°, ${secondPoint[1].toFixed(2)}°)` },
{ header: "Second Offset Point Area", value: `${secondPointArea.toFixed(2)}%` }
];
default:
case RobotOffsetPointMode.None:
@@ -35,7 +40,13 @@ const offsetPoints = computed<MetricItem[]>(() => {
}
});
const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)) ? 9 : 8;
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>
<template>
@@ -44,9 +55,11 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
v-model="useCameraSettingsStore().currentPipelineSettings.contourTargetOffsetPointEdge"
label="Target Offset Point"
tooltip="Changes where the 'center' of the target is (used for calculating e.g. pitch and yaw)"
:items="['Center','Top','Bottom','Left','Right']"
:items="['Center', 'Top', 'Bottom', 'Left', 'Right']"
:select-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourTargetOffsetPointEdge: value}, false)"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourTargetOffsetPointEdge: value }, false)
"
/>
<cv-select
v-if="!isTagPipeline"
@@ -55,7 +68,9 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="Used to determine how to calculate target landmarks (e.g. the top, left, or bottom of the target)"
:items="['Portrait', 'Landscape']"
:select-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({contourTargetOrientation: value}, false)"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ contourTargetOrientation: value }, false)
"
/>
<cv-switch
v-model="useCameraSettingsStore().currentPipelineSettings.outputShowMultipleTargets"
@@ -63,7 +78,9 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
tooltip="If enabled, up to five targets will be displayed and sent to user code, instead of just one"
:disabled="isTagPipeline"
:switch-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({outputShowMultipleTargets: value}, false)"
@input="
(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ outputShowMultipleTargets: value }, false)
"
/>
<v-divider />
<table
@@ -71,20 +88,12 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
class="metrics-table mt-3 mb-3"
>
<tr>
<th
v-for="(item, itemIndex) in offsetPoints"
:key="itemIndex"
class="metric-item metric-item-title"
>
<th v-for="(item, itemIndex) in offsetPoints" :key="itemIndex" class="metric-item metric-item-title">
{{ item.header }}
</th>
</tr>
<tr>
<td
v-for="(item, itemIndex) in offsetPoints"
:key="itemIndex"
class="metric-item"
>
<td v-for="(item, itemIndex) in offsetPoints" :key="itemIndex" class="metric-item">
{{ item.value }}
</td>
</tr>
@@ -93,21 +102,23 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
v-model="useCameraSettingsStore().currentPipelineSettings.offsetRobotOffsetMode"
label="Robot Offset Mode"
tooltip="Used to add an arbitrary offset to the location of the targeting crosshair"
:items="['None','Single Point','Dual Point']"
:items="['None', 'Single Point', 'Dual Point']"
:select-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({offsetRobotOffsetMode: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ offsetRobotOffsetMode: value }, false)"
/>
<v-row
v-if="useCameraSettingsStore().currentPipelineSettings.offsetRobotOffsetMode !== RobotOffsetPointMode.None"
align="center"
justify="start"
>
<v-row v-if="useCameraSettingsStore().currentPipelineSettings.offsetRobotOffsetMode === RobotOffsetPointMode.Single">
<v-row
v-if="useCameraSettingsStore().currentPipelineSettings.offsetRobotOffsetMode === RobotOffsetPointMode.Single"
>
<v-col>
<v-btn
small
color="accent"
style="width: 100%;"
style="width: 100%"
class="black--text"
@click="useCameraSettingsStore().takeRobotOffsetPoint(RobotOffsetType.Single)"
>
@@ -115,12 +126,14 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
</v-btn>
</v-col>
</v-row>
<v-row v-else-if="useCameraSettingsStore().currentPipelineSettings.offsetRobotOffsetMode === RobotOffsetPointMode.Dual">
<v-row
v-else-if="useCameraSettingsStore().currentPipelineSettings.offsetRobotOffsetMode === RobotOffsetPointMode.Dual"
>
<v-col>
<v-btn
small
color="accent"
style="width: 100%;"
style="width: 100%"
class="black--text"
@click="useCameraSettingsStore().takeRobotOffsetPoint(RobotOffsetType.DualFirst)"
>
@@ -131,7 +144,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
<v-btn
small
color="accent"
style="width: 100%;"
style="width: 100%"
class="black--text"
@click="useCameraSettingsStore().takeRobotOffsetPoint(RobotOffsetType.DualSecond)"
>
@@ -143,7 +156,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
<v-btn
small
color="yellow darken-3"
style="width: 100%;"
style="width: 100%"
@click="useCameraSettingsStore().takeRobotOffsetPoint(RobotOffsetType.Clear)"
>
Clear All Points
@@ -154,7 +167,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
</template>
<style scoped>
.metrics-table{
.metrics-table {
border-collapse: separate;
border-spacing: 0;
border-radius: 5px;

View File

@@ -6,7 +6,13 @@ import CvSlider from "@/components/common/cv-slider.vue";
import { computed, getCurrentInstance } from "vue";
import { useStateStore } from "@/stores/StateStore";
const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)) ? 9 : 8;
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>
<template>
@@ -15,18 +21,18 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
v-model="useCameraSettingsStore().currentPipelineSettings.targetModel"
label="Target Model"
:items="[
{name: '2020 High Goal Outer', value: TargetModel.InfiniteRechargeHighGoalOuter},
{name: '2020 High Goal Inner', value: TargetModel.InfiniteRechargeHighGoalInner},
{name: '2019 Dual Target', value: TargetModel.DeepSpaceDualTarget},
{name: '2020 Power Cell (7in)', value: TargetModel.CircularPowerCell7in},
{name: '2022 Cargo Ball (9.5in)', value: TargetModel.RapidReactCircularCargoBall},
{name: '2016 High Goal', value: TargetModel.StrongholdHighGoal},
{name: '200mm AprilTag', value: TargetModel.Apriltag_200mm},
{name: '6in (16h5) Aruco', value: TargetModel.Aruco6in_16h5},
{name: '6in (16h5) AprilTag', value: TargetModel.Apriltag6in_16h5}
{ name: '2020 High Goal Outer', value: TargetModel.InfiniteRechargeHighGoalOuter },
{ name: '2020 High Goal Inner', value: TargetModel.InfiniteRechargeHighGoalInner },
{ name: '2019 Dual Target', value: TargetModel.DeepSpaceDualTarget },
{ name: '2020 Power Cell (7in)', value: TargetModel.CircularPowerCell7in },
{ name: '2022 Cargo Ball (9.5in)', value: TargetModel.RapidReactCircularCargoBall },
{ name: '2016 High Goal', value: TargetModel.StrongholdHighGoal },
{ name: '200mm AprilTag', value: TargetModel.Apriltag_200mm },
{ name: '6in (16h5) Aruco', value: TargetModel.Aruco6in_16h5 },
{ name: '6in (16h5) AprilTag', value: TargetModel.Apriltag6in_16h5 }
]"
:select-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({targetModel: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ targetModel: value }, false)"
/>
<cv-slider
v-model="useCameraSettingsStore().currentPipelineSettings.cornerDetectionAccuracyPercentage"
@@ -35,7 +41,10 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
label="Contour simplification Percentage"
:min="0"
:max="100"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({cornerDetectionAccuracyPercentage: value}, false)"
@input="
(value) =>
useCameraSettingsStore().changeCurrentPipelineSetting({ cornerDetectionAccuracyPercentage: value }, false)
"
/>
</div>
</template>

View File

@@ -6,69 +6,52 @@ import { useStateStore } from "@/stores/StateStore";
<template>
<div>
<v-row
align="start"
class="pb-4"
style="height: 300px;"
>
<v-row align="start" class="pb-4" style="height: 300px">
<!-- Simple table height must be set here and in the CSS for the fixed-header to work -->
<v-simple-table
fixed-header
height="100%"
dense
dark
>
<v-simple-table fixed-header height="100%" dense dark>
<template #default>
<thead style="font-size: 1.25rem;">
<thead style="font-size: 1.25rem">
<tr>
<th class="text-center">
Target Count
</th>
<th class="text-center">Target Count</th>
<th
v-if="useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag || useCameraSettingsStore().currentPipelineType === PipelineType.Aruco"
v-if="
useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag ||
useCameraSettingsStore().currentPipelineType === PipelineType.Aruco
"
class="text-center"
>
Fiducial ID
</th>
<template v-if="!useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled">
<th class="text-center">
Pitch &theta;&deg;
</th>
<th class="text-center">
Yaw &theta;&deg;
</th>
<th class="text-center">
Skew &theta;&deg;
</th>
<th class="text-center">
Area %
</th>
<th class="text-center">Pitch &theta;&deg;</th>
<th class="text-center">Yaw &theta;&deg;</th>
<th class="text-center">Skew &theta;&deg;</th>
<th class="text-center">Area %</th>
</template>
<template v-else>
<th class="text-center">
X meters
</th>
<th class="text-center">
Y meters
</th>
<th class="text-center">
Z Angle &theta;&deg;
</th>
<th class="text-center">X meters</th>
<th class="text-center">Y meters</th>
<th class="text-center">Z Angle &theta;&deg;</th>
</template>
<template v-if="useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag && useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled">
<th class="text-center">
Ambiguity %
</th>
<template
v-if="
useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag &&
useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled
"
>
<th class="text-center">Ambiguity %</th>
</template>
</tr>
</thead>
<tbody>
<tr
v-for="(target, index) in useStateStore().pipelineResults?.targets"
:key="index"
>
<tr v-for="(target, index) in useStateStore().pipelineResults?.targets" :key="index">
<td>{{ index }}</td>
<td v-if="useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag || useCameraSettingsStore().currentPipelineType === PipelineType.Aruco">
<td
v-if="
useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag ||
useCameraSettingsStore().currentPipelineType === PipelineType.Aruco
"
>
{{ target.fiducialId }}
</td>
<template v-if="!useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled">
@@ -80,9 +63,14 @@ import { useStateStore } from "@/stores/StateStore";
<template v-else-if="useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled">
<td>{{ target.pose?.x.toFixed(2) }}&nbsp;m</td>
<td>{{ target.pose?.y.toFixed(2) }}&nbsp;m</td>
<td>{{ (target.pose?.angle_z * 180.0 / Math.PI).toFixed(2) }}&deg;</td>
<td>{{ ((target.pose?.angle_z * 180.0) / Math.PI).toFixed(2) }}&deg;</td>
</template>
<template v-if="useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag && useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled">
<template
v-if="
useCameraSettingsStore().currentPipelineType === PipelineType.AprilTag &&
useCameraSettingsStore().currentPipelineSettings.solvePNPEnabled
"
>
<td>{{ target.ambiguity?.toFixed(2) }}%</td>
</template>
</tr>
@@ -100,7 +88,8 @@ import { useStateStore } from "@/stores/StateStore";
text-align: center;
background-color: #006492 !important;
th, td {
th,
td {
background-color: #006492 !important;
font-size: 1rem !important;
}

View File

@@ -10,7 +10,7 @@ const averageHue = computed<number>(() => {
const isHueInverted = useCameraSettingsStore().currentPipelineSettings.hueInverted;
let val = Object.values(useCameraSettingsStore().currentPipelineSettings.hsvHue).reduce((a, b) => a + b, 0);
if(isHueInverted) val += 180;
if (isHueInverted) val += 180;
if (val > 360) val -= 360;
return val;
@@ -19,23 +19,23 @@ const averageHue = computed<number>(() => {
// TODO fix cv-range-slider so that store access doesn't need to be deferred
const hsvHue = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.hsvHue) as [number, number],
set: v => useCameraSettingsStore().currentPipelineSettings.hsvHue = v
set: (v) => (useCameraSettingsStore().currentPipelineSettings.hsvHue = v)
});
const hsvSaturation = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.hsvSaturation) as [number, number],
set: v => useCameraSettingsStore().currentPipelineSettings.hsvSaturation = v
set: (v) => (useCameraSettingsStore().currentPipelineSettings.hsvSaturation = v)
});
const hsvValue = computed<[number, number]>({
get: () => Object.values(useCameraSettingsStore().currentPipelineSettings.hsvValue) as [number, number],
set: v => useCameraSettingsStore().currentPipelineSettings.hsvValue = v
set: (v) => (useCameraSettingsStore().currentPipelineSettings.hsvValue = v)
});
let selectedEventMode: 0 | 1 | 2 | 3 = 0;
const handleStreamClick = (event: MouseEvent) => {
if(!useStateStore().colorPickingMode || selectedEventMode === 0) return;
if (!useStateStore().colorPickingMode || selectedEventMode === 0) return;
const cameraStream = document.getElementById("input-camera-stream");
if(cameraStream === null) return;
if (cameraStream === null) return;
const canvas = document.createElement("canvas");
canvas.width = cameraStream.clientWidth;
@@ -43,18 +43,21 @@ const handleStreamClick = (event: MouseEvent) => {
// Get the (x, y) position of the click with (0, 0) in the top left corner
const rect = cameraStream.getBoundingClientRect();
const x = Math.round((event.clientX - rect.left) / rect.width * cameraStream.clientWidth);
const y = Math.round((event.clientY - rect.top) / rect.height * cameraStream.clientHeight);
const x = Math.round(((event.clientX - rect.left) / rect.width) * cameraStream.clientWidth);
const y = Math.round(((event.clientY - rect.top) / rect.height) * cameraStream.clientHeight);
const context = canvas.getContext("2d");
if(context === null) return;
if (context === null) return;
context.drawImage(cameraStream as CanvasImageSource, 0, 0, cameraStream.clientWidth, cameraStream.clientHeight);
const colorPicker = new ColorPicker(context.getImageData(x, y, 1, 1).data);
// Calculate HSV values based on the mode
let selectedHSVData: [HSV, HSV] = [[0, 0, 0], [0, 0, 0]];
if(selectedEventMode === 1) {
let selectedHSVData: [HSV, HSV] = [
[0, 0, 0],
[0, 0, 0]
];
if (selectedEventMode === 1) {
selectedHSVData = colorPicker.selectedColorRange();
} else {
const currentHue = Object.values(useCameraSettingsStore().currentPipelineSettings.hsvHue);
@@ -66,19 +69,22 @@ const handleStreamClick = (event: MouseEvent) => {
[currentHue[1], currentSaturation[1], currentValue[1]]
];
if(selectedEventMode === 2) {
if (selectedEventMode === 2) {
selectedHSVData = colorPicker.expandColorRange(currentData);
} else if(selectedEventMode === 3) {
} else if (selectedEventMode === 3) {
selectedHSVData = colorPicker.shrinkColorRange(currentData);
}
}
// Update the store and backend with the new HSV values
useCameraSettingsStore().changeCurrentPipelineSetting({
hsvHue: [selectedHSVData[0][0], selectedHSVData[1][0]],
hsvSaturation: [selectedHSVData[0][1], selectedHSVData[1][1]],
hsvValue: [selectedHSVData[0][2], selectedHSVData[1][2]]
}, true);
useCameraSettingsStore().changeCurrentPipelineSetting(
{
hsvHue: [selectedHSVData[0][0], selectedHSVData[1][0]],
hsvSaturation: [selectedHSVData[0][1], selectedHSVData[1][1]],
hsvValue: [selectedHSVData[0][2], selectedHSVData[1][2]]
},
true
);
disableColorPicking();
};
@@ -90,36 +96,45 @@ const enableColorPicking = (mode: 1 | 2 | 3) => {
useStateStore().colorPickingMode = true;
inputShowing = useCameraSettingsStore().currentPipelineSettings.inputShouldShow;
outputShowing = useCameraSettingsStore().currentPipelineSettings.outputShouldShow;
useCameraSettingsStore().changeCurrentPipelineSetting({ outputShouldDraw: false, inputShouldShow: true, outputShouldShow: false }, true);
useCameraSettingsStore().changeCurrentPipelineSetting(
{ outputShouldDraw: false, inputShouldShow: true, outputShouldShow: false },
true
);
selectedEventMode = mode;
};
const disableColorPicking = () => {
useStateStore().colorPickingMode = false;
useCameraSettingsStore().changeCurrentPipelineSetting({ outputShouldDraw: true, inputShouldShow: inputShowing, outputShouldShow: outputShowing }, true);
useCameraSettingsStore().changeCurrentPipelineSetting(
{ outputShouldDraw: true, inputShouldShow: inputShowing, outputShouldShow: outputShowing },
true
);
selectedEventMode = 0;
};
onMounted(() => {
const cameraStream = document.getElementById("input-camera-stream");
if(cameraStream === null) return;
if (cameraStream === null) return;
cameraStream.addEventListener("click", handleStreamClick);
});
onBeforeUnmount(() => {
const cameraStream = document.getElementById("input-camera-stream");
if(cameraStream === null) return;
if (cameraStream === null) return;
cameraStream.removeEventListener("click", handleStreamClick);
});
const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) && (!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)) ? 9 : 8;
const interactiveCols = computed(
() =>
(getCurrentInstance()?.proxy.$vuetify.breakpoint.mdAndDown || false) &&
(!useStateStore().sidebarFolded || useCameraSettingsStore().isDriverMode)
)
? 9
: 8;
</script>
<template>
<div
class="threshold-modifiers"
:style="{'--averageHue': averageHue}"
>
<div class="threshold-modifiers" :style="{ '--averageHue': averageHue }">
<cv-range-slider
id="hue-slider"
v-model="hsvHue"
@@ -130,7 +145,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:max="180"
:slider-cols="interactiveCols"
:inverted="useCameraSettingsStore().currentPipelineSettings.hueInverted"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({hsvHue: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ hsvHue: value }, false)"
/>
<cv-range-slider
id="sat-slider"
@@ -141,7 +156,7 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="255"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({hsvSaturation: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ hsvSaturation: value }, false)"
/>
<cv-range-slider
id="value-slider"
@@ -152,26 +167,19 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
:min="0"
:max="255"
:slider-cols="interactiveCols"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({hsvValue: value}, false)"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ hsvValue: value }, false)"
/>
<cv-switch
v-model="useCameraSettingsStore().currentPipelineSettings.hueInverted"
label="Invert Hue"
:switch-cols="interactiveCols"
tooltip="Selects the hue range outside of the hue slider bounds instead of inside"
@input="value => useCameraSettingsStore().changeCurrentPipelineSetting({hueInverted: value}, false)"
/>
<v-divider
class="mt-3"
@input="(value) => useCameraSettingsStore().changeCurrentPipelineSetting({ hueInverted: value }, false)"
/>
<v-divider class="mt-3" />
<div>
<div class="pt-3 white--text">
Color Picker
</div>
<v-row
justify="center"
class="mt-3 mb-3"
>
<div class="pt-3 white--text">Color Picker</div>
<v-row justify="center" class="mt-3 mb-3">
<template v-if="!useStateStore().colorPickingMode">
<v-btn
color="accent"
@@ -179,42 +187,25 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
small
@click="enableColorPicking(useCameraSettingsStore().currentPipelineSettings.hueInverted ? 2 : 3)"
>
<v-icon left>
mdi-minus
</v-icon>
<v-icon left> mdi-minus </v-icon>
Shrink Range
</v-btn>
<v-btn
color="accent"
class="ma-2 black--text"
small
@click="enableColorPicking(1)"
>
<v-icon left>
mdi-plus-minus
</v-icon>
<v-btn color="accent" class="ma-2 black--text" small @click="enableColorPicking(1)">
<v-icon left> mdi-plus-minus </v-icon>
{{ useCameraSettingsStore().currentPipelineSettings.hueInverted ? "Exclude" : "Set to" }} Average
</v-btn>
<v-btn
color="accent"
class="ma-2 black--text"
small
@click="enableColorPicking(useCameraSettingsStore().currentPipelineSettings.hueInverted ? 3: 2)"
@click="enableColorPicking(useCameraSettingsStore().currentPipelineSettings.hueInverted ? 3 : 2)"
>
<v-icon left>
mdi-plus
</v-icon>
<v-icon left> mdi-plus </v-icon>
Expand Range
</v-btn>
</template>
<template v-else>
<v-btn
color="accent"
class="ma-2 black--text"
style="width: 30%;"
small
@click="disableColorPicking"
>
<v-btn color="accent" class="ma-2 black--text" style="width: 30%" small @click="disableColorPicking">
Cancel
</v-btn>
</template>
@@ -228,18 +219,21 @@ const interactiveCols = computed(() => (getCurrentInstance()?.proxy.$vuetify.bre
--averageHue: 0;
}
#hue-slider >>> .v-slider {
background: linear-gradient( to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100% );
background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
border-radius: 10px;
/* prettier-ignore */
box-shadow: 0 0 5px #333, inset 0 0 3px #333;
}
#sat-slider >>> .v-slider {
background: linear-gradient( to right, #fff 0%, hsl(var(--averageHue), 100%, 50%) 100% );
background: linear-gradient(to right, #fff 0%, hsl(var(--averageHue), 100%, 50%) 100%);
border-radius: 10px;
/* prettier-ignore */
box-shadow: 0 0 5px #333, inset 0 0 3px #333;
}
#value-slider >>> .v-slider {
background: linear-gradient( to right, #000 0%, hsl(var(--averageHue), 100%, 50%) 100% );
background: linear-gradient(to right, #000 0%, hsl(var(--averageHue), 100%, 50%) 100%);
border-radius: 10px;
/* prettier-ignore */
box-shadow: 0 0 5px #333, inset 0 0 3px #333;
}
>>> .v-slider__thumb {