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()