Fitopatometria

Diretório das imagens

# mudar de acordo com a pasta em seu computador
setwd("E:/Desktop/tiagoolivoto/static/tutorials/pliman_lca/imgs")

Severidade de doenças

Utilizando paletas

# gerar tabelas html
print_tbl <- function(table,  digits = 3, ...){
  knitr::kable(table, booktabs = TRUE, digits = digits, ...)
}
library(pliman)
## |==========================================================|
## | Tools for Plant Image Analysis (pliman 1.0.0)            |
## | Author: Tiago Olivoto                                    |
## | Type 'vignette('pliman_start')' for a short tutorial     |
## | Visit 'http://bit.ly/pkg_pliman' for a complete tutorial |
## |==========================================================|
library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5     v purrr   0.3.4
## v tibble  3.1.6     v dplyr   1.0.7
## v tidyr   1.1.4     v stringr 1.4.0
## v readr   2.1.1     v forcats 0.5.1
## Warning: package 'tidyr' was built under R version 4.1.1
## Warning: package 'readr' was built under R version 4.1.2
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x forcats::%>%()  masks stringr::%>%(), dplyr::%>%(), purrr::%>%(), tidyr::%>%(), tibble::%>%(), pliman::%>%()
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()

img <- image_import("img_1.jpeg")
h <- image_import("h_img1.png")
d <- image_import("d_img1.png")
b <- image_import("b_img1.png")
image_combine(img, h, d, b, ncol = 4)

Gerando paletas

h2 <- pick_palette(img)
d2 <- pick_palette(img)
b2 <- pick_palette(img)
image_combine(h2, d2, b2, ncol = 3)

Padrão da função

sev <- 
  measure_disease(img = img,
                  img_healthy = h,
                  img_symptoms = d,
                  img_background = b)

Mostrando preenchimento das lesões

sev <- 
  measure_disease(img = img,
                  img_healthy = h,
                  img_symptoms = d,
                  img_background = b,
                  show_contour = FALSE)

Mostrando uma máscara

sev <- 
  measure_disease(img = img,
                  img_healthy = h,
                  img_symptoms = d,
                  img_background = b,
                  show_contour = FALSE,
                  show_original = FALSE)

Segmentando e analizando lesões

sev <- 
  measure_disease(img = img,
                  img_healthy = h,
                  img_symptoms = d,
                  img_background = b,
                  watershed = TRUE,
                  show_contour = FALSE, # não mostra os contornos
                  show_features = TRUE, # computa características das lesões
                  show_segmentation = TRUE) # mostra as segmentações

sev$severity
##    healthy symptomatic
## 1 76.52184    23.47816
sev$statistics %>% 
  print_tbl()
stat value
n 427.000
min_area 35.000
mean_area 418.028
max_area 6648.000
sd_area 561.783
sum_area 178498.000
sev$shape[1:10, ] %>% 
  print_tbl()
id x y area perimeter radius_mean radius_min radius_max radius_sd radius_ratio major_axis eccentricity theta
1 1060.112 274.637 6648 394 46.660 19.898 72.080 11.628 3.623 118.273 0.686 -0.036
2 1058.562 361.674 5326 369 40.613 24.949 53.431 6.464 2.142 90.033 0.433 -1.508
3 463.503 536.277 6253 430 45.405 27.803 62.039 8.917 2.231 115.102 0.764 -0.076
4 774.009 402.347 1745 166 23.292 18.509 30.490 2.932 1.647 54.225 0.625 1.066
5 800.022 317.335 2854 266 30.496 14.594 43.726 7.225 2.996 81.776 0.794 0.744
6 1123.083 351.937 2001 214 25.462 15.513 35.551 4.584 2.292 61.195 0.671 -0.561
7 331.351 534.904 1202 138 19.263 12.376 24.908 2.732 2.013 45.366 0.629 -1.562
8 1108.355 494.521 1078 116 18.259 14.763 24.157 2.119 1.636 38.820 0.303 -1.133
9 1090.104 468.889 1185 136 19.392 9.087 25.175 4.068 2.771 48.675 0.715 -1.013
10 788.304 363.604 1192 159 19.842 11.637 27.588 3.852 2.371 49.020 0.725 -1.118

Utilizando índices RGB

Para identificar o melhor índice para segmentar a imagem do fundo e após as lesões da folha sadia, pode-se utilizar a função image_segment_iter. (OBS. somente funcionará em uma seção iterativa).

img %>% 
  image_resize(50) %>% 
  image_segment_iter(nseg = 2)

