Skip to content

Commit 11767e9

Browse files
committed
Clean things up
1 parent d1a5ab8 commit 11767e9

File tree

4 files changed

+128
-11
lines changed

4 files changed

+128
-11
lines changed

src/main/java/org/photonvision/mrcal/MrCalJNI.java

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828
import org.opencv.core.MatOfPoint2f;
2929

3030
public class MrCalJNI {
31+
public static enum CameraLensModel {
32+
LENSMODEL_OPENCV5,
33+
LENSMODEL_OPENCV8,
34+
LENSMODEL_STEREOGRAPHIC,
35+
LENSMODEL_SPLINED_STEREOGRAPHIC;
36+
}
37+
3138
public static class MrCalResult {
3239
public boolean success;
3340
public double[] intrinsics;
@@ -121,6 +128,29 @@ public String toString() {
121128
}
122129
}
123130

131+
/**
132+
* Performs camera calibration using [mrcal](https://mrcal.secretsauce.net/formulation.html)
133+
*
134+
* @param observations_board a packed double array containing all observations across all frames.
135+
* The array is structured as a flattened list where each observation consists of 3
136+
* consecutive doubles: [x, y, level] for each corner of each board in each frame. Structure:
137+
* For N frames, each observing a boardWidth×boardHeight checkerboard, the array has length N
138+
* × boardWidth × boardHeight × 3. The level value (0-based) represents detection quality and
139+
* will be converted to a weight using weight = 0.5^level. A negative level indicates the
140+
* corner was not detected (will be marked as an outlier).
141+
* @param boardWidth the number of internal corners in the horizontal direction of the calibration
142+
* board
143+
* @param boardHeight the number of internal corners in the vertical direction of the calibration
144+
* board
145+
* @param boardSpacing the physical distance (in arbitrary but consistent units) between adjacent
146+
* corners on the calibration board. PhotonVision uses meters.
147+
* @param imageWidth the width in pixels of the images used for calibration
148+
* @param imageHeight the height in pixels of the images used for calibration
149+
* @param focalLen an initial guess for the focal length in pixels, used to seed the optimization
150+
* @return an {@link MrCalResult} object containing the calibration results, including optimized
151+
* intrinsics, board poses, RMS error, per-observation residuals, detected outliers, and a
152+
* boolean mask indicating which corners were actually used in the final optimization
153+
*/
124154
public static native MrCalResult mrcal_calibrate_camera(
125155
double[] observations_board,
126156
int boardWidth,
@@ -130,8 +160,34 @@ public static native MrCalResult mrcal_calibrate_camera(
130160
int imageHeight,
131161
double focalLen);
132162

163+
/**
164+
* Applies mrcal lens distortion correction to undistort pixel coordinates.
165+
*
166+
* <p>This method takes distorted pixel coordinates and applies the inverse of mrcal's lens
167+
* distortion model to produce undistorted (corrected) coordinates. The input coordinates are
168+
* unprojected through the specified lens model to 3D ray vectors, then reprojected through a
169+
* pinhole model.
170+
*
171+
* @param dstMat a pointer to a cv::Mat containing distorted pixel coordinates (passed as a long
172+
* representing the memory address). Must be a CV_64FC2 continuous matrix where each row
173+
* contains one (x, y) coordinate pair. The matrix is modified in-place with the undistorted
174+
* coordinates as output.
175+
* @param cameraMat a pointer to the camera calibration matrix cv::Mat (3×3, opencv format).
176+
* @param distCoeffsMat a pointer to the distortion coefficients cv::Mat. The interpretation of
177+
* these coefficients depends on the specified lens model.
178+
* @param lensModelOrdinal the ordinal value of the {@link CameraLensModel} enum indicating which
179+
* lens distortion model to use for undistortion
180+
* @param order the spline interpolation order to use when warping pixels, if the lensmodel is
181+
* splined. Unused otherwise
182+
* @param Nx the number of control points in the x-direction for the distortion spline model.
183+
* Unused otherwise
184+
* @param Ny the number of control points in the y-direction for the distortion spline model.
185+
* Unused otherwise
186+
* @param fov_x_deg the horizontal field of view in degrees used for certain lens model, if
187+
* splined. Unused otherwise calculations
188+
* @return true if the undistortion was successful, false otherwise
189+
*/
133190
public static native boolean undistort_mrcal(
134-
long srcMat,
135191
long dstMat,
136192
long cameraMat,
137193
long distCoeffsMat,
@@ -141,6 +197,44 @@ public static native boolean undistort_mrcal(
141197
int Ny,
142198
int fov_x_deg);
143199

200+
/**
201+
* Computes projection uncertainty for camera calibration across a grid of image points.
202+
*
203+
* <p>This method evaluates the uncertainty in 3D point projection due to calibration error. It
204+
* computes uncertainty at a regular grid of points across the image plane.
205+
*
206+
* @param observations_board a packed double array containing calibration observations with the
207+
* same structure as used in {@link #mrcal_calibrate_camera}. For N frames observing a
208+
* boardWidth×boardHeight checkerboard, the array has length N × boardWidth × boardHeight × 3,
209+
* where each triplet is [x, y, level].
210+
* @param intrinsics a double array containing the camera intrinsic parameters. The exact content
211+
* and length depend on the lens distortion model being used, but typically includes focal
212+
* length, principal point, and distortion coefficients.
213+
* @param rt_ref_frames a packed double array containing the poses (rotations and translations) of
214+
* the calibration board relative to the camera for each frame. The array is structured as N
215+
* consecutive 6-element groups, where each group represents one frame's pose: [rx, ry, rz,
216+
* tx, ty, tz]. The rotation components (rx, ry, rz) form a rotation vector (axis-angle
217+
* representation), and (tx, ty, tz) represent the translation. Total array length is N × 6,
218+
* where N is the number of observed frames.
219+
* @param boardWidth the number of internal corners in the horizontal direction of the calibration
220+
* board
221+
* @param boardHeight the number of internal corners in the vertical direction of the calibration
222+
* board
223+
* @param boardSpacing the physical distance between adjacent corners on the calibration board
224+
* (must match the value used in calibration). PhotonVision uses meters.
225+
* @param imageWidth the width in pixels of the camera imager at this particular VideoMode
226+
* @param imageHeight the height in pixels of the camera imager at this particular VideoMode
227+
* @param sampleGridWidth the number of sample points in the horizontal direction for uncertainty
228+
* computation
229+
* @param sampleGridHeight the number of sample points in the vertical direction for uncertainty
230+
* computation
231+
* @param warpX the x-component of lens distortion warp, or zero if no warp was estimated.
232+
* @param warpY the y-component of lens distortion warp
233+
* @return a packed double array containing uncertainty values at each sampled grid point. The
234+
* array is structured as a sequence of 3D points (mrcal_point3_t), representing [u, v,
235+
* uncertainty] for each point we sampled. Total array length is sampleGridWidth ×
236+
* sampleGridHeight × 3. Returns null if computation fails.
237+
*/
144238
public static native double[] compute_uncertainty(
145239
double[] observations_board,
146240
double[] intrinsics,
@@ -155,7 +249,14 @@ public static native double[] compute_uncertainty(
155249
double warpX,
156250
double warpY);
157251

158-
public static double[] makeObservations(
252+
/**
253+
* Convert a list of board-pixel-corners and detection levels for each snapshot of a chessboard
254+
* boardWidth x boardHeight to a packed double[] suitable to pass to
255+
* MrCalJni::mrcal_calibrate_camera. Levels will be converted to weights using weight = 0.5^level,
256+
* as explained
257+
* [here](https://github.com/dkogan/mrcal/blob/7cd9ac4c854a4b244a35f554c9ebd0464d59e9ff/mrcal-calibrate-cameras#L152)
258+
*/
259+
private static double[] makeObservations(
159260
List<MatOfPoint2f> board_corners,
160261
List<MatOfFloat> board_corner_levels,
161262
int boardWidth,
@@ -192,6 +293,23 @@ public static double[] makeObservations(
192293
return observations;
193294
}
194295

296+
/**
297+
* High-level wrapper for camera calibration using mrcal.
298+
*
299+
* <p>Converts detected chessboard corners and their detection levels into a packed double array,
300+
* then calls {@link #mrcal_calibrate_camera} to perform calibration. Each corner's detection
301+
* level is converted to a weight (0.5^level), and negative levels indicate undetected corners.
302+
*
303+
* @param board_corners List of detected chessboard corners for each frame
304+
* @param board_corner_levels List of detection levels for each corner in each frame. Point weight is calculated as weight = 0.5^level. Negative weight will ignore this observation
305+
* @param boardWidth Number of internal corners horizontally
306+
* @param boardHeight Number of internal corners vertically
307+
* @param boardSpacing Physical spacing between corners (meters)
308+
* @param imageWidth Image width in pixels
309+
* @param imageHeight Image height in pixels
310+
* @param focalLen Initial guess for focal length (pixels)
311+
* @return Calibration result with optimized intrinsics, poses, and error metrics
312+
*/
195313
public static MrCalResult calibrateCamera(
196314
List<MatOfPoint2f> board_corners,
197315
List<MatOfFloat> board_corner_levels,

src/mrcal_jni.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,16 +273,15 @@ Java_org_photonvision_mrcal_MrCalJNI_mrcal_1calibrate_1camera
273273
/*
274274
* Class: org_photonvision_mrcal_MrCalJNI_undistort
275275
* Method: 1mrcal
276-
* Signature: (JJJJIIIII)Z
276+
* Signature: (JJJIIIII)Z
277277
*/
278278
JNIEXPORT jboolean JNICALL
279279
Java_org_photonvision_mrcal_MrCalJNI_undistort_1mrcal
280-
(JNIEnv *, jclass, jlong srcMat, jlong dstMat, jlong camMat, jlong distCoeffs,
280+
(JNIEnv *, jclass, jlong dstMat, jlong camMat, jlong distCoeffs,
281281
jint lensModelOrdinal, jint order, jint Nx, jint Ny, jint fov_x_deg)
282282
{
283283
return undistort_mrcal(
284-
reinterpret_cast<cv::Mat *>(srcMat), reinterpret_cast<cv::Mat *>(dstMat),
285-
reinterpret_cast<cv::Mat *>(camMat),
284+
reinterpret_cast<cv::Mat *>(dstMat), reinterpret_cast<cv::Mat *>(camMat),
286285
reinterpret_cast<cv::Mat *>(distCoeffs),
287286
static_cast<CameraLensModel>(lensModelOrdinal),
288287
static_cast<uint16_t>(order), static_cast<uint16_t>(Nx),

src/mrcal_wrapper.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ std::unique_ptr<mrcal_result> mrcal_main(
501501
return result;
502502
}
503503

504-
bool undistort_mrcal(const cv::Mat *src, cv::Mat *dst, const cv::Mat *cameraMat,
504+
bool undistort_mrcal(cv::Mat *dst, const cv::Mat *cameraMat,
505505
const cv::Mat *distCoeffs, CameraLensModel lensModel,
506506
// Extra stuff for splined stereographic models
507507
uint16_t order, uint16_t Nx, uint16_t Ny,
@@ -536,15 +536,15 @@ bool undistort_mrcal(const cv::Mat *src, cv::Mat *dst, const cv::Mat *cameraMat,
536536
return false;
537537
}
538538

539-
if (!(dst->cols == 2 && dst->cols == 2)) {
539+
if (!(dst->cols == 2)) {
540540
std::cerr << "Bad input array size\n";
541541
return false;
542542
}
543-
if (!(dst->type() == CV_64FC2 && dst->type() == CV_64FC2)) {
543+
if (!(dst->type() == CV_64FC2)) {
544544
std::cerr << "Bad input type -- need CV_64F\n";
545545
return false;
546546
}
547-
if (!(dst->isContinuous() && dst->isContinuous())) {
547+
if (!(dst->isContinuous())) {
548548
std::cerr << "Bad input array -- need continuous\n";
549549
return false;
550550
}

src/mrcal_wrapper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ enum class CameraLensModel {
8888
LENSMODEL_SPLINED_STEREOGRAPHIC
8989
};
9090

91-
bool undistort_mrcal(const cv::Mat *src, cv::Mat *dst, const cv::Mat *cameraMat,
91+
bool undistort_mrcal(cv::Mat *dst, const cv::Mat *cameraMat,
9292
const cv::Mat *distCoeffs, CameraLensModel lensModel,
9393
// Extra stuff for splined stereographic models
9494
uint16_t order, uint16_t Nx, uint16_t Ny,

0 commit comments

Comments
 (0)