Skip to content

Commit

Permalink
Support more charuco boards (#1348)
Browse files Browse the repository at this point in the history
Add support for the old opencv charuco board like calibio. 

Add support for other tag families while calibrating.

Fix calibration issue index out of range with charuco missing points.
  • Loading branch information
Juniormunk authored Jun 21, 2024
1 parent 1d98105 commit 8c45fef
Show file tree
Hide file tree
Showing 38 changed files with 143 additions and 29 deletions.
25 changes: 23 additions & 2 deletions photon-client/src/components/cameras/CameraCalibrationCard.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, ref } from "vue";
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
import { CalibrationBoardTypes, type VideoFormat } from "@/types/SettingTypes";
import { CalibrationBoardTypes, CalibrationTagFamilies, type VideoFormat } from "@/types/SettingTypes";
import JsPDF from "jspdf";
import { font as PromptRegular } from "@/assets/fonts/PromptRegular";
import MonoLogo from "@/assets/images/logoMono.png";
Expand Down Expand Up @@ -79,6 +79,8 @@ const markerSizeIn = ref(0.75);
const patternWidth = ref(8);
const patternHeight = ref(8);
const boardType = ref<CalibrationBoardTypes>(CalibrationBoardTypes.Charuco);
const useOldPattern = ref(false);
const tagFamily = ref<CalibrationTagFamilies>(CalibrationTagFamilies.Dict_4X4_1000);
const useMrCalRef = ref(true);
const useMrCal = computed<boolean>({
get() {
Expand Down Expand Up @@ -200,7 +202,9 @@ const startCalibration = () => {
patternHeight: patternHeight.value,
patternWidth: patternWidth.value,
boardType: boardType.value,
useMrCal: useMrCal.value
useMrCal: useMrCal.value,
useOldPattern: useOldPattern.value,
tagFamily: tagFamily.value
});
// The Start PnP method already handles updating the backend so only a store update is required
useCameraSettingsStore().currentCameraSettings.currentPipelineIndex = WebsocketPipelineType.Calib3d;
Expand Down Expand Up @@ -302,6 +306,15 @@ const setSelectedVideoFormat = (format: VideoFormat) => {
:items="['Chessboard', 'Charuco']"
:disabled="isCalibrating"
/>
<pv-select
v-model="tagFamily"
v-show="boardType == CalibrationBoardTypes.Charuco"
label="Tag Family"
tooltip="Dictionary of aruco markers on the charuco board"
:select-cols="7"
:items="['Dict_4X4_1000', 'Dict_5X5_1000', 'Dict_6X6_1000', 'Dict_7X7_1000']"
:disabled="isCalibrating"
/>
<pv-number-input
v-model="squareSizeIn"
label="Pattern Spacing (in)"
Expand Down Expand Up @@ -335,6 +348,14 @@ const setSelectedVideoFormat = (format: VideoFormat) => {
:rules="[(v) => v >= 4 || 'Height must be at least 4']"
:label-cols="5"
/>
<pv-switch
v-model="useOldPattern"
v-show="boardType == CalibrationBoardTypes.Charuco"
label="Old OpenCV Pattern"
:disabled="isCalibrating"
tooltip="If enabled, Photon will use the old OpenCV pattern for calibration."
:label-cols="5"
/>
<pv-switch
v-model="useMrCal"
label="Try using MrCal over OpenCV"
Expand Down
3 changes: 3 additions & 0 deletions photon-client/src/stores/settings/CameraSettingsStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineStore } from "pinia";
import type {
CalibrationTagFamilies,
CalibrationBoardTypes,
CameraCalibrationResult,
CameraSettings,
Expand Down Expand Up @@ -319,6 +320,8 @@ export const useCameraSettingsStore = defineStore("cameraSettings", {
patternHeight: number;
boardType: CalibrationBoardTypes;
useMrCal: boolean;
useOldPattern: boolean;
tagFamily: CalibrationTagFamilies;
},
cameraIndex: number = useStateStore().currentCameraIndex
) {
Expand Down
7 changes: 7 additions & 0 deletions photon-client/src/types/SettingTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,13 @@ export enum CalibrationBoardTypes {
Charuco = 1
}

export enum CalibrationTagFamilies {
Dict_4X4_1000 = 0,
Dict_5X5_1000 = 1,
Dict_6X6_1000 = 2,
Dict_7X7_1000 = 3
}

export enum RobotOffsetType {
Clear = 0,
Single = 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ public void createObjectPoints() {
new Size(params.boardWidth, params.boardHeight),
(float) params.gridSize,
(float) params.markerSize,
Objdetect.getPredefinedDictionary(params.tagFamily));
Objdetect.getPredefinedDictionary(params.tagFamily.getValue()));
board.setLegacyPattern(params.useOldPattern);
detector = new CharucoDetector(board);
} else {
logger.error("Can't create pattern for unknown board type " + params.type);
Expand Down Expand Up @@ -309,6 +310,7 @@ private FindBoardCornersPipeResult findBoardCorners(Pair<Mat, Mat> in) {
}

outBoardCorners.fromArray(boardCorners);
objPts.fromArray(objectPoints);
outLevels.fromArray(levels);
}
imgPoints.release();
Expand Down Expand Up @@ -371,23 +373,26 @@ public static class FindCornersPipeParams {
final double gridSize;
final double markerSize;
final FrameDivisor divisor;
final int tagFamily;
final UICalibrationData.TagFamily tagFamily;
final boolean useOldPattern;

public FindCornersPipeParams(
int boardHeight,
int boardWidth,
UICalibrationData.BoardType type,
int tagFamily,
UICalibrationData.TagFamily tagFamily,
double gridSize,
double markerSize,
FrameDivisor divisor) {
FrameDivisor divisor,
boolean useOldPattern) {
this.boardHeight = boardHeight;
this.boardWidth = boardWidth;
this.tagFamily = tagFamily;
this.type = type;
this.gridSize = gridSize; // meter
this.markerSize = markerSize; // meter
this.divisor = divisor;
this.useOldPattern = useOldPattern;
}

@Override
Expand All @@ -412,6 +417,8 @@ public boolean equals(Object obj) {
FindCornersPipeParams other = (FindCornersPipeParams) obj;
if (boardHeight != other.boardHeight) return false;
if (boardWidth != other.boardWidth) return false;
if (tagFamily != other.tagFamily) return false;
if (useOldPattern != other.useOldPattern) return false;
if (type != other.type) return false;
if (Double.doubleToLongBits(gridSize) != Double.doubleToLongBits(other.gridSize))
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ protected void setPipeParamsImpl() {
settings.tagFamily,
settings.gridSize,
settings.markerSize,
settings.streamingFrameDivisor);
settings.streamingFrameDivisor,
settings.useOldPattern);
findBoardCornersPipe.setParams(findCornersPipeParams);

Calibrate3dPipe.CalibratePipeParams calibratePipeParams =
Expand Down Expand Up @@ -227,7 +228,9 @@ private void broadcastState() {
settings.boardWidth,
settings.boardHeight,
settings.boardType,
settings.useMrCal));
settings.useMrCal,
settings.useOldPattern,
settings.tagFamily));

DataChangeService.getInstance()
.publishEvent(OutgoingUIEvent.wrappedOf("calibrationData", state));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@

import edu.wpi.first.math.util.Units;
import org.opencv.core.Size;
import org.opencv.objdetect.Objdetect;
import org.photonvision.vision.frame.FrameDivisor;

public class Calibration3dPipelineSettings extends AdvancedPipelineSettings {
public int boardHeight = 8;
public int boardWidth = 8;
public UICalibrationData.BoardType boardType = UICalibrationData.BoardType.CHESSBOARD;
public int tagFamily = Objdetect.DICT_4X4_50;
public UICalibrationData.TagFamily tagFamily = UICalibrationData.TagFamily.Dict_4X4_1000;
public double gridSize = Units.inchesToMeters(1.0);
public double markerSize = Units.inchesToMeters(0.75);

public Size resolution = new Size(640, 480);
public boolean useMrCal = true;
public boolean useOldPattern = false;

public Calibration3dPipelineSettings() {
super();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.photonvision.vision.pipeline;

import org.opencv.objdetect.Objdetect;

public class UICalibrationData {
public int videoModeIndex;
public int count;
Expand All @@ -28,6 +30,8 @@ public class UICalibrationData {
public BoardType boardType;
public boolean useMrCal;
public double markerSizeIn;
public boolean useOldPattern;
public TagFamily tagFamily;

public UICalibrationData() {}

Expand All @@ -41,7 +45,9 @@ public UICalibrationData(
int patternWidth,
int patternHeight,
BoardType boardType,
boolean useMrCal) {
boolean useMrCal,
boolean useOldPattern,
TagFamily tagFamily) {
this.count = count;
this.minCount = minCount;
this.videoModeIndex = videoModeIndex;
Expand All @@ -52,13 +58,34 @@ public UICalibrationData(
this.patternHeight = patternHeight;
this.boardType = boardType;
this.useMrCal = useMrCal;
this.useOldPattern = useOldPattern;
this.tagFamily = tagFamily;
}

public enum BoardType {
CHESSBOARD,
CHARUCOBOARD,
}

public enum TagFamily {
Dict_4X4_1000(Objdetect.DICT_4X4_1000),
Dict_5X5_1000(Objdetect.DICT_5X5_1000),
Dict_6X6_1000(Objdetect.DICT_6X6_1000),
Dict_7X7_1000(Objdetect.DICT_7X7_1000);

private int value;

// getter method
public int getValue() {
return this.value;
}

// enum constructor - cannot be public or protected
private TagFamily(int value) {
this.value = value;
}
}

@Override
public String toString() {
return "UICalibrationData{"
Expand All @@ -80,6 +107,10 @@ public String toString() {
+ patternHeight
+ ", boardType="
+ boardType
+ ", tagFamily="
+ tagFamily
+ ", useOldPattern="
+ useOldPattern
+ '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ public void startCalibration(UICalibrationData data) {
settings.boardType = data.boardType;
settings.useMrCal = data.useMrCal;
settings.resolution = resolution;
settings.useOldPattern = data.useOldPattern;
settings.tagFamily = data.tagFamily;

// Disable gain if not applicable
if (!cameraQuirks.hasQuirk(CameraQuirk.Gain)) {
Expand Down
Loading

0 comments on commit 8c45fef

Please sign in to comment.