The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

coiR

Edson Silva-Júnior 2026-09-29

coiR

Package to calculate Canopy Openness Index (COI) from canopy images

Installing package

require("devtools")

devtools::install_github("Edbbioeco/coiR")

Loading package

coiR package is downloaded now, so we can library it. Additionally, we library the following packages:

library(coiR)

library(terra)

library(purrr)

library(ggplot2)

library(tidyterra)

Data

Importing

Now, we need to import our data Images may be shotten photos, as .png, .jpg or .jpeg files. first, we import package exemple data, using coiR::coir_data() function, and import them using terra::rast() function for every image, throught a loop with purrr::map() function. Our images (images) are setted as a list class object.

images <- purrr::map(coiR::data_coir(),
                     ~.x |> terra::rast())

images
[[1]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source      : imagem1.png
names       : imagem1_1, imagem1_2, imagem1_3, imagem1_4

[[2]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source      : imagem2.png
names       : imagem2_1, imagem2_2, imagem2_3, imagem2_4

[[3]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source      : imagem3.png
names       : imagem3_1, imagem3_2, imagem3_3, imagem3_4

[[4]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source      : imagem4.png
names       : imagem4_1, imagem4_2, imagem4_3, imagem4_4

Visualizing

Next, lets visualize every image, using a purrr::map() loop, through ggplot and tidyterra::geom_spatraster_rgb() function.

purrr::map(images, 
           purrr::in_parallel(
             
             ~ggplot() + 
               tidyterra::geom_spatraster_rgb(data = .x) + 
               theme_void()
             
             ),
           .progress = TRUE)
[[1]]

[[2]]

[[3]]

[[4]]

Canopy Openness Index

Isolating a single image

For our exemples, lets work in two ways: run for a single and run for multiple images. Lets set first image as a single image.

single_image <- images[[1]]

Crop image

Usely, canopy images are shotten photos, square images. For our analysis, we need to crop images into circles. We use coiR::coir_crop() |function.

single_image |> 
  coiR::coir_crop()

class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
varname     : imagem1
names       : imagem1_1, imagem1_2, imagem1_3, imagem1_4
min values  :         4,        25,        33,        29
max values  :       243,       241,       246,       255

And we also can analyse multiple images from an one shot, using purrr::map() loop.

purrr::map(images, coiR::coir_crop)

[[1]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
varname     : imagem1
names       : imagem1_1, imagem1_2, imagem1_3, imagem1_4
min values  :         4,        25,        33,        29
max values  :       243,       241,       246,       255

[[2]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
varname     : imagem2
names       : imagem2_1, imagem2_2, imagem2_3, imagem2_4
min values  :         2,        21,        21,        29
max values  :       255,       255,       255,       255

[[3]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
varname     : imagem3
names       : imagem3_1, imagem3_2, imagem3_3, imagem3_4
min values  :         3,        19,         7,        29
max values  :       255,       255,       255,       255

[[4]]
class       : SpatRaster
size        : 800, 800, 4  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
varname     : imagem4
names       : imagem4_1, imagem4_2, imagem4_3, imagem4_4
min values  :         1,        13,         1,        30
max values  :       255,       255,       255,       255

Binarize images

Our next step is to binarize our images. We use coiR::coir_binarize() function. To avoid replot canopy image, we use plot = FALSE argument at coiR::coir_crop() function. To facilite our analysis, lets use pipe (|>) to conect functions output.

single_image |> 
  coiR::coir_crop(plot = FALSE) |> 
  coiR::coir_binarize()

class       : SpatRaster
size        : 800, 800, 1  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
name        : variavel
min value   :        0
max value   :        1

As previously made, we can binarize multiple images, making a function in our purrr::map() loop.

purrr::map(images, 
           purrr::in_parallel(
             
             ~coiR::coir_crop(data = .x,
                              plot = FALSE) |>
               coiR::coir_binarize()
             
             ),
           .progress = TRUE)

[[1]]
class       : SpatRaster
size        : 800, 800, 1  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
name        : variavel
min value   :        0
max value   :        1

[[2]]
class       : SpatRaster
size        : 800, 800, 1  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
name        : variavel
min value   :        0
max value   :        1

[[3]]
class       : SpatRaster
size        : 800, 800, 1  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
name        : variavel
min value   :        0
max value   :        1

[[4]]
class       : SpatRaster
size        : 800, 800, 1  (nrow, ncol, nlyr)
resolution  : 1, 1  (x, y)
extent      : 0, 800, 0, 800  (xmin, xmax, ymin, ymax)
coord. ref. : 
source(s)   : memory
name        : variavel
min value   :        0
max value   :        1

Index

Finally, we get COI index. We use coiR::coir_index() for get that value. To avoid replot cropped and binarized images, we set plot = FALSE for both coiR::coir_crop() and coiR::coir_binarize() functions.

single_image |> 
  coiR::coir_crop(plot = FALSE) |> 
  coiR::coir_binarize(plot = FALSE) |> 
  coiR::coir_index()
[1] 0.5

As previously made, we can also do for multiple images, making a function in purrr::map_dbl() function.

purrr::map_dbl(images, 
               purrr::in_parallel(
                 
      ~coiR::coir_crop(data = .x,
                       plot = FALSE) |>
        coiR::coir_binarize(plot = FALSE) |> 
        coiR::coir_index()
             
             ),
      .progress = TRUE)
[1] 0.50 0.52 0.28 0.29

Finally, we make a data rame with those values, using purrr::imap_dfr(), to get image names.

df_index <- purrr::imap_dfr(
  images, 
  purrr::in_parallel(
    
    \(imagem, nome){
      
      index <- imagem |> 
        coiR::coir_crop(plot = FALSE) |>
        coiR::coir_binarize(plot = FALSE) |> 
        coiR::coir_index(round = 3)
      
      tibble::tibble(id = nome,
                     Index = index)
      
      }
    
    ),
  .progress = TRUE)

df_index
# A tibble: 4 × 2
     id Index
  <int> <dbl>
1     1 0.501
2     2 0.518
3     3 0.281
4     4 0.29 

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.