119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
![]() |
from util import *
|
|||
|
from osgeo import gdal
|
|||
|
import argparse
|
|||
|
|
|||
|
|
|||
|
@timeit
|
|||
|
def otsu(img, max_value, data_water_mask, ignore_value=0, foreground=1, background=0):
|
|||
|
height = img.shape[0]
|
|||
|
width = img.shape[1]
|
|||
|
|
|||
|
hist = np.zeros([max_value], np.float32)
|
|||
|
|
|||
|
# 计算直方图
|
|||
|
invalid_counter = 0
|
|||
|
for i in range(height):
|
|||
|
for j in range(width):
|
|||
|
if img[i, j] == ignore_value or img[i, j] < 0 or data_water_mask[i, j] == 0:
|
|||
|
invalid_counter = invalid_counter + 1
|
|||
|
continue
|
|||
|
|
|||
|
hist[img[i, j]] += 1
|
|||
|
|
|||
|
hist /= (height * width - invalid_counter)
|
|||
|
|
|||
|
threshold = 0
|
|||
|
deltaMax = 0
|
|||
|
# 遍历像素值,计算最大类间方差
|
|||
|
for i in range(max_value):
|
|||
|
wA = 0
|
|||
|
wB = 0
|
|||
|
uAtmp = 0
|
|||
|
uBtmp = 0
|
|||
|
uA = 0
|
|||
|
uB = 0
|
|||
|
u = 0
|
|||
|
for j in range(max_value):
|
|||
|
if j <= i:
|
|||
|
wA += hist[j]
|
|||
|
uAtmp += j * hist[j]
|
|||
|
else:
|
|||
|
wB += hist[j]
|
|||
|
uBtmp += j * hist[j]
|
|||
|
if wA == 0:
|
|||
|
wA = 1e-10
|
|||
|
if wB == 0:
|
|||
|
wB = 1e-10
|
|||
|
uA = uAtmp / wA
|
|||
|
uB = uBtmp / wB
|
|||
|
u = uAtmp + uBtmp
|
|||
|
|
|||
|
# 计算类间方差
|
|||
|
deltaTmp = wA * ((uA - u)**2) + wB * ((uB - u)**2)
|
|||
|
# 找出最大类间方差以及阈值
|
|||
|
if deltaTmp > deltaMax:
|
|||
|
deltaMax = deltaTmp
|
|||
|
threshold = i
|
|||
|
|
|||
|
# 二值化
|
|||
|
det_img = img.copy()
|
|||
|
det_img[img > threshold] = foreground
|
|||
|
det_img[img <= threshold] = background
|
|||
|
det_img[np.where(data_water_mask == 0)] = background
|
|||
|
return det_img
|
|||
|
|
|||
|
|
|||
|
def find_overexposure_area(img_path, threhold=4095):
|
|||
|
# 第一步通过某个像素的光谱找到信号最强的波段
|
|||
|
|
|||
|
# 根据上步所得的波段号检测过曝区域
|
|||
|
pass
|
|||
|
|
|||
|
|
|||
|
@timeit
|
|||
|
def find_severe_glint_area(img_path, water_mask, glint_wave=750, output_path=None):
|
|||
|
if output_path is None:
|
|||
|
output_path = append2filename(img_path, "_severe_glint_area")
|
|||
|
|
|||
|
glint_band_number = find_band_number(glint_wave, img_path)
|
|||
|
|
|||
|
dataset = gdal.Open(img_path)
|
|||
|
num_bands = dataset.RasterCount
|
|||
|
im_geotrans = dataset.GetGeoTransform()
|
|||
|
im_proj = dataset.GetProjection()
|
|||
|
|
|||
|
tmp = dataset.GetRasterBand(glint_band_number + 1) # 波段计数从1开始
|
|||
|
band_flare = tmp.ReadAsArray().astype(np.int16)
|
|||
|
band_flare_stretch = (band_flare / band_flare.max() * 255).astype(np.int32)
|
|||
|
|
|||
|
dataset_water_mask = gdal.Open(water_mask)
|
|||
|
data_water_mask = dataset_water_mask.GetRasterBand(1).ReadAsArray()
|
|||
|
del dataset_water_mask
|
|||
|
|
|||
|
# 不加1报错:IndexError: index 73 is out of bounds for axis 0 with size 73
|
|||
|
flare_binary = otsu(band_flare_stretch, band_flare_stretch.max() + 1, data_water_mask)
|
|||
|
|
|||
|
write_bands(img_path, output_path, flare_binary)
|
|||
|
|
|||
|
del dataset
|
|||
|
|
|||
|
return output_path
|
|||
|
|
|||
|
|
|||
|
# Press the green button in the gutter to run the script.
|
|||
|
if __name__ == '__main__':
|
|||
|
img_path = r"D:\PycharmProjects\0water_rlx\test_data\ref_mosaic_1m_bsq"
|
|||
|
|
|||
|
parser = argparse.ArgumentParser(description="此程序通过大律法分割图像,提取耀斑最严重的区域,输出的栅格和输入的影像具有相同的行列数。")
|
|||
|
|
|||
|
parser.add_argument('-i1', '--input', type=str, required=True, help='输入影像文件的路径')
|
|||
|
parser.add_argument('-i2', '--input_water_mask', type=str, required=True, help='输入水域掩膜文件的路径')
|
|||
|
parser.add_argument('-gw', '--glint_wave', type=float, default=750.0, help='用于提取耀斑严重区域的波段.')
|
|||
|
parser.add_argument('-o', '--output', type=str, help='输出文件的路径')
|
|||
|
|
|||
|
parser.add_argument('-v', '--verbose', action='store_true', help='启用详细模式')
|
|||
|
|
|||
|
args = parser.parse_args()
|
|||
|
|
|||
|
find_severe_glint_area(args.input, args.input_water_mask, args.glint_wave, args.output)
|