wangcheng/threshold_adapt.py

226 lines
9.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from osgeo import gdal
import cv2
import numpy as np
from osgeo import gdal
import ephem
# 水体掩膜
def is_water(reflectance_band4, reflectance_band5, threshold_reflectance_4=0.05, threshold_reflectance_5=0.15):
if reflectance_band4 < threshold_reflectance_4 and reflectance_band5 < threshold_reflectance_5:
return True
else:
return False
#云掩膜
def is_cloud(reflectance_band3, reflectance_band5, band14_00_00_temperature, threshold_reflectance_35=0.9, threshold_temperature_14=265):
if reflectance_band3 + reflectance_band5 > threshold_reflectance_35 and band14_00_00_temperature < threshold_temperature_14:
return True
else:
return False
# 太阳光耀
def calculate_solar_azimuth(latitude, longitude, observation_time):
observer = ephem.Observer()
observer.lat = str(latitude)
observer.lon = str(longitude)
observer.date = observation_time # Set the observation time
sun = ephem.Sun()
sun.compute(observer)
azimuth = float(sun.az) * 180 / ephem.pi
if azimuth < 0:
azimuth += 360
return azimuth
def main():
# 打开影像文件
image_00_00_path = "E:/Vscode_code/HS_H09_20230801_0000/HS_H09_20230801_0000.tif" # 替换为你的影像路径
dataset_00 = gdal.Open(image_00_00_path)
if dataset_00 is None:
print("HS_H09_20230801_0000.tif.")
return
# 水体掩膜
#获取波段4和波段5的表观反射率
band4_00_00_radiance = dataset_00.GetRasterBand(4).ReadAsArray()
band5_00_00_radiance = dataset_00.GetRasterBand(5).ReadAsArray()
# Specify your thresholds
threshold_reflectance_4 = 0.05
threshold_reflectance_5 = 0.15
#生成云掩膜
#获取波段3和波段5的表观反射率波段14的亮温
band3_00_00_radiance = dataset_00.GetRasterBand(3).ReadAsArray()
band5_00_00_radiance = dataset_00.GetRasterBand(5).ReadAsArray()
band14_00_00_temperature = dataset_00.GetRasterBand(14).ReadAsArray()
# Specify your thresholds
threshold_reflectance_35 = 0.9
threshold_temperature_14 = 265
#计算太阳方位角
# Get the geotransformation information
geo_transform = dataset_00.GetGeoTransform()
# Get image size (number of rows and columns)
rows = dataset_00.RasterYSize
cols = dataset_00.RasterXSize
# Iterate through each pixel and convert row/col to geographic coordinates
for row in range(rows):
for col in range(cols):
x_geo = geo_transform[0] + col * geo_transform[1] + row * geo_transform[2]
y_geo = geo_transform[3] + col * geo_transform[4] + row * geo_transform[5]
# Replace with the actual latitude, longitude, and observation time
latitude = y_geo
longitude = x_geo
observation_time = "2023/08/01/00/00/00" # Replace with the actual observation time
solar_azimuth = calculate_solar_azimuth(latitude, longitude, observation_time)
# Create an empty mask to store water,cloud,sun pixels
water_cloud_sun_mask_image = []
# Iterate through each pixel and determine if it's water,cloud,sun or not
for y in range(len(band3_00_00_radiance)):
row_mask = []
for x in range(len(band3_00_00_radiance[y])):
if is_water(band4_00_00_radiance[y, x], band5_00_00_radiance[y, x], threshold_reflectance_4, threshold_reflectance_5):
row_mask.append(0)
elif is_cloud(band3_00_00_radiance[y, x], band5_00_00_radiance[y, x], band14_00_00_temperature[y, x], threshold_reflectance_35, threshold_temperature_14):
row_mask.append(0)
elif 165 < solar_azimuth < 200:
row_mask.append(0)
else:
row_mask.append(255)
water_cloud_sun_mask_image.append(row_mask)
# 遥感数据假设你已经有了一个4通道的温度数据和对应的14通道数据
band7_00_00_temperature = dataset_00.GetRasterBand(7).ReadAsArray()
band14_00_00_temperature = dataset_00.GetRasterBand(14).ReadAsArray()
# 定义阈值
day_threshold = 360 # 白天温度阈值
night_threshold = 320 # 夜晚温度阈值
background_expansion = 7 # 背景区域扩展步长
# 计算晴空植被像元数量
# 计算NDVI
band4_00_00_radiance = dataset_00.GetRasterBand(4).ReadAsArray()
band3_00_00_radiance = dataset_00.GetRasterBand(3).ReadAsArray()
# 禁用特定的警告
np.seterr(divide='ignore', invalid='ignore')
# 计算NDVI将无效值设为0
ndvi = np.where((band4_00_00_radiance + band3_00_00_radiance) != 0, (band4_00_00_radiance - band3_00_00_radiance) / (band4_00_00_radiance + band3_00_00_radiance), 0)
# 遥感数据假设你已经有了一个植被指数的数据比如Normalized Difference Vegetation Index (NDVI)
ndvi_data = ndvi # 替换为你的植被指数数据
# 定义阈值,这个阈值通常需要根据具体的数据和应用场景来设置
vegetation_threshold = 0.2 # 例如设置为0.2表示NDVI值大于0.2的像元被认为是植被
# 定义植被列表
vegetation_band7_00_00 = []
vegetation_band14_00_00 = []
# 定义疑似高温火点列表,初始化为白色 (255)
suspicious_hotspots = np.full_like(band7_00_00_temperature, 255, dtype=np.uint8)
# 遍历每个像元
for row in range(len(band7_00_00_temperature)):
for col in range(len(band7_00_00_temperature[0])):
if water_cloud_sun_mask_image[row][col] == 255:
# 获取当前像元的温度数据
band7_00_00_temperature_current = band7_00_00_temperature[row][col]
band14_00_00_temperature_current = band14_00_00_temperature[row][col]
# 检查白天和夜晚的温度阈值条件
if band7_00_00_temperature_current > day_threshold or band7_00_00_temperature_current > night_threshold :
# 初始化邻域扩展步长
expansion = background_expansion
# 初始化晴空植被像元数量
clear_vegetation_count = 0
# 开始扩展邻域,直到满足晴空植被像元数量条件
while clear_vegetation_count < (expansion * expansion * 0.2):
# 获取邻域像元数据
neighborhood_band7_00_00 = band7_00_00_temperature[
row - expansion // 2 : row + expansion // 2 + 1,
col - expansion // 2 : col + expansion // 2 + 1,
]
# 计算左上角和右上角的行列索引
top_left_row = max(row - expansion // 2, 0)
top_left_col = max(col - expansion // 2, 0)
bottom_right_row = min(row + expansion // 2, 6001 - 1)
bottom_right_col = min(col + expansion // 2 + 1, 6001)
# 遍历每个像元
for row in range(top_left_row, +bottom_right_row + 1):
for col in range(top_left_col, bottom_right_col):
# 获取当前像元的植被指数值
ndvi_value = ndvi_data[row][col]
# 判断是否为晴空植被像元
if ndvi_value > vegetation_threshold:
# 如果是晴空植被像元,将其添加到晴空植被像元数量中
clear_vegetation_count += 1
# 计算背景晴空植被像元band7和band14亮温
vegetation_band7_00_00.append(band7_00_00_temperature[row][col])
vegetation_band14_00_00.append(band14_00_00_temperature[row][col])
# 如果还不满足条件,增加邻域扩展步长
if clear_vegetation_count < (expansion * expansion * 0.2):
expansion += 2 # 可以按需调整步长,例如+2
# 如果扩展步长超过最大值例如19x19则退出循环
if expansion > 19:
break
# 计算温度差和平均温度差
delta_B7_14 = band7_00_00_temperature_current - band14_00_00_temperature_current
delta_B7_11_bg = np.array(vegetation_band7_00_00) - np.array(vegetation_band14_00_00)
# 检查疑似高温火点条件
if band7_00_00_temperature_current > np.mean(vegetation_band7_00_00) + 10 and delta_B7_14 > np.mean(delta_B7_11_bg) + 8:
# 将当前像元标记为疑似高温火点
suspicious_hotspots[row][col] = np.array( 0, dtype=np.uint8) # 黑色
suspicious_hotspots= np.array(suspicious_hotspots, dtype=np.uint8)
# 保存图像到本地
cv2.imwrite("E:/Vscode_code/threshold_adapt_fireimage/suspicious_hotspots.tif", suspicious_hotspots)
# Open target TIFF for update
target_dataset = gdal.Open("E:/Vscode_code/threshold_adapt_fireimage/suspicious_hotspots.tif", gdal.GA_Update)
dataset_00_geo_transform = dataset_00.GetGeoTransform()
# Apply the source geo-transform to the target TIFF
target_dataset.SetGeoTransform(dataset_00_geo_transform)
# Close the datasets to save changes
dataset_00 = None
target_dataset = None
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
main()