calibrate_lens: Calibrate lens

View source: R/calibrate_lens.R

calibrate_lensR Documentation

Calibrate lens

Description

Calibrate a fisheye lens to derive the mathematical relationship between image-space radial distances from the zenith and zenith angles in hemispherical space (assuming upward-looking hemispherical photography with the optical axis vertically aligned).

Usage

calibrate_lens(path_to_csv, degree = 3)

Arguments

path_to_csv

character vector. Path(s) to CSV file(s) created with the ImageJ point selection tool. See Note.

degree

numeric vector of length one. Polynomial model degree.

Details

Fisheye lenses have a wide field of view and radial symmetry with respect to distortion. This property allows precise fitting of a polynomial model to relate pixel distances to zenith angles. The method implemented here, known as the "simple method", is described in detail by \insertCiteDiaz2024;textualrcaiman.

Value

List with named elements:

ds

Data frame used to fit the model.

model

lm object fitted to pixel distance vs. zenith angle.

horizon_radius

Radius at 90 deg.

lens_coef

Numeric vector of polynomial model coefficients for predicting relative radius.

zenith_colrow

Raster coordinates of the zenith push pin.

max_theta

Maximum zenith angle (deg).

max_theta_px

Distance in pixels between the zenith and the maximum zenith angle.

Step-by-step guide for producing a CSV file to feed this function

Materials

  • this package and ImageJ

  • camera and lens

  • tripod

  • standard yoga mat

  • table at least as wide as the yoga mat width

  • twenty two push pins of different colors

  • one print of this sheet (A1 size, almost like a research poster).

  • scissors

  • some patience

Instructions

Cut the sheet by the dashed line. Place the yoga mat extended on top of the table. Place the sheet on top of the yoga mat. Align the dashed line with the yoga mat border closest to you. Place push pins on each cross. If you are gentle, the yoga mat will allow you to do that without damaging the table. Of course, other materials could be used to obtain the same result, such as cardboard, foam, nails, etc. calibrationBoard.jpg Place the camera on the tripod. Align its optical axis with the table while looking for getting an image showing the overlapping of the three pairs of push pins, as instructed in the print. In order to take care of the line of pins at 90º relative to the optical axis, it may be of help to use the naked eye to align the entrance pupil of the lens with the pins. The alignment of the push pins only guarantees the position of the lens entrance pupil, the leveling should be cheeked with an instrument, and the alignment between the optical axis and the radius of the zenith push pin should be taken into account. In practice, the latter is achieved by aligning the camera body with the orthogonal frame made by the quarter circle.

Take a photo and transfer it to the computer, open it with ImageJ, and use the point selection tool to digitize the push pins, starting from the zenith push pin and not skipping any shown push pin. End with an additional point where the image meets the surrounding black (or the last pixel in case there is not blackness because it is not a circular hemispherical image. There is no need to follow the line formed by the push pins). Then, use the dropdown menu Analyze>Measure to open the window Results. To obtain the CSV, use File>Save As... pushpinsImageJ.jpg

Note

To calibrate different directions, think of the fisheye image as an analog clock. To calibrate 3 o'clock, attach the camera to the tripod in landscape mode while leaving the quarter-circle at the lens's right side. To calibrate 9 o'clock, rotate the camera to put the quarter-circle at the lens's left side. To calibrate 12 and 6 o'clock, do the same but with the camera in portrait mode.

References

\insertAllCited

See Also

test_lens_coef(), crosscalibrate_lens(), extract_radiometry()

Examples

path <- system.file("external/Results_calibration.csv", package = "rcaiman")
calibration <- calibrate_lens(path)
coefficients(calibration$model)
calibration$lens_coef %>% signif(3)
calibration$horizon_radius

## Not run: 
test_lens_coef(calibration$lens_coef) #MacOS and Windows tend to differ here
test_lens_coef(c(0.628, 0.0399, -0.0217))

## End(Not run)

.fp <- function(theta, lens_coef) {
  x <- lens_coef[1:5]
  x[is.na(x)] <- 0
  for (i in 1:5) assign(letters[i], x[i])
  a * theta + b * theta^2 + c * theta^3 + d * theta^4 + e * theta^5
}

plot(calibration$ds)
theta <- seq(0, pi/2, pi/180)
lines(theta, .fp(theta, coefficients(calibration$model)))

rcaiman documentation built on Sept. 9, 2025, 5:42 p.m.