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

36
LAGEF_UFF/__init__.py Normal file
View File

@@ -0,0 +1,36 @@
import ee
def autenticar_gee(project: str):
"""
Autentica e inicializa o Google Earth Engine (GEE) com o projeto fornecido.
Args:
project (str): Nome do projeto no GEE.
Raises:
Exception: Caso a autenticação falhe.
"""
try:
ee.Authenticate()
ee.Initialize(project=project)
print(f"Autenticação bem-sucedida com o projeto: {project}")
except Exception as e:
raise Exception(f"Erro na autenticação ou inicialização do GEE: {e}")
# Solicita que o usuário insira o nome do projeto no momento da importação
try:
project_name = input("Insira o nome do seu projeto no Google Earth Engine: ")
autenticar_gee(project_name)
except Exception as e:
raise ImportError(f"Erro ao autenticar o Google Earth Engine: {e}")
# Importa as funções da biblioteca
from .LAGEF_UFF_Shoreline import (
function_lc,
estatisticas_mare,
area_linha_de_costa_loop,
linha_de_costa_loop,
exportar_resultados,
visualizar_composite
)

View File

@@ -0,0 +1,31 @@
Metadata-Version: 2.4
Name: LAGEF-UFF-Shoreline
Version: 0.1.0
Summary: Scripts para análise de linha de costa - Lagef UFF - projeto IVC
Author: Pablo Simoes
Author-email: ['pablosergio.simoes@gmail.com', 'pablosimoes@id.uff.br']
License: MIT License
Keywords: lagef uff,linha de costa,shoreline,google earth engine
Description-Content-Type: text/markdown
License-File: LICENCE
Requires-Dist: pandas
Requires-Dist: geemap
Requires-Dist: numpy
Requires-Dist: earthengine-api
Requires-Dist: scikit-image
Requires-Dist: matplotlib
Dynamic: author
Dynamic: author-email
Dynamic: description
Dynamic: description-content-type
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: requires-dist
Dynamic: summary
## Repositorio nao oficial
### Linha de costa Lagef - UFF - Projeto IVC - Pablo Simoes
# Repositorio teste para o Projeto IVC - LAGEF - UFF

View File

@@ -0,0 +1,10 @@
LICENCE
README.md
setup.py
LAGEF_UFF/LAGEF_UFF_Shoreline.py
LAGEF_UFF/__init__.py
LAGEF_UFF_Shoreline.egg-info/PKG-INFO
LAGEF_UFF_Shoreline.egg-info/SOURCES.txt
LAGEF_UFF_Shoreline.egg-info/dependency_links.txt
LAGEF_UFF_Shoreline.egg-info/requires.txt
LAGEF_UFF_Shoreline.egg-info/top_level.txt

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,6 @@
pandas
geemap
numpy
earthengine-api
scikit-image
matplotlib

View File

@@ -0,0 +1 @@
LAGEF_UFF

20
LICENCE Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2024 Pablo Sergio Marques Simoes - Projeto IVC - LAGEF UFF
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

31
PKG-INFO Normal file
View File

@@ -0,0 +1,31 @@
Metadata-Version: 2.4
Name: LAGEF-UFF-Shoreline
Version: 0.1.0
Summary: Scripts para análise de linha de costa - Lagef UFF - projeto IVC
Author: Pablo Simoes
Author-email: ['pablosergio.simoes@gmail.com', 'pablosimoes@id.uff.br']
License: MIT License
Keywords: lagef uff,linha de costa,shoreline,google earth engine
Description-Content-Type: text/markdown
License-File: LICENCE
Requires-Dist: pandas
Requires-Dist: geemap
Requires-Dist: numpy
Requires-Dist: earthengine-api
Requires-Dist: scikit-image
Requires-Dist: matplotlib
Dynamic: author
Dynamic: author-email
Dynamic: description
Dynamic: description-content-type
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: requires-dist
Dynamic: summary
## Repositorio nao oficial
### Linha de costa Lagef - UFF - Projeto IVC - Pablo Simoes
# Repositorio teste para o Projeto IVC - LAGEF - UFF

5
README.md Normal file
View File

@@ -0,0 +1,5 @@
## Repositorio nao oficial
### Linha de costa Lagef - UFF - Projeto IVC - Pablo Simoes
# Repositorio teste para o Projeto IVC - LAGEF - UFF

4
setup.cfg Normal file
View File

@@ -0,0 +1,4 @@
[egg_info]
tag_build =
tag_date = 0

23
setup.py Normal file
View File

@@ -0,0 +1,23 @@
from setuptools import setup
with open('README.md','r') as arq:
readme = arq.read()
setup(name='LAGEF-UFF-Shoreline',
version='0.1.0',
license='MIT License',
author='Pablo Simoes',
long_description=readme,
long_description_content_type="text/markdown",
author_email=['pablosergio.simoes@gmail.com','pablosimoes@id.uff.br'],
keywords=['lagef uff','linha de costa','shoreline','google earth engine'],
description=u'Scripts para análise de linha de costa - Lagef UFF - projeto IVC',
packages=['LAGEF_UFF'],
install_requires=['pandas','geemap','numpy','earthengine-api','scikit-image','matplotlib'],)