Após escolhidos os índices, podemos utilizar os argumentos index_lb e index_dh para segmentação da folha e fundo | lesão e sadio, respectivamente.

# após escolhidos os índices, utiliza
sev_index <- 
  measure_disease(img, 
                  index_lb = "G",
                  index_dh = "NGRDI",
                  threshold = c("Otsu", -0.05),
                  show_image = TRUE)

Processamento em lote

Para analisar diversas imagens de um diretório, utiliza-se o argumento pattern, para declarar um padrão de nomes de arquivos. Serão utilizadas 20 folhas de soja disponíveis no repositório https://osf.io/4hbr6, um banco de dados de imagens de anotação de severidade de doenças de plantas. Obrigado a Emerson M. Del Ponte e seus colaboradores por manter este projeto disponível publicamente.

system.time(
  sev_lote <- 
    measure_disease(pattern = "soy",
                    img_healthy = "healthy",
                    img_symptoms = "disease",
                    img_background = "back",
                    save_image = TRUE,
                    show_original = FALSE,
                    dir_processed = "processed",
                    show_image = FALSE)
)
## Processing image soy_1 |==                                       | 5% 00:00:00 
## Processing image soy_10 |====                                    | 10% 00:00:02 
## Processing image soy_11 |======                                  | 15% 00:00:02 
## Processing image soy_12 |========                                | 20% 00:00:03 
## Processing image soy_13 |==========                              | 25% 00:00:04 
## Processing image soy_14 |============                            | 30% 00:00:06 
## Processing image soy_15 |==============                          | 35% 00:00:07 
## Processing image soy_16 |================                        | 40% 00:00:07 
## Processing image soy_17 |==================                      | 45% 00:00:08 
## Processing image soy_18 |====================                    | 50% 00:00:10 
## Processing image soy_19 |======================                  | 55% 00:00:12 
## Processing image soy_2 |=========================                | 60% 00:00:14 
## Processing image soy_20 |==========================              | 65% 00:00:15 
## Processing image soy_3 |=============================            | 70% 00:00:17 
## Processing image soy_4 |===============================          | 75% 00:00:17 
## Processing image soy_5 |=================================        | 80% 00:00:19 
## Processing image soy_6 |===================================      | 85% 00:00:21 
## Processing image soy_7 |=====================================    | 90% 00:00:22 
## Processing image soy_8 |=======================================  | 95% 00:00:23 
## Processing image soy_9 |=========================================| 100% 00:00:24 
##   usuário   sistema decorrido 
##     23.29      2.31     25.74
sev_lote$severity %>% 
  print_tbl()
img healthy symptomatic
soy_1 93.316 6.684
soy_10 85.335 14.665
soy_11 16.849 83.151
soy_12 66.002 33.998
soy_13 79.255 20.745
soy_14 62.275 37.725
soy_15 58.377 41.623
soy_16 50.488 49.512
soy_17 82.083 17.917
soy_18 53.107 46.893
soy_19 87.621 12.379
soy_2 63.575 36.425
soy_20 51.526 48.474
soy_3 62.815 37.185
soy_4 44.305 55.695
soy_5 84.058 15.942
soy_6 78.668 21.332
soy_7 76.380 23.620
soy_8 70.316 29.684
soy_9 54.912 45.088

Diagramas de área padrão

Os diagramas de área padrão (SAD) têm sido usados há muito tempo como uma ferramenta para auxiliar na estimativa da severidade de doenças de plantas, servindo como um modelo de referência padrão antes ou durante as avaliações.

Dado um objeto calculado com measure_disease(), um SAD com n imagens contendo os respectivos valores de severidade é obtido com sad().

As folhas com menor e maior severidade sempre estarão no SAD. Se n = 1, a folha com a menor severidade será retornada. As outras são amostradas sequencialmente para obter as n imagens após a severidade ter sido ordenada em ordem crescente. Por exemplo, se houver 30 folhas e n for definido como 3, as folhas amostradas serão a 1ª, 15ª e 30ª com os menores valores de severidade.

O SAD só pode ser calculado se um nome de padrão de imagem for usado no argumento pattern da função measure_disease(). Se as imagens forem salvas, as n imagens serão recuperadas do diretório dir_processed (diretório padrão por default). Caso contrário, a severidade será calculada novamente para gerar as imagens. Um SAD com 8 imagens do exemplo acima pode ser obtido facilmente com:

sad(sev_lote, n = 4, ncol = 4)

##       img  healthy symptomatic rank
## 1   soy_1 93.31565    6.684354    1
## 17  soy_6 78.66753   21.332469    7
## 6  soy_14 62.27506   37.724938   13
## 3  soy_11 16.84902   83.150984   20

