Na aula de hoje iremos precisar dos pacotes a seguir. Então, antes de iniciar, realizem a instalação dos pocotes e o carregamento dos mesmos, como instruído no código a seguir.
Antes de darmos início ao trabalho, vamos conferir se estamos trabalhando no diretório correto (pasta de trabalho).
## [1] "C:/ARQUIVOS COMPUTADOR/DOUTORADO/APOSTILA PROCESSAMENTO DIGITAL DE IMAGENS"
Com os pacotes instalados e carregados, vamos carregar novamente os arquivos que utilizamos na semana passada (imagem orbital e imagem orbital recortada). Utilizaremos os mesmos arquivos, portanto, o código a seguir é o mesmo da semana passada. Portanto, utilizaremos o arquivo CBERS_4_MUX_20231228_156_123_L4_BAND8.tif, imagem orbital disponibilizada pelo INPE, no acervo digital da instituição. Para o carregamento, a função será raster() com a especificação do nome do arquivo na pasta de trabalho. Após o carregamento, seguimos o mesmo procedimento de recorte da imagem, focalizando em uma área aleatoriamente definida dentro da imagem orbital.
#Carregamento da imagem orbital
imagem_orbital <- raster("CBERS_4_MUX_20231228_156_123_L4_BAND8.tif")
#Definindo a extensão geográfica da área de interesse
aoi_extent <- extent(c(xmin = 196940 , xmax = 216940 , ymin = 7723010 , ymax = 7743010 ))
#Recortando a área de interesse
imagem_recortada <- crop(imagem_orbital, extent(aoi_extent))Realizado o recorte da imagem orbital, passamos à classificação. A seguir estão expressos os mesmos comando da semana anterior, somente para realizarmos a classificação.
# Obter os valores dos pixels
valores_pixels <- raster::extract(imagem_recortada, raster::extent(imagem_recortada), buffer = 500)
# Normalizar os valores
valores_normalizados <- scale(valores_pixels)
# Remover valores ausentes dos dados normalizados
valores_normalizados[is.na(valores_normalizados)] <- 0
# Ajustar o número de clusters para 7
num_clusters <- 7
# Realizar a clusterização com k-means
kmeans_result <- kmeans(valores_normalizados, centers = num_clusters)
# Atribuir rótulos aos clusters
rotulos_clusters <- kmeans_result$cluster
# Atribuir rótulos aos pixels
valores_atribuidos <- matrix(rotulos_clusters, ncol = ncol(imagem_recortada), nrow = nrow(imagem_recortada), byrow = TRUE)
imagem_agrupada <- setValues(imagem_recortada, valores_atribuidos)
# Visualizar a imagem original e a imagem agrupada
par(mfrow=c(1, 2))
plot(imagem_recortada, main = "Imagem Original")
plot(imagem_agrupada, col = brewer.pal(num_clusters, "Set3"), main = "Imagem Agrupada")
Até aqui nenhuma novidade foi apresentada, mas precisamos deste material
para dar continuidade à prática de hoje: Histogramas: quantização e
amostragem. Nela vamos trazer alguns formatos para tal:
histogramas, gráficos de caixas ou gráficos de densidade, os
quais são úteis para examinar a distribuição dos valores de cada uma das
classes (valores entre 0 e 255 que vimos na escala de cores).
Estes gráficos são úteis para analisar a distribuição dos valores (escala de cores) entre as classes (lembrando que definimos 7 classes na semana passada), oferecendo insights sobre padrões e variações nas diferentes classes.
#Supondo que a imagem agrupada já foi criada e é representada por "imagem_agrupada" e que os rótulos dos grupos estão na variável "rotulos_clusters"
#Converter a imagem agrupada para um dataframe
df_imagem <- as.data.frame(imagem_agrupada)
df_imagem$Classe <- factor(rotulos_clusters)
#Melt para formato longo
#A função melt é utilizada para converter os dados do formato largo para o formato longo, permitindo uma manipulação e análise mais flexíveis dos dados. Neste contexto específico, a função melt foi usada para transformar a imagem agrupada de formato largo para longo antes de criar os gráficos de densidade separados para cada classe.
df_melted <- melt(df_imagem, id.vars = "Classe", variable.name = "Pixel", value.name = "Valor")
# Criar gráfico de densidade para cada classe com a paleta de cores
ggplot(df_melted, aes(x = Valor, fill = Classe)) +
geom_density(alpha = 0.5) +
labs(title = "Distribuição dos Valores por Classe",
x = "Valor",
y = "Densidade") +
theme_minimal() +
scale_fill_brewer(palette = "Set3")Em contexto de imagens orbitais ou raster, um histograma é uma representação gráfica da distribuição dos valores dos pixels na imagem. Ele exibe a frequência com que diferentes faixas de valores ocorrem. Cada barra no histograma representa um intervalo de valores, e a altura da barra indica quantos pixels na imagem têm valores dentro desse intervalo.
No caso específico de imagens orbitais, o histograma pode oferecer insights sobre a distribuição de intensidades de pixel na imagem. Isso é útil para entender a variação de tons na imagem e pode ser usado para identificar padrões, características específicas ou até mesmo para realizar pré-processamento, como ajuste de contraste.
Ao criar um histograma, é possível observar se a distribuição dos valores é uniforme, se existe uma tendência predominante ou se há picos que indicam a presença de determinadas características na imagem.
Em um primeiro momento, vamos tentar criar nosso histograma somente com as informações constantes na imagem recortada e classificada. Neste caso, vamos desconsiderar a nossa classificação em 7 grupos para ver o que acontece. Usaremos Set3 como padrão de cores (o mesmo que estamos usando desde o início da aula), o qual aceita até 12 cores como padrão.
# Supondo que a imagem recortada já foi carregada e é representada por "imagem_recortada"
# Obter os valores dos pixels
valores_pixels <- raster::extract(imagem_recortada, raster::extent(imagem_recortada), buffer = 500)
# Criar um data frame para o histograma
df_histograma <- data.frame(Valor = valores_pixels)
# Criar o histograma
ggplot(df_histograma, aes(x = Valor, fill = factor(Valor))) +
geom_histogram(binwidth = 1, alpha = 0.7, position = "identity") +
labs(title = "Histograma da Imagem Recortada",
x = "Valor do Pixel",
y = "Frequência") +
theme_minimal() +
scale_fill_brewer(palette = "Set3")## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_bin()`).
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Set3 is 12
## Returning the palette you asked for with that many colors
Ao executarmos o código sem classificação (agrupamento cluster), notamos que ocorre um aviso. Isto ocorre porque Set3 aceita 12 cores apenas e nós temos, na imagem orbital, um gradiente muito diverso de cores.
Assim, vamos fazer duas considerações (ajustes). O primeiro vai ser considerando os nossos grupos (cluster) na construção do histograma. O código a seguir ilustra este formato.
# Supondo que a imagem recortada já foi carregada e é representada por "imagem_recortada"
# Obter os valores dos pixels
valores_pixels <- raster::extract(imagem_recortada, raster::extent(imagem_recortada), buffer = 500)
# Atribuir rótulos aos pixels
valores_atribuidos <- matrix(rotulos_clusters, ncol = ncol(imagem_recortada), nrow = nrow(imagem_recortada), byrow = TRUE)
# Criar um data frame para o histograma
df_histograma <- data.frame(Valor = valores_pixels, Classe = as.factor(valores_atribuidos))
# Remover valores não finitos
df_histograma <- na.omit(df_histograma)
# Criar o histograma com a paleta de cores "Set3"
ggplot(df_histograma, aes(x = Valor, fill = Classe)) +
geom_histogram(binwidth = 1, alpha = 0.7, position = "identity") +
labs(title = "Histograma da Imagem Recortada por Classe",
x = "Valor do Pixel",
y = "Frequência") +
theme_minimal() +
scale_fill_brewer(palette = "Set3")Este é nosso histograma com as classes. Para facilitar a visualização, vamos separar o histograma de cada classe na sequência.
# Criar visualizações separadas para cada classe
for (classe in unique(df_histograma$Classe)) {
df_classe <- subset(df_histograma, Classe == classe)
# Criar o histograma mantendo as cores automáticas do ggplot2
p <- ggplot(df_classe, aes(x = Valor)) +
geom_histogram(binwidth = 1, alpha = 0.7) +
labs(title = paste("Histograma - Classe", classe),
x = "Valor do Pixel",
y = "Frequência") +
theme_minimal()
# Salvar cada gráfico em um arquivo separado
ggsave(paste("histograma_classe_", classe, ".png", sep = ""), plot = p, device = "png", width = 6, height = 4)
}O segundo, vamos tentar realizar a construção do histograma sem determinar a paleta de cores (Set3) para analisarmos os resultados. Acompanhe na sequência.
# Supondo que a imagem recortada já foi carregada e é representada por "imagem_recortada"
# Obter os valores dos pixels
valores_pixels <- raster::extract(imagem_recortada, raster::extent(imagem_recortada), buffer = 500)
# Remover valores não finitos
valores_pixels <- na.omit(valores_pixels)
# Criar um data frame para o histograma
df_histograma <- data.frame(Valor = valores_pixels)
# Criar o histograma
ggplot(df_histograma, aes(x = Valor, fill = factor(Valor))) +
geom_histogram(binwidth = 1, alpha = 0.7, position = "identity") +
labs(title = "Histograma da Imagem Recortada",
x = "Valor do Pixel",
y = "Frequência") +
theme_minimal() +
scale_fill_viridis(discrete = TRUE)Os gráficos de caixa (ou boxplots) são uma forma de visualização estatística que fornece uma representação compacta da distribuição de um conjunto de dados. Eles são úteis para visualizar a variação e a distribuição dos dados, destacando características como a mediana, quartis e a presença de possíveis valores atípicos.
A estrutura básica de um gráfico de caixa inclui:
Caixa (Box): Representa o intervalo interquartil (IQR), que contém a maioria dos dados. A caixa é dividida em quartis, com a linha interna representando a mediana.
Bigodes (Whiskers): Linhas que se estendem para fora da caixa até um determinado limite. Podem indicar a extensão total dos dados ou serem limitados por valores específicos.
Outliers: Pontos fora dos limites dos bigodes, que podem indicar valores atípicos ou extremos.
Um gráfico de caixa é útil para identificar a dispersão dos dados e verificar a presença de valores atípicos. Pode ser gerado para cada classe ou grupo em um conjunto de dados para comparações visuais.Então vamos a análise da nossa imagem classificada através de boxplot.
ggplot(df_melted, aes(x = Classe, y = Valor, fill = factor(Classe))) +
geom_boxplot(alpha = 0.7) +
geom_jitter(aes(color = factor(Classe)), position = position_jitter(0.2), alpha = 0.5) + # Adicionar pontos com cor
labs(title = "Boxplot da Imagem Agrupada",
x = "Classe",
y = "Valor do Pixel") +
theme_minimal() +
scale_fill_viridis(discrete = TRUE) +
scale_color_viridis(discrete = TRUE) # Adicionar escala de cores para os pontosCom base no nosso histograma das 7 classes, vamos realizar algumas métricas estatísticas para analisá-lo. Começaremos com a média, como abordamos no código a seguir.
# Criar um data frame com os valores e classes
dados <- data.frame(Valor = valores_pixels, Classe = rotulos_clusters)
# Remover linhas com valores NA
dados <- na.omit(dados)
# Calcular a média por classe
media_por_classe <- tapply(dados$Valor, dados$Classe, mean)
# Exibir a média por classe
print(media_por_classe)## 1 2 3 4 5 6 7
## 121.63670 92.81795 175.69057 69.32225 107.55858 139.89789 35.24704
Os resultados acima representam as médias por classe. Agora vamos calcular os valores da mediana.
# Calcular a mediana por classe
mediana_por_classe <- tapply(dados$Valor, dados$Classe, median)
# Exibir a mediana por classe
print(mediana_por_classe)## 1 2 3 4 5 6 7
## 121 94 171 71 108 138 34
Os resultados apenas apresentados referem-se às medianas das classes. Outra métrica relevante é a variância, vamos ao cálculo.
# Calcular a variância por classe
variancia_por_classe <- tapply(dados$Valor, dados$Classe, var)
# Exibir a variância por classe
print(variancia_por_classe)## 1 2 3 4 5 6 7
## 20.13221 27.69104 289.19312 75.90209 15.84376 51.28896 97.58279
# Criar o data frame
tabela_estatisticas <- data.frame(
Classe = 1:7,
Mediana = mediana_por_classe,
Media = media_por_classe,
Variancia = variancia_por_classe
)
# Mostrar a tabela
print(tabela_estatisticas)## Classe Mediana Media Variancia
## 1 1 121 121.63670 20.13221
## 2 2 94 92.81795 27.69104
## 3 3 171 175.69057 289.19312
## 4 4 71 69.32225 75.90209
## 5 5 108 107.55858 15.84376
## 6 6 138 139.89789 51.28896
## 7 7 34 35.24704 97.58279
Estes valores representam a variância por classe. Com os três padrões gráficos e alguns exemplos de métricas estatísticas associadas às imagens orbitais, encerramos nossa prática de hoje. Vimos como gerar histogramas, gráficos de densidade e boxplots dentro do R para a quantização e amostragem dos dados provenientes das imagens orbitais e como usar algumas métricas para extrair informações sobre as imagens orbitais.
ANDERSON, E. C. Making Maps with R Â: Reproducible Research. GitHub, 2021. Disponível em: https://eriqande.github.io/rep-res-web/lectures/making-maps-with-R.html.
CHAMBERS, J. M. Extending R. CRC Press, 364p., 2017. ISBN: 9781498775724.
DA SILVA, F. R.; GONÇALVES-SOUZA, T.; PATERNO, G. B.; PROVETE, D. B.; VANCINE, M. H. Análises ecológicas no R. Recife, PE: Nupeea, 1ª ed., 640p., 2022. ISBN: 9788579175640. Disponível em: https://analises-ecologicas.com/.
GAUTHIER, N. Anthromes 12K DGG (V1) analysis code and R research compendium. Harvard Dataverse, 2021. DOI: https://doi.org/10.7910/DVN/6FWPZ9.
LOVELACE, R. Introduction to visualizing spatial data in R. 2017. Disponível em:https://github.com/Robinlovelace/Creating-maps-in-R.
LOVELACE, R., NOWOSAD, J., & MUENCHOW, J. Geocomputation with R. Chapman and Hall/CRC, 353p., 2019. Disponível em: https://www.routledge.com/Geocomputation-withR/Lovelace-Nowosad-Muenchow/p/book/9780367670573
MACHLIS, S. Create maps in R in 10 (fairly) easy steps. Computerworld, 2017. Disponível em: https://www.computerworld.com/article/3038270/create-maps-in-r-in-10-fairly-easy-steps.html.
MARTOS, G. Cluster Analysis with R. 2021. Disponível em: https://rstudio-pubsstatic.s3.amazonaws.com/33876_1d7794d9a86647ca90c4f182df93f0e8.html.
MENESES, P. R.; ALMEIDA, T. D.; ROSA, A. N. D. C. S.; SANO, E. E. et al. Introdução ao Processamento de Imagens de Sensoriamento Remoto. Brasília: UnB-CNPq, 276 p., 2012.
MORENO, M. & BASILLE, M. Drawing beautiful maps programmatically with R, sf and ggplot2 - Part 1: Basics. 2021. Disponível em: https://r-spatial.org/r/2018/10/25/ggplot2-sf.html.
MUENCHOW, J.; SCHRATZ, P.; BRENNING, A. RQGIS: Integrating R with QGIS for Statistical Geocomputing. The R Journal, 9, n. 2, p. 409-428, 2017 2017. Doi: https://doi.org/10.32614/RJ-2017-067.
NOVIA, D. Cluster Analysis in R: Tips for Great Analysis and Visualization. Datanovia, 2018.Disponível em: https://www.datanovia.com/en/blog/cluster-analysis-in-r-simplified-and-enhanced/.
PEBESMA, E.; BIVAND, R. Spatial Data Science: With Applications in R. Chapman and Hall/CRC, 1ª ed., 314p., 2023. Doi: https://doi.org/10.1201/9780429459016.
R-BLOGGERS. Cluster Analysis in R. 2021. Disponível em: https://www.rbloggers.com/2021/04/cluster-analysis-in-r/.
STANIAK, M.; BIECEK, P. The Landscape of R Packages for Automated Exploratory Data Analysis. The R Journal, v. 11, n. 2, 23 p., 2019. Disponível em: https://arxiv.org/pdf/1904.02101.
VENABLES, W. N.; SMITH, D. M. An Introduction to R. R Core Team, 2017. Disponível em: http://colinfay.me/intro-to-r/#.
WICKHAM, H. Advanced R. CRC Press, 2ª ed., 2022. Disponível em: https://advr.hadley.nz/#license
:::