Learn R Programming

rcaiman (version 1.2.2)

calibrate_lens: Calibrate lens

Description

Calibrate a fisheye lens

Usage

calibrate_lens(path_to_csv, degree = 3)

Value

An object of class list with named elements. ds is the dataset used to fit the model, model is the fitted model (class lm, see stats::lm()), horizon_radius is the radius at 90º, lens_coef is a numeric vector of length equal to the degree argument containing the polynomial model coefficients for predicting relative radius (coefficients(model)/horizon_radius), zenith_colrow are the raster coordinates of the zenith push pin, max_theta is the maximum zenith angle in degrees, and max_theta_px is the distance in pixels between the zenith and the maximum zenith angle in pixels units.

Arguments

path_to_csv

Character vector. Path to a CSV file created with the point selection tool of ‘ImageJ’ software.

degree

Numeric vector of length one. Polynomial model degree.

Details

Fisheye lenses have a wide field of view and the same distortion in all directions running orthogonally to the optical axis. The latter property allows fitting a precise mathematical relationship between distances to the zenith on the image space and zenith angles on the hemispherical space (assuming upward-looking hemispherical photography with the optical axis vertically aligned).

The method outlined here, known as the simple method, is explained in details in Diaz2024;textualrcaiman. Next explanation might serve mostly as a handbook.

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.

Calibration board

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...

Points digitization with ImageJ

Use test_lens_coef() to test if coefficients are OK.

References

See Also

Other Lens Functions: azimuth_image(), calc_diameter(), calc_relative_radius(), calc_zenith_colrow(), crosscalibrate_lens(), expand_noncircular(), extract_radiometry(), fisheye_to_equidistant(), fisheye_to_pano(), lens(), test_lens_coef(), zenith_image()

Examples

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

if (FALSE) {
test_lens_coef(calibration$lens_coef) #MacOS and Windows tend to differ here
test_lens_coef(c(0.628, 0.0399, -0.0217))
}

.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)))

Run the code above in your browser using DataLab