Processamento paralelo

system.time(
  sev_lote <- 
    measure_disease(pattern = "soy",
                    img_healthy = "healthy",
                    img_symptoms = "disease",
                    img_background = "back",
                    show_image = FALSE,
                    parallel = TRUE)
)
## Image processing using multiple sessions (6). Please wait.
##   usuário   sistema decorrido 
##      0.27      0.05      7.92

Imagens processadas

imgs <- 
  image_import(pattern = "proc_",
               path = "processed",
               plot = TRUE,
               ncol = 5)

Um exemplo a mais

# criar paletas 
img <- image_import( "multiplas_02.jpeg")
plot(img)

back <- pick_palette(img)
l <- pick_palette(img)
d <- pick_palette(img)

# usar as paletas na estimação de severidade
sev <- 
  measure_disease(pattern = "multip",
                  img_healthy = l,
                  img_symptoms = d,
                  img_background = back,
                  col_lesions = "red")
## Processing image multiplas_01 |=======                           | 20% 00:00:00 

## Processing image multiplas_02 |==============                    | 40% 00:00:01 

## Processing image multiplas_03 |====================              | 60% 00:00:02 

## Processing image multiplas_04 |===========================       | 80% 00:00:02 

## Processing image multiplas_05 |==================================| 100% 00:00:04 

Número de ovos

O seguinte exemplo demonstra como contar o número de ovos em uma folha. A imagem foi obtida do pacote ExpImage. Para identificar os melhores índices para segmentação da folha/fundo e ovos/folha, a função image_segment_iter() é usada.

ovos <- image_import("ovos.jpg", plot = TRUE)

# funciona apenas em uma seção iterativa
image_segment_iter(img, nseg = 2)

Após conhecer os índices, o número de ovos é computado com a função measure_disease(), indicando os índices para segmentação.

ovos_cont <- 
  measure_disease(ovos,
                  index_lb = "HUE2",
                  index_dh = "GRAY",
                  invert = c(FALSE, TRUE),
                  threshold = c("Otsu", 0.7),
                  show_features = TRUE,
                  show_segmentation = TRUE,
                  show_contour = FALSE)

ovos_cont$statistics
##        stat       value
## 1         n  170.000000
## 2  min_area    7.000000
## 3 mean_area   12.147059
## 4  max_area   21.000000
## 5   sd_area    2.085912
## 6  sum_area 2065.000000
ovos_cont <- 
  measure_disease(ovos,
                  index_lb = "HUE2",
                  index_dh = "GRAY",
                  invert = c(FALSE, TRUE),
                  threshold = c("Otsu", 0.7),
                  show_features = TRUE,
                  show_contour = FALSE,
                  col_lesions = "blue",
                  col_background = "black")

# apenas na versão de desenvolvimento
pick_count(ovos)

Mensuração iterativa

A função measure_disease_iter() fornece uma seção iterativa para measure_disease(), onde o usuário extrai amostras na imagem para criar as paletas de cores necessárias. measure_disease_iter() executa apenas em uma seção interativa. Nesta função, os usuários serão capazes extrair amostras de imagens para criar, iterativamente, as paletas de cores necessárias. Este processo chama pick_palette() internamente. Se has_background for TRUE (padrão), a paleta de cores do fundo é criada primeiro. A amostra de cores é realizada a cada clique com o botão esquerdo do mouse e continua até que o usuário pressione Esc. Em seguida, um novo processo de amostragem é realizado para amostrar a cor dos tecidos saudáveis e, em seguida, dos tecidos doentes. As paletas geradas são então passadas para measure_disease(). Todos os argumentos de tal função podem ser passados para measure_disease() usando ... (três pontos).

# somente roda em uma seção interativa
img <- image_pliman("sev_leaf.jpg", plot = TRUE)
measure_disease_iter(img)

Desafios

img <- image_import("maize_1.png", plot = TRUE)

image_segment(img, index = "all")

img <- image_import("maize_2.png", plot = TRUE)

image_segment(img, index = "all")

img2 <- image_crop(img,
                   width = 959:32,
                   height = 163:557,
                   plot = TRUE)


image_segment_iter(img2, 
                   nseg = 2, # define o número de segmentações
                   index = c("NR", "GLI"), # índices para primeira e segunda
                   invert = c(T, F), # inverter a segmentação? (passa um vetor)
                   ncol = 3) # número de colunas no plot
##      image  pixels   percent
## 1 original 1466240 100.00000
## 2     seg1   75147   5.12515
## 3     seg2   17325  23.05481

Previous