Separate AWB gain slider (#410)

Makes gain adjust digital gain, adds sliders for red/blue on picam

Co-authored-by: Chris Gerth <chrisgerth010592@gmail.com>
This commit is contained in:
Declan
2022-02-28 00:45:29 -05:00
committed by GitHub
parent 50fdfd8bce
commit 5655ca6890
9 changed files with 115 additions and 25 deletions

View File

@@ -55,7 +55,8 @@ export default new Vuex.Store({
// Settings that apply to all pipeline types
cameraExposure: 1,
cameraBrightness: 2,
cameraGain: 3,
cameraRedGain: 3,
cameraBlueGain: 4,
inputImageRotationMode: 0,
cameraVideoModeIndex: 0,
streamingFrameDivisor: 0,

View File

@@ -196,13 +196,24 @@
@input="e => handlePipelineUpdate('cameraBrightness', e)"
/>
<CVslider
v-if="$store.getters.currentPipelineSettings.cameraGain !== -1"
v-model="$store.getters.currentPipelineSettings.cameraGain"
name="Gain"
:min="0"
:max="100"
slider-cols="8"
@input="e => handlePipelineUpdate('cameraGain', e)"
v-if="$store.getters.currentPipelineSettings.cameraRedGain !== -1"
v-model="$store.getters.currentPipelineSettings.cameraRedGain"
name="Red AWB Gain"
min="0"
max="100"
tooltip="Controls red automatic white balance gain, which affects how the camera captures colors in different conditions"
:slider-cols="8"
@input="e => handlePipelineData('cameraRedGain', e)"
/>
<CVslider
v-if="$store.getters.currentPipelineSettings.cameraBlueGain !== -1"
v-model="$store.getters.currentPipelineSettings.cameraBlueGain"
name="Blue AWB Gain"
min="0"
max="100"
tooltip="Controls blue automatic white balance gain, which affects how the camera captures colors in different conditions"
:slider-cols="8"
@input="e => handlePipelineData('cameraBlueGain', e)"
/>
</v-col>
</v-row>

View File

@@ -22,15 +22,26 @@
@rollback="e => rollback('cameraBrightness', e)"
/>
<CVslider
v-if="cameraGain !== -1"
v-model="cameraGain"
name="Gain"
v-if="cameraRedGain !== -1"
v-model="cameraRedGain"
name="Red AWB Gain"
min="0"
max="100"
tooltip="Controls automatic white balance gain, which affects how the camera captures colors in different conditions"
tooltip="Controls red automatic white balance gain, which affects how the camera captures colors in different conditions"
:slider-cols="largeBox"
@input="handlePipelineData('cameraGain')"
@rollback="e => rollback('cameraGain', e)"
@input="handlePipelineData('cameraRedGain')"
@rollback="e => rollback('cameraRedGain', e)"
/>
<CVslider
v-if="cameraBlueGain !== -1"
v-model="cameraBlueGain"
name="Blue AWB Gain"
min="0"
max="100"
tooltip="Controls blue automatic white balance gain, which affects how the camera captures colors in different conditions"
:slider-cols="largeBox"
@input="handlePipelineData('cameraBlueGain')"
@rollback="e => rollback('cameraBlueGain', e)"
/>
<CVselect
v-model="inputImageRotationMode"
@@ -105,12 +116,20 @@
this.$store.commit("mutatePipeline", {"cameraBrightness": parseInt(val)});
}
},
cameraGain: {
cameraRedGain: {
get() {
return parseInt(this.$store.getters.currentPipelineSettings.cameraGain)
return parseInt(this.$store.getters.currentPipelineSettings.cameraRedGain)
},
set(val) {
this.$store.commit("mutatePipeline", {"cameraGain": parseInt(val)});
this.$store.commit("mutatePipeline", {"cameraRedGain": parseInt(val)});
}
},
cameraBlueGain: {
get() {
return parseInt(this.$store.getters.currentPipelineSettings.cameraBlueGain)
},
set(val) {
this.$store.commit("mutatePipeline", {"cameraBlueGain": parseInt(val)});
}
},
inputImageRotationMode: {

View File

@@ -140,8 +140,12 @@ public class PicamJNI {
public static native boolean setBrightness(int brightness);
// This adjusts the analog gain (normalized to 0-100); ignores the digital gain
public static native boolean setGain(int gain);
// Adjusts the auto white balance gains, which are normalized 0-100 in the native code
public static native boolean setAwbGain(int red, int blue);
public static native boolean setRotation(int rotation);
public static native void setShouldCopyColor(boolean shouldCopyColor);

View File

@@ -18,6 +18,7 @@
package org.photonvision.vision.camera;
import edu.wpi.first.cscore.VideoMode;
import edu.wpi.first.math.Pair;
import java.util.HashMap;
import org.photonvision.common.configuration.CameraConfiguration;
import org.photonvision.common.configuration.ConfigManager;
@@ -84,9 +85,10 @@ public class ZeroCopyPicamSource extends VisionSource {
public static class PicamSettables extends VisionSourceSettables {
private FPSRatedVideoMode currentVideoMode;
private double lastExposure;
private int lastBrightness;
private int lastGain;
private double lastExposure = 50;
private int lastBrightness = 50;
private int lastGain = 50;
private Pair<Integer, Integer> lastAwbGains = new Pair(18, 18);
public PicamSettables(CameraConfiguration configuration) {
super(configuration);
@@ -137,21 +139,38 @@ public class ZeroCopyPicamSource extends VisionSource {
public void setExposure(double exposure) {
lastExposure = exposure;
var failure = PicamJNI.setExposure((int) Math.round(exposure));
if (failure) logger.warn("Couldn't set Pi camera exposure");
if (failure) logger.warn("Couldn't set Pi Camera exposure");
}
@Override
public void setBrightness(int brightness) {
lastBrightness = brightness;
var failure = PicamJNI.setBrightness(brightness);
if (failure) logger.warn("Couldn't set Pi camera brightness");
if (failure) logger.warn("Couldn't set Pi Camera brightness");
}
@Override
public void setGain(int gain) {
lastGain = gain;
var failure = PicamJNI.setGain(gain);
if (failure) logger.warn("Couldn't set Pi camera gain");
if (failure) logger.warn("Couldn't set Pi Camera gain");
}
@Override
public void setRedGain(int red) {
lastAwbGains = Pair.of(red, lastAwbGains.getSecond());
setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond());
}
@Override
public void setBlueGain(int blue) {
lastAwbGains = Pair.of(lastAwbGains.getFirst(), blue);
setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond());
}
public void setAwbGain(int red, int blue) {
var failure = PicamJNI.setAwbGain(red, blue);
if (failure) logger.warn("Couldn't set Pi Camera AWB gains");
}
@Override
@@ -165,17 +184,18 @@ public class ZeroCopyPicamSource extends VisionSource {
var failure = PicamJNI.destroyCamera();
if (failure)
throw new RuntimeException(
"Couldn't destroy a zero copy Pi camera while switching video modes");
"Couldn't destroy a zero copy Pi Camera while switching video modes");
failure = PicamJNI.createCamera(mode.width, mode.height, mode.fpsActual);
if (failure)
throw new RuntimeException(
"Couldn't create a zero copy Pi camera while switching video modes");
"Couldn't create a zero copy Pi Camera while switching video modes");
// We don't store last settings on the native side, and when you change video mode these get
// reset on MMAL's end
setExposure(lastExposure);
setBrightness(lastBrightness);
setGain(lastGain);
setAwbGain(lastAwbGains.getFirst(), lastAwbGains.getSecond());
currentVideoMode = mode;
}

View File

@@ -41,7 +41,12 @@ public class CVPipelineSettings implements Cloneable {
public String pipelineNickname = "New Pipeline";
public double cameraExposure = 50;
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;
// Currently only used by the zero-copy Pi Camera driver
public int cameraRedGain = 50;
public int cameraBlueGain = 50;
public int cameraVideoModeIndex = 0;
public FrameDivisor streamingFrameDivisor = FrameDivisor.NONE;
public boolean ledMode = false;
@@ -57,6 +62,8 @@ public class CVPipelineSettings implements Cloneable {
&& Double.compare(that.cameraExposure, cameraExposure) == 0
&& Double.compare(that.cameraBrightness, cameraBrightness) == 0
&& Double.compare(that.cameraGain, cameraGain) == 0
&& Double.compare(that.cameraRedGain, cameraRedGain) == 0
&& Double.compare(that.cameraBlueGain, cameraBlueGain) == 0
&& cameraVideoModeIndex == that.cameraVideoModeIndex
&& ledMode == that.ledMode
&& pipelineType == that.pipelineType
@@ -79,6 +86,8 @@ public class CVPipelineSettings implements Cloneable {
cameraExposure,
cameraBrightness,
cameraGain,
cameraRedGain,
cameraBlueGain,
cameraVideoModeIndex,
streamingFrameDivisor,
ledMode,

View File

@@ -107,6 +107,13 @@ public class VisionModule {
if (it.cameraGain == -1) it.cameraGain = 20; // Sane default
});
}
if (cameraQuirks.hasQuirk(CameraQuirk.PiCam)) {
pipelineManager.userPipelineSettings.forEach(
it -> {
if (it.cameraRedGain == -1) it.cameraRedGain = 16; // Sane defaults
if (it.cameraBlueGain == -1) it.cameraBlueGain = 16;
});
}
this.pipelineManager = pipelineManager;
this.visionSource = visionSource;
@@ -345,6 +352,10 @@ public class VisionModule {
if (!cameraQuirks.hasQuirk(CameraQuirk.Gain)) {
settings.cameraGain = -1;
}
if (!cameraQuirks.hasQuirk(CameraQuirk.PiCam)) {
settings.cameraRedGain = -1;
settings.cameraBlueGain = -1;
}
setPipeline(PipelineManager.CAL_3D_INDEX);
}
@@ -391,6 +402,16 @@ public class VisionModule {
} else {
config.cameraGain = -1;
}
if (cameraQuirks.hasQuirk(CameraQuirk.PiCam)) {
// If the AWB gains are disabled for some reason, re-enable it
if (config.cameraRedGain == -1) config.cameraRedGain = 16;
if (config.cameraBlueGain == -1) config.cameraBlueGain = 16;
visionSource.getSettables().setRedGain(Math.max(0, config.cameraRedGain));
visionSource.getSettables().setBlueGain(Math.max(0, config.cameraBlueGain));
} else {
config.cameraRedGain = -1;
config.cameraBlueGain = -1;
}
setVisionLEDs(config.ledMode);

View File

@@ -48,6 +48,11 @@ public abstract class VisionSourceSettables {
public abstract void setBrightness(int brightness);
public abstract void setGain(int gain);
// Pretty uncommon so instead of abstract this is just a no-op by default
// Overriden by cameras with AWB gain support
public void setRedGain(int red) {}
public void setBlueGain(int blue) {}
public abstract VideoMode getCurrentVideoMode();