森林火点识别算法代码

This commit is contained in:
王诚 2023-11-26 23:00:11 +08:00
commit 1b28df6d76
3 changed files with 311 additions and 0 deletions

12
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"configurations": [
{
"name": "Python: File",
"type": "python",
"request": "launch",
"program": "${file}",
"justMyCode": true
}
]
}

74
threshold.py Normal file
View File

@ -0,0 +1,74 @@
from osgeo import gdal
import cv2
import numpy as np
from osgeo import gdal
def main():
# 打开影像文件
image_00_00_path = "E:/vscode_code/fire_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
image_00_10_path = "E:/vscode_code/fire_code/HS_H09_20230801_0010/HS_H09_20230801_0010.tif" # 替换为你的影像路径
dataset_10 = gdal.Open(image_00_10_path)
if dataset_10 is None:
print("HS_H09_20230801_0010.tif.")
return
# 获取00时00分 band 7 和 band 14 的 temperature 数据
band7_00_00_temperature = dataset_00.GetRasterBand(7).ReadAsArray()
band14_00_00_temperature = dataset_00.GetRasterBand(14).ReadAsArray()
# 获取00时10分 band 7 和 band 14 的 temperature 数据
band7_00_10_temperature = dataset_10.GetRasterBand(7).ReadAsArray()
band14_00_10_temperature = dataset_10.GetRasterBand(14).ReadAsArray()
#计算band7band14在00分到10分的差值
band7_temperature_difference = band7_00_10_temperature - band7_00_00_temperature
band14_temperature_difference = band14_00_10_temperature - band14_00_00_temperature
#计算band7与band14在00分和10分的差值
band7_band14_00temperature_difference = band7_00_00_temperature - band14_00_00_temperature
band7_band14_10temperature_difference = band7_00_10_temperature - band14_00_10_temperature
#计算10分的band7与00分的band14的差值
band7_band14_0010temperature_difference = band7_00_10_temperature - band14_00_00_temperature
#判断火点依据
fire_point_image = []
for y in range(len(band7_00_00_temperature)):
row = []
for x in range(len(band7_00_00_temperature[y])):
if band7_00_00_temperature[y][x] > 260 and band7_00_10_temperature[y][x] > 260 and band7_temperature_difference[y][x]>15 and band7_band14_10temperature_difference[y][x] >10 and band14_temperature_difference[y][x] >-1 and band7_band14_0010temperature_difference[y][x] >12:
row.append(0) # 白色
else:
row.append(225) # 黑色
fire_point_image.append(row)
fire_point_image = np.array(fire_point_image, dtype=np.uint8)
# 保存火点图像到本地
cv2.imwrite("fire_point_image_2.tif", fire_point_image)
# Open target TIFF for update
target_dataset = gdal.Open("fire_point_image_2.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
dataset_10 = None
target_dataset = None
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
main()

225
threshold_adapt.py Normal file
View File

@ -0,0 +1,225 @@
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()