gdi

library(gdi)
#> Loading required package: jpeg
#> Loading required package: png

This vignette demonstrates the basic workflow of the gdi package. We start with a set of image files showing orthogonal views of an animal for which a volumetric estimate is desired.

These image files should be aligned and with the long axis horizontal, and complex features that violate the assumption of elliptical or superelliptical cross-sections (e.g. limbs or fins protruding from the silhouette) should be removed and estimated separately.

These example images are provided with the package in the folder exdata. To import them, execute:


fdir <- system.file(package="gdi")

measurements_lateral <- measuresil(file.path(fdir,"exdata","lat.png"))
measurements_dorsal <- measuresil(file.path(fdir,"exdata","dors.png"))

In this case the images are in rgba format and with transparent background. We therefore do not need to change the default options for threshold (0.5), method (“greater”) and channel (4) provided with the function. The default selection will automatically count all pixels with an opacity (alpha channel value) of more than 0.5 as part of the silhouette and treat everything else as background.

Verify that our measurement worked and resulted in two vectors of equal length:

length(measurements_lateral)
#> [1] 2341
length(measurements_dorsal)
#> [1] 2341

We can now perform our graphic double integration to estimate the volume:

gdi(measurements_lateral, measurements_dorsal, scale=100, method="smooth")
#> [1] 42.35045

The result of this function is the estimated volume in the chosen unit of measurements. The silhouette is at a scale of 100px:10cm, so a scale value of 100 will report the volume in litres (cubic decimetres), namely 1.0171777^{-4} for this example.

To demonstrate the difference between the “raw” and “smooth” settings of the gdi()-function, consider the following simple example.

sil <- c(0,1)
gdi(sil, sil, method="raw", scale=1)
#> [1] 0.7853982
gdi(sil, sil, method="smooth", scale=1)
#> [1] 1.047198

As we can see, method “raw” gives us the volume of a cylinder with a diameter of 1 and a length (because scale is set to 1) of 1. On the other hand, method “smooth” (or any other setting), estimates the volume as a series of frusta, with base areas based on each segment and the one succeeding it. In this case, because segment 1 has a diameter of 0, this results in the estimated volume being that of a cone with length 1 and base diameter 1 and a cylinder for segment two.

This difference in methods has no major effects on analyses using pixel-precise measurements of digital images (in this case, the difference is only -0.2617994 l), but can have a notable effect at lower resolutions (fewer, longer segments).

In the event that the cross-sectional geometry of our shape deviates markedly from an ellipse, the package provides two approaches to account for this. The first is the specification of a superellipse exponent as part of the function call to gdi():

gdi(measurements_lateral,measurements_dorsal,k=2.3, scale=100)
#> [1] 44.46848

In this case we specified a superellipse exponent of k, which results in a cross-sectional area, and thus a volume, approximately 5% greater than an ordinary ellipse. For a review of cross-sectional geometry in vertebrates, see Motani (2001).

The second option is to use a graphical reconstruction of the cross-sectional shape to calculate a correction factor determined from the ratio in areas between the actual cross-section, and an ellipse matching its vertical and horizontal maximum diameters (which correspond to the diameters that would be measured from silhouettes for the GDI. Determining this correction factor from a silhouette image of the cross-section is implemented in the cscorr()-function:

fdir <- system.file(package="gdi")
correction_factor <- cscorr(file.path(fdir,"exdata","cross_section.png"))
print(correction_factor)
#> [1] 1.092215

The resulting correction factor can then be multiplied by the “raw” volume estimated by the gdi without correction, or directly supplied to the gdi()-function using the ‘corr’ parameter.

Both the k and corr parameters can either be a single value applicable to the entire volume, or a numeric vector containing a correction factor for every segment (this vector needs to be of the same length as the diameter measurements used with the gdi()-function). If desired, interpolation between different cross-sectional geometries over the length of the model (e.g. using approx()) might be used in order to further increase accuracy of the estimation.

The volume of more complex shapes can be estimated using this technique, by manually splitting the silhouettes into several pairs of image files, each containing two orthogonal views of each body part. Total volume can then simply be estimated as the sum of all body parts.