1st commit

This commit is contained in:
2026-06-08 20:00:40 -03:00
commit c81627b5ae
12 changed files with 1013 additions and 0 deletions

View File

@@ -0,0 +1,845 @@
import ee
import geemap
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import skimage.filters as filters
import random
import os
####################################################################################
Map = geemap.Map()
#################################################################################### MAIN FUNCTION
####################################################################################
####################################################################################
####################################################################################
def function_lc(ano_de_interesse, roi, path1, row1, porcentagem_nuvem_roi, caminho_excel_mares, nome_aba_excel, min_mare, max_mare,otsu_method,limiar_otsu):
#"dicionário"
start_dateNuv = ano_de_interesse
roi = roi
porcentagem_nuvem_roi = porcentagem_nuvem_roi
file_path = caminho_excel_mares
sheet_name = nome_aba_excel
# Definir o intervalo de datas para busca das imagens
end_dateNuv = start_dateNuv.advance(1, 'year')
# Determinar a coleção do Landsat com base na data
landsat_collection = ee.ImageCollection(
ee.Algorithms.If(
start_dateNuv.difference(ee.Date('2013-01-01'), 'year').gte(0),
ee.ImageCollection('LANDSAT/LC08/C02/T1_L2'), # Objeto Landsat 8
ee.ImageCollection('LANDSAT/LT05/C02/T1_L2') # Objeto Landsat 5
)
).filterDate(start_dateNuv, end_dateNuv) \
.filterBounds(roi) \
.filter(ee.Filter.lt('CLOUD_COVER', 100))
# Aplicar o fator de escala e o offset à coleção
landsat_collection = landsat_collection##.map(apply_scale_factor)
# Obter a primeira imagem da coleção
first_image = landsat_collection.first()
# Obter o ID da imagem e imprimir
image_id = first_image.get('system:id').getInfo()
#print(f"ID da imagem utilizada: {image_id}")
def cloud_coverage(image):
# Selecionar a banda de qualidade (QA_PIXEL) para identificar pixels de nuvens
qa = image.select('QA_PIXEL')
# Criar uma máscara para pixels de nuvens (bits 3 e 5 no QA_PIXEL)
cloud_mask = qa.bitwiseAnd(1 << 3).Or(qa.bitwiseAnd(1 << 5))
# Calcular a área total da ROI
total_area = roi.area()
# Calcular a área coberta por nuvens na ROI
cloud_area = cloud_mask.multiply(ee.Image.pixelArea()).reduceRegion(
reducer=ee.Reducer.sum(),
geometry=roi,
scale=30,
maxPixels=1e9
).get('QA_PIXEL')
# Calcular a área total da imagem
image_area = image.geometry().area()
# Calcular a área coberta por nuvens na imagem completa
image_cloud_area = cloud_mask.multiply(ee.Image.pixelArea()).reduceRegion(
reducer=ee.Reducer.sum(),
geometry=image.geometry(),
scale=30,
maxPixels=1e9
).get('QA_PIXEL')
# Calcular a porcentagem de cobertura de nuvens
cloud_percentage_roi = ee.Number(cloud_area).divide(total_area).multiply(100)
cloud_percentage_image = ee.Number(image_cloud_area).divide(image_area).multiply(100)
return image.set('cloud_coverage_roi', cloud_percentage_roi).set('cloud_coverage_image', cloud_percentage_image)
# Aplicar a função a cada imagem na coleção
landsat_with_cloud_coverage = landsat_collection.map(cloud_coverage)
# Recuperar os IDs das imagens e as porcentagens de cobertura de nuvens
image_ids2 = landsat_with_cloud_coverage.aggregate_array('system:id').getInfo()
cloud_percentages_roi = landsat_with_cloud_coverage.aggregate_array('cloud_coverage_roi').getInfo()
cloud_percentages_image = landsat_with_cloud_coverage.aggregate_array('cloud_coverage_image').getInfo()
# Definindo o intervalo de datas para busca das imagens
start_dateMar = start_dateNuv
end_dateMar = end_dateNuv
# Definir o path e row específicos para a Baía de Guanabara
path = path1
row = row1
# Carregar a coleção de imagens Landsat 8
landsat_collectionMar = landsat_with_cloud_coverage \
.filterDate(start_dateMar, end_dateMar) \
.filter(ee.Filter.eq('WRS_PATH', path)) \
.filter(ee.Filter.eq('WRS_ROW', row))
# Recuperar os IDs das imagens filtradas e as porcentagens de cobertura de nuvens na ROI
image_idsMar = landsat_collectionMar.aggregate_array('system:id').getInfo()
cloud_percentages_roiMar = landsat_collectionMar.aggregate_array('cloud_coverage_roi').getInfo()
# Função para extrair a data dos IDs das imagens
def extract_date_from_id(image_id):
date_str = image_id.split('_')[-1]
return pd.to_datetime(date_str, format='%Y%m%d')
# Criar um DataFrame com as datas das imagens e porcentagens de nuvens na ROI
image_dates_df = pd.DataFrame({
'image_id': image_idsMar,
'image_date': [extract_date_from_id(image_id) for image_id in image_idsMar],
'cloud_coverage_roi': cloud_percentages_roiMar
})
# Adicionar índice à coluna de data do DataFrame de imagens e garantir o tipo datetime
image_dates_df['image_date'] = pd.to_datetime(image_dates_df['image_date'])
image_dates_df.set_index('image_date', inplace=True)
# Carregar a tabela de marés a partir da planilha específica
tides_df = pd.read_excel(file_path, sheet_name=sheet_name)
# Converter a coluna 'Data' para datetime no DataFrame de marés e garantir o tipo correto
tides_df['Data'] = pd.to_datetime(tides_df['Data'], format='%d/%m/%Y')
# Filtrar os valores de marés entre 0,51 e 0,96 e a hora de 9h ## USANDO 0.59 e 1.03
filtered_tides_df = tides_df[
(tides_df['valor'] >= min_mare) &
(tides_df['valor'] <= max_mare) &
(tides_df['Horat'] == 9)
].copy()
# Adicionar índice à coluna de data do DataFrame de marés e garantir o tipo datetime
filtered_tides_df['Data'] = pd.to_datetime(filtered_tides_df['Data'])
filtered_tides_df.set_index('Data', inplace=True)
# Ordenar os DataFrames pelas datas (necessário para merge_asof)
image_dates_df.sort_index(inplace=True)
filtered_tides_df.sort_index(inplace=True)
# Combinar os DataFrames pelas datas usando merge_asof
combined_df = pd.merge_asof(
image_dates_df,
filtered_tides_df,
left_index=True,
right_index=True,
direction='nearest',
tolerance=pd.Timedelta('1D')
)
# Filtrar imagens com menos de x% de cobertura de nuvens na ROI
filtered_combined_df = combined_df[combined_df['cloud_coverage_roi'] < porcentagem_nuvem_roi] # USANDO 0.01
# Obter os IDs das imagens correspondentes, removendo os NaNs resultantes da junção
matching_image_ids = filtered_combined_df.dropna(subset=['valor'])['image_id'].tolist()
#print(matching_image_ids)
# Função para aplicar máscara de nuvens
def mask_l8_sr(image):
qa_mask = image.select('QA_PIXEL').bitwiseAnd(int('11111', 2)).eq(0) #11111
saturation_mask = image.select('QA_RADSAT').eq(0)
#optical_bands = image.select('SR_B.').multiply(0.0000275).add(-0.2)
#thermal_bands = image.select('ST_B.*').multiply(0.00341802).add(149.0) #.updateMask(qa_mask)
return image.updateMask(saturation_mask) \
.updateMask(qa_mask)
#.addBands(optical_bands, None, True) \
#.addBands(thermal_bands, None, True) \
# Carregar a coleção de imagens Landsat
landsat8 = landsat_collection
# Definir o ID da imagem base manualmente ##estou testando a coleção de SR
base_image_id = matching_image_ids[0]
# Selecionar a imagem base pelo ID
base_image = ee.Image(base_image_id)
# Função para determinar as bandas de visualização com base na coleção
def get_visualization_bands(image):
# Verificar a coleção da imagem (Landsat 8 ou Landsat 5)
if 'LC08' in image.get('system:id').getInfo():
# Definir as bandas para Landsat 8
return ['SR_B4', 'SR_B3', 'SR_B2'] # Red, Green, Blue
elif 'LT05' in image.get('system:id').getInfo():
# Definir as bandas para Landsat 5
return ['SR_B3', 'SR_B2', 'SR_B1'] # Red, Green, Blue
else:
# Caso a coleção não seja reconhecida
return []
# Obter as bandas para visualização automaticamente
visualization_bands = get_visualization_bands(base_image)
# Definir parâmetros de visualização
visualization = {
'bands': visualization_bands,
'min': 0,
'max': 0.2
}
# Aplicar a máscara de nuvens na imagem base
combined_image = base_image
# Período do mosaico de referência (base abaixo da imagem única)
start_date = start_dateNuv
end_date = end_dateNuv
# Filtrar e mascarar a coleção de imagens no período de referência
filtered_collection = landsat8.filterDate(start_date, end_date).filterBounds(roi).map(mask_l8_sr)
# Criar um mosaico mediano das imagens de referência
reference_mosaic = filtered_collection.median()
#reference_mosaic = reference_mosaic.select(reference_mosaic.bandNames()).multiply(0.0000275).add(-0.2)
# Função para preencher os pixels nublados da imagem base com o mosaico de referência
def fill_cloud_pixels(base, reference):
# Criar uma máscara para os pixels nublados
cloud_mask = base.mask().Not()
# Preencher os pixels nublados com os pixels do mosaico de referência
filled = base.unmask(reference)
return filled
# Preencher os pixels nublados da imagem base com o mosaico de referência
corrected_image = fill_cloud_pixels(combined_image, reference_mosaic)
comp = combined_image.clip(roi)
# Função para obter as bandas corretas dependendo da coleção de imagem (Landsat 5 ou Landsat 8)
def get_bands_for_mndwi(image):
# Verificar a coleção da imagem (Landsat 8 ou Landsat 5)
if 'LC08' in image.get('system:id').getInfo():
# Landsat 8: B3 (Green), B6 (SWIR), B5 (NIR), B4 (Red), B2 (Blue)
return {
'GREEN': image.select('SR_B3'),
'SWIR': image.select('SR_B6'),
'NIR': image.select('SR_B5'),
'RED': image.select('SR_B4'),
'BLUE': image.select('SR_B2')
}
elif 'LT05' in image.get('system:id').getInfo():
# Landsat 5: B2 (Green), B5 (SWIR), B4 (NIR), B3 (Red), B1 (Blue)
return {
'GREEN': image.select('SR_B2'),
'SWIR': image.select('SR_B5'),
'NIR': image.select('SR_B4'),
'RED': image.select('SR_B3'),
'BLUE': image.select('SR_B1')
}
else:
# Caso a coleção não seja reconhecida
return None
# Selecionar as bandas corretas para a imagem base
bands = get_bands_for_mndwi(comp)
# Verificar se as bandas foram corretamente identificadas
if bands:
# Calcular o MNDWI
mndwi = comp.expression(
'(GREEN - SWIR) / (GREEN + SWIR)',
bands
).rename('mndwi')
# Parâmetros de visualização para o MNDWI
mndwi_vis_params = {
'min': -1,
'max': 1,
'palette': ['00FFFF', '0000FF']
}
# Adicionar o MNDWI ao mapa
#Map.add_ee_layer(mndwi, mndwi_vis_params, 'MNDWI', 1)
else:
print('Coleção de imagem não reconhecida para MNDWI.')
#Map
# Obter uma coleção de pixels da imagem MNDWI
mndwi_pixels = mndwi.sample(roi, scale=30).reduceColumns(ee.Reducer.toList(), ['mndwi']).get('list')
# Converter a coleção de pixels em uma lista e, em seguida, em um array NumPy
mndwi_values = np.array(ee.List(mndwi_pixels).getInfo())
# selecao otsu
if otsu_method == "Otsu":
# Limiar único (duas classes)
otsu_threshold = filters.threshold_otsu(mndwi_values)
print("Otsu Threshold:", otsu_threshold)
## Imagem binária: mndwi > threshold => 1 (úmido); caso contrário, 0 (seco)
final_result_clip = mndwi.expression('mndwi > threshold ? 1 : 0', {
'mndwi':mndwi,
'threshold':otsu_threshold
}).rename('binary_mndwi').clip(roi)
# Também pode salvar o threshold para referência
first_threshold = otsu_threshold
# Criar imagem binária com base nesse limiar (igual acima)
binary_mndwi_first_threshold = final_result_clip.rename('binary_mndwi_first_threshold')
else:
# Multi-threshold com 3 classes (água, lama, continente)
otsu_thresholds = filters.threshold_multiotsu(mndwi_values, classes=3)
print("Otsu Thresholds:", otsu_thresholds)
binary_mndwi_classes = []
for i in range(len(otsu_thresholds) + 1):
if i == 0:
binary_class = mndwi.expression('mndwi <= threshold ? 1 : 0', {
'mndwi': mndwi,
'threshold': otsu_thresholds[i]
}).rename(f'binary_class_{i}') # Água
elif i == len(otsu_thresholds):
binary_class = mndwi.expression('mndwi > threshold ? 1 : 0', {
'mndwi': mndwi,
'threshold': otsu_thresholds[i - 1]
}).rename(f'binary_class_{i}') # Continente
else:
binary_class = mndwi.expression('mndwi > threshold_min && mndwi <= threshold_max ? 1 : 0', {
'mndwi': mndwi,
'threshold_min': otsu_thresholds[i - 1],
'threshold_max': otsu_thresholds[i]
}).rename(f'binary_class_{i}') # Lama
binary_mndwi_classes.append(binary_class)
# Combinar as classes em uma única imagem
final_result = ee.Image(binary_mndwi_classes[0]).multiply(0)
for i in range(len(binary_mndwi_classes)):
final_result = final_result.where(binary_mndwi_classes[i].eq(1), i)
final_result_clip = final_result.clip(roi)
# Primeiro limiar intermediário (água/solo exposto)
if limiar_otsu < len(otsu_thresholds):
first_threshold = otsu_thresholds[limiar_otsu]
else:
raise ValueError(f"limiar fora do intervado, existem apenas {len(otsu_thresholds)} limiares")
# Criar imagem binária com base no primeiro limiar
binary_mndwi_first_threshold = mndwi.expression('mndwi > threshold ? 1 : 0', {
'mndwi': mndwi,
'threshold': first_threshold
}).rename('binary_mndwi_first_threshold').clip(roi)
### daqui para frente será para o tratamento visual dos dados
## Selecionar a resolução que os resultados serão exportados mais tarde
# QUANTO MAIOR A RESOLUÇÃO MAIS SMOOTH O RESULTADO
expresm = 15
##será necessário add um limiar (threshold) também a resolução em m acima para elimiar erros e ilhas, por exemplo
# em caso de um corpo hídrico maior, ou falhas maiores, próximas a linha de costa que se imagina deve setar o valor maior
waterbodysizem = 5000 ## para o RJ usar cerca de 5000
islandsizem = 900 ## para o RJ usar cerca de 3000
##agora sera feito um def para binarizar a água e terra aplicando as duas o filtro de corpos hidricos e resolução.
def removerfalhas(water_image, waterbodysizem, islandsizem, expresm):
water_image = water_image.int()
#definir os próximos, a proximidade, com os parametros setados
pixland = ee.Number(waterbodysizem).divide(expresm).int()
pixwater = ee.Number(islandsizem).divide(expresm).int()
#remover corpos hidricos no continente
landfill = water_image.addBands(water_image)\
.reduceConnectedComponents(ee.Reducer.median(), 'binary_mndwi_first_threshold', pixland)\
.unmask(99).eq(99).And(water_image.neq(0))
# remover ilhas e erros pequenos
waterfill = landfill.addBands(landfill)\
.reduceConnectedComponents(ee.Reducer.median(), 'binary_mndwi_first_threshold_1', pixwater)\
.unmask(99).eq(99).And(landfill.neq(1))
#limite entre terra e agua com os limites já feitos acima
return waterfill
# binarizar e visualizar todos os dados feitos no bloco acima
limiteat = removerfalhas(binary_mndwi_first_threshold, waterbodysizem, islandsizem, expresm)
limitevis = {'min': 0, 'max': 1, 'palette': ['white', 'black']}
#converter a linha de costa do raster para um vetor
vetor = limiteat.selfMask() \
.reduceToVectors(
geometry=roi,
scale=expresm,
eightConnected=True,
maxPixels=1e20,
tileScale=16
)
#adicionar o produto em vetor ao mapa e verificar se esta correto.
Map.add_ee_layer(vetor, {'color': 'blue'}, 'aguavetor')
Map
# Polígono para linha
def extrair_linha_de_costa(vetor):
# Simplificar vetores
def feature(f):
coords = f.geometry().simplify(maxError=expresm).coordinates()
# Buffer - rasterizar
# o polígono de fronteira
buffer = ee.Number(expresm).multiply(-1)
return f.setGeometry(
ee.Geometry.MultiLineString(coords).intersection(roi.buffer(buffer))
)
vetores_processados = vetor.map(feature)
return vetores_processados
vetor_linha_de_costa = extrair_linha_de_costa(vetor);
Map.add_ee_layer(vetor_linha_de_costa, {'color': 'red'},'Linha de costa')
# Supondo que a variável 'imagem' seja a imagem do Landsat ou outro dataset com a data associada
imagem = comp # Substitua pelo ID correto
# Obter a data da imagem (ano)
data_imagem = imagem.get("system:time_start").getInfo()
ano_imagem = ee.Date(data_imagem).format("YYYY").getInfo() # Extrai o ano da imagem
# Calcular a área do ROI em metros quadrados e converter para km²
roi_area_m2 = roi.area().getInfo() # Área em metros quadrados
roi_area_km2 = roi_area_m2 / 1e6 # Converter para km²
#print(f"Área do ROI ({ano_imagem}): {roi_area_km2} km²")
# Calcular a área do vetor (linha de costa) com um erro de margem de 1 metro
vetor_area_m2 = vetor.geometry().area(maxError=1).getInfo() # Área em metros quadrados
vetor_area_km2 = vetor_area_m2 / 1e6 # Converter para km²
#print(f"Área do vetor (linha de costa) ({ano_imagem}): {vetor_area_km2} km²")
# Retornando o vetor e as áreas como um dicionário
return {
'vetor': vetor,
'vetor_lc': vetor_linha_de_costa,
'area_vetor': f"Área do vetor (linha de costa) ({ano_imagem}): {vetor_area_km2} km²",
'area_roi': f"Área do ROI ({ano_imagem}): {roi_area_km2} km²",
'composite': comp,
'mndwi': mndwi,
'thresholds': otsu_threshold if otsu_method == "Otsu" else otsu_thresholds,
'mndwi_values': mndwi_values, # array numpy
'imagem_binarizada': binary_mndwi_first_threshold if otsu_method == "Otsu" else binary_mndwi_classes,
}
#################################################################################### TIDE FUNCTION
####################################################################################
####################################################################################
####################################################################################
def estatisticas_mare(caminho_excel_mares, nome_aba_excel):
"""
Carrega uma planilha de marés, calcula estatísticas descritivas e imprime os resultados.
Parâmetros:
file_path (str): Caminho para o arquivo Excel - entre aspas simples.
sheet_name (str): Nome da aba da planilha que contém os dados - entre aspas simples.
"""
#"dicionário"
file_path = caminho_excel_mares
sheet_name = nome_aba_excel
# Carregar a tabela de marés a partir da planilha especificada
tides_df = pd.read_excel(file_path, sheet_name=sheet_name)
# Calcular as estatísticas descritivas para a coluna 'valor'
summary_stats = tides_df['valor'].describe(percentiles=[0.25, 0.5, 0.75])
# Renomear as colunas
summary_stats = summary_stats.rename({
'min': 'Min.',
'25%': '1st Qu.',
'50%': 'Median',
'mean': 'Mean',
'75%': '3rd Qu.',
'max': 'Max.'
})
# Selecionar e reordenar as colunas
summary_stats = summary_stats[['count', 'Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.']]
# Imprimir as estatísticas descritivas
print(summary_stats)
##################################################################################### RESULTS LINHAS loop
#####################################################################################
#####################################################################################
#####################################################################################
def linha_de_costa_loop(ano_inicial, ano_final, function_lc, roi, path1, row1, porcentagem_nuvem_roi, caminho_excel_mares, nome_aba_excel, min_mare, max_mare, Map, otsu_method, limiar_otsu):
"""
Processa imagens para um intervalo de anos e gera resultados com cores aleatórias.
Parâmetros:
start_year (int): Ano inicial para o processamento.
end_year (int): Ano final para o processamento (exclusivo).
processar_imagens (function): Função que processa imagens e retorna resultados.
roi (object): Região de interesse.
path1, row1 (int): Caminho e linha da imagem.
porcentagem_nuvem_roi (float): Porcentagem máxima de nuvem permitida na ROI.
file_path (str): Caminho do arquivo de entrada.
sheet_name (str): Nome da planilha no arquivo.
min_mare, max_mare (float): Limites mínimos e máximos da maré.
Map (object): Mapa interativo para adicionar camadas.
otsu_method (str): Método de Otsu (Multi_Otsu ou Otsu).
limiar_otsu (float): Valor de limiar pré-definido para Otsu, se aplicável. [0] = primeiro limiar
Retorna:
dict: Dicionários contendo resultados por ano, áreas do vetor e áreas do ROI.
"""
#"dicionário de argumentos"
start_year = ano_inicial
end_year = ano_final
file_path = caminho_excel_mares
sheet_name = nome_aba_excel
# Dicionários para armazenar os vetores, áreas e as linhas de costa
resultados_por_ano = {}
areas_vetor = {}
areas_roi = {}
linhas_de_costa = {} # Dicionário para armazenar as linhas de costa por ano
# Função para gerar uma cor aleatória no formato hexadecimal
def gerar_cor_aleatoria():
return "#{:06x}".format(random.randint(0, 0xFFFFFF))
# Loop para processar imagens de start_year até end_year
for ano in range(start_year, end_year):
try:
# Define a data de início como o primeiro dia de janeiro do ano
data_inicio = ee.Date(f'{ano}-01-01')
# Chama a função processar_imagens com todos os argumentos necessários
resultado = function_lc(data_inicio, roi, path1, row1, porcentagem_nuvem_roi, file_path, sheet_name, min_mare, max_mare, otsu_method, limiar_otsu)
# Armazena o vetor e as áreas no dicionário
resultados_por_ano[ano] = resultado
areas_vetor[ano] = resultado['area_vetor']
areas_roi[ano] = resultado['area_roi']
# Armazenar a linha de costa no dicionário
if 'vetor_lc' in resultado:
linhas_de_costa[ano] = resultado['vetor_lc'] # Adicionando a linha de costa ao dicionário
# Gera uma cor aleatória para o ano
cor_aleatoria = gerar_cor_aleatoria()
# Adiciona o vetor ao mapa com a cor gerada aleatoriamente
#if 'vetor' in resultado and isinstance(resultado['vetor'], (ee.FeatureCollection, ee.Feature, ee.Geometry)):
#Map.add_layer(resultado['vetor'], {'color': cor_aleatoria, 'width': 2}, f'Vetor {ano} ({cor_aleatoria})')
#else:
#print(f"Vetor inválido ou não encontrado para o ano {ano}")
# Adiciona a linha de costa ao mapa
if ano in linhas_de_costa:
Map.add_layer(linhas_de_costa[ano], {'color': cor_aleatoria, 'width': 3}, f'Linha de Costa {ano} ({cor_aleatoria})')
# Exibe as informações de área no console
print(f"Ano: {ano} - Área do vetor: {resultado['area_vetor']} ")
print(f"Ano: {ano} - Área do ROI: {resultado['area_roi']} ")
except Exception as e:
# Se ocorrer um erro, imprime uma mensagem e pula para o próximo ano
print(f"Erro ao processar o ano {ano}: {e}")
continue # Pula para o próximo ano
# Retorna os resultados incluindo as linhas de costa
return resultados_por_ano, areas_vetor, areas_roi, linhas_de_costa # Retorno com 'linhas_de_costa'
#################################################################################### RESULTS area loop
####################################################################################
####################################################################################
####################################################################################
def area_linha_de_costa_loop(ano_inicial, ano_final, function_lc, roi, path1, row1, porcentagem_nuvem_roi, caminho_excel_mares, nome_aba_excel, min_mare, max_mare, Map):
"""
Processa imagens para um intervalo de anos e gera resultados com cores aleatórias.
Parâmetros:
start_year (int): Ano inicial para o processamento.
end_year (int): Ano final para o processamento (exclusivo).
processar_imagens (function): Função que processa imagens e retorna resultados.
roi (object): Região de interesse.
path1, row1 (int): Caminho e linha da imagem.
porcentagem_nuvem_roi (float): Porcentagem máxima de nuvem permitida na ROI.
file_path (str): Caminho do arquivo de entrada.
sheet_name (str): Nome da planilha no arquivo.
min_mare, max_mare (float): Limites mínimos e máximos da maré.
Map (object): Mapa interativo para adicionar camadas.
Retorna:
dict: Dicionários contendo resultados por ano, áreas do vetor e áreas do ROI.
"""
#"dicionário de argumentos"
start_year = ano_inicial
end_year = ano_final
file_path = caminho_excel_mares
sheet_name = nome_aba_excel
# Dicionários para armazenar os vetores, áreas e as linhas de costa
resultados_por_ano = {}
areas_vetor = {}
areas_roi = {}
linhas_de_costa = {} # Dicionário para armazenar as linhas de costa por ano
# Função para gerar uma cor aleatória no formato hexadecimal
def gerar_cor_aleatoria():
return "#{:06x}".format(random.randint(0, 0xFFFFFF))
# Loop para processar imagens de start_year até end_year
for ano in range(start_year, end_year):
try:
# Define a data de início como o primeiro dia de janeiro do ano
data_inicio = ee.Date(f'{ano}-01-01')
# Chama a função processar_imagens com todos os argumentos necessários
resultado = function_lc(data_inicio, roi, path1, row1, porcentagem_nuvem_roi, file_path, sheet_name, min_mare, max_mare)
# Armazena o vetor e as áreas no dicionário
resultados_por_ano[ano] = resultado
areas_vetor[ano] = resultado['area_vetor']
areas_roi[ano] = resultado['area_roi']
# Armazenar a linha de costa no dicionário
if 'vetor_lc' in resultado:
linhas_de_costa[ano] = resultado['vetor_lc'] # Adicionando a linha de costa ao dicionário
# Gera uma cor aleatória para o ano
cor_aleatoria = gerar_cor_aleatoria()
# Adiciona o vetor ao mapa com a cor gerada aleatoriamente
if 'vetor' in resultado and isinstance(resultado['vetor'], (ee.FeatureCollection, ee.Feature, ee.Geometry)):
Map.add_layer(resultado['vetor'], {'color': cor_aleatoria, 'width': 2}, f'Vetor {ano} ({cor_aleatoria})')
else:
print(f"Vetor inválido ou não encontrado para o ano {ano}")
# Adiciona a linha de costa ao mapa
#if ano in linhas_de_costa:
#Map.add_layer(linhas_de_costa[ano], {'color': cor_aleatoria, 'width': 3}, f'Linha de Costa {ano} ({cor_aleatoria})')
# Exibe as informações de área no console
print(f"Ano: {ano} - Área do vetor: {resultado['area_vetor']} km²")
print(f"Ano: {ano} - Área do ROI: {resultado['area_roi']} km²")
except Exception as e:
# Se ocorrer um erro, imprime uma mensagem e pula para o próximo ano
print(f"Erro ao processar o ano {ano}: {e}")
continue # Pula para o próximo ano
# Retorna os resultados incluindo as linhas de costa
return resultados_por_ano, areas_vetor, areas_roi, linhas_de_costa # Retorno com 'linhas_de_costa'
#################################################################################### VIZUALIZACAO do processamento
####################################################################################
####################################################################################
def visualizar_composite(ano_de_interesse, roi, path1, row1, porcentagem_nuvem_roi,
caminho_excel_mares, nome_aba_excel, min_mare, max_mare,
otsu_method, limiar_otsu, Map):
"""
Visualiza os dados para um ano específico, incluindo RGB, MNDWI, binário e histograma.
Parâmetros:
ano_de_interesse (int): Ano a ser visualizado.
roi (ee.Geometry): Região de interesse.
path1, row1 (int): Path e Row da cena Landsat.
porcentagem_nuvem_roi (float): Limite de nuvens.
caminho_excel_mares (str): Caminho para o Excel de marés.
nome_aba_excel (str): Aba do Excel.
min_mare, max_mare (float): Intervalo de maré permitido.
otsu_method (str): 'Otsu' ou 'Multi_Otsu'.
limiar_otsu (int): Limiar a ser utilizado.
Map (geemap.Map): Objeto de mapa interativo.
"""
import matplotlib.pyplot as plt
# Executa a função principal
resultado = function_lc(
ano_de_interesse=ano_de_interesse,
roi=roi,
path1=path1,
row1=row1,
porcentagem_nuvem_roi=porcentagem_nuvem_roi,
caminho_excel_mares=caminho_excel_mares,
nome_aba_excel=nome_aba_excel,
min_mare=min_mare,
max_mare=max_mare,
otsu_method=otsu_method,
limiar_otsu=limiar_otsu
)
# Extrai os resultados
composite = resultado['composite']
mndwi = resultado['mndwi']
binarizada = resultado['imagem_binarizada']
valor_otsu = resultado['thresholds']
mndwi_values = resultado['mndwi_values'] # array numpy com os valores do MNDWI
# Adiciona ao mapa RGB
vis_rgb = {
'bands': ['SR_B4', 'SR_B3', 'SR_B2'],
'min': 0,
'max': 0.3,
'gamma': 1.2
}
Map.add_layer(composite.clip(roi), vis_rgb, f'RGB {ano_de_interesse.get("year").getInfo()}')
# Adiciona MNDWI
Map.add_layer(mndwi.clip(roi), {'min': -1, 'max': 1, 'palette': ['purple', 'white', 'green']}, f'MNDWI {ano_de_interesse.get("year").getInfo()}')
# Adiciona imagem binarizada
Map.add_layer(binarizada.clip(roi), {'min': 0, 'max': 2, 'palette': ['brown', 'yellow', 'blue']}, f'Binarizada {ano_de_interesse.get("year").getInfo()}')
# Gera histograma com matplotlib a partir dos valores do MNDWI
plt.figure(figsize=(10, 5))
plt.hist(mndwi_values, bins=50, color='gray', edgecolor='black')
plt.title(f'Histograma do MNDWI - Ano {ano_de_interesse.get("year").getInfo()}')
plt.xlabel('Valor MNDWI')
plt.ylabel('Contagem de Pixels')
# Adiciona os limiares
if isinstance(valor_otsu, list):
for i, v in enumerate(valor_otsu):
plt.axvline(x=v, color='red', linestyle='--', label=f'Limiar {i+1} = {v:.2f}')
else:
plt.axvline(x=valor_otsu, color='red', linestyle='--', label=f'Limiar = {valor_otsu:.2f}')
plt.legend()
plt.grid(True)
plt.show()
#################################################################################### EXPORTS Areas e/ou Linhas
####################################################################################
####################################################################################
####################################################################################
def exportar_resultados(resultados_lc, caminho_saida, exportar_linhas=True, exportar_vetores=True):
"""
Função para exportar os resultados (vetores ou linhas de costa) para o Google Drive
e criar uma tabela de áreas em formato Excel.
Parâmetros:
resultados_teste (tuple): Tupla com os resultados do processamento, contendo os vetores e áreas por ano.
output_path (str): Caminho para a pasta de saída no Google Drive.
exportar_linhas (bool): Se True, exporta as linhas de costa. Default é True.
exportar_vetores (bool): Se True, exporta os vetores de área. Default é True.
Retorna:
list: Lista de tarefas de exportação para execução no Google Earth Engine.
"""
# "dicionário de argumentos"
resultados_teste = resultados_lc
output_path = caminho_saida
# Inicializa uma lista para acumular os dados de área
tabela_acumulada = []
# Lista para armazenar as tarefas de exportação
export_tasks = []
# Extrai os resultados dos anos (considerando que resultados_teste é uma tupla com a estrutura correta)
resultados_por_ano, _, _, _ = resultados_teste # Desempacotando a tupla
# Percorrer os resultados do teste por ano
for ano, resultado in resultados_por_ano.items():
try:
# Verifica se o vetor está presente para o ano
area_vetor = resultado['area_vetor']
area_roi = resultado['area_roi']
# Acumula os dados da tabela para o ano
tabela_acumulada.append({
'Ano': ano,
'Área do vetor (km²)': area_vetor,
'Área do ROI (km²)': area_roi
})
# Exportar o vetor como SHP (caso o usuário tenha escolhido exportar vetores)
if exportar_vetores:
vetor = resultado['vetor']
export_vetor = ee.FeatureCollection(vetor)
export_task_vetor = ee.batch.Export.table.toDrive(
collection=export_vetor,
description=f'vetor_{ano}_linha_de_costa',
fileFormat='SHP',
folder=output_path # Usando o caminho definido pelo usuário
)
export_task_vetor.start() # Inicia a tarefa de exportação
export_tasks.append(export_task_vetor)
# Exportar a linha de costa como SHP (caso o usuário tenha escolhido exportar linhas)
if exportar_linhas:
vetor_lc = resultado['vetor_lc']
export_linha = ee.FeatureCollection(vetor_lc)
export_task_linha = ee.batch.Export.table.toDrive(
collection=export_linha,
description=f'linha_de_costa_{ano}',
fileFormat='SHP',
folder=output_path # Usando o caminho definido pelo usuário
)
export_task_linha.start() # Inicia a tarefa de exportação
export_tasks.append(export_task_linha)
except Exception as e:
print(f"Erro ao processar o ano {ano}: {e}")
# Criar DataFrame com os dados acumulados
df_tabela = pd.DataFrame(tabela_acumulada)
# Exporta a tabela com as informações de área como arquivo Excel
tabela_path = f"{output_path}/tabela_areas_total.xlsx"
df_tabela.to_excel(tabela_path, index=False)
# Retorna as tarefas de exportação para execução no Google Earth Engine
return export_tasks
####################################################################################
# Em caso de problema ou dúvida procurar por Pablo Simões no contato abaixo:
# pablosergio.simoes@gmail.com / pablosimoes@id.uff.br