Files
BRDF/Flexbrdf/scripts/rad2geo.py
2026-04-10 16:46:45 +08:00

783 lines
27 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.

#!/usr/bin/env python3
"""
高光谱图像地理变换工具
功能:
- 读取地理校正后的高光谱航带图像 (dat格式11个波段前3个光谱波段、列号、行号、航带号、后5个光谱波段)
- 读取原始高光谱图像 (bil格式)
- 通过行列号进行地理变换匹配
- 保存变换后的高光谱图像
文件命名格式:
- 地理校正文件2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo1.dat
- 原始文件2025_9_2_3_53_45_202592_35252_0_rad.bil
依赖:
- numpy
- spectral (pip install spectral)
- pathlib
"""
import numpy as np
import os
from pathlib import Path
import re
from typing import Tuple, Optional, List
try:
import spectral
SPECTRAL_AVAILABLE = True
except ImportError:
SPECTRAL_AVAILABLE = False
print("警告: spectral库不可用请安装: pip install spectral")
# 可选GDAL库用于保存ENVI格式文件
try:
from osgeo import gdal
GDAL_AVAILABLE = True
except ImportError:
GDAL_AVAILABLE = False
print("警告: GDAL不可用将使用numpy保存")
def _format_geo_info_for_envi(geo_value):
"""
直接返回地理信息的原始格式已经是从HDR文件直接复制的
"""
if not geo_value:
return None
return geo_value
def extract_file_key(filename: str) -> str:
"""
从文件名中提取用于匹配的关键字
匹配规则:按"2025_9_2_3_53_45_202592_35252_0"这一部分完全相同进行匹配
即匹配模式为数字_数字_..._数字_rad
示例:
"2025_9_2_3_53_45_202592_35252_2_rad_rgbxyz_geo1.dat" -> "2025_9_2_3_53_45_202592_35252_2"
"2025_9_2_3_53_45_202592_35252_9_rad.bil" -> "2025_9_2_3_53_45_202592_35252_9"
"""
# 提取_rad之前的部分作为匹配键
if '_rad' in filename:
key = filename.split('_rad')[0]
return key
else:
# 如果没有_rad尝试其他方式
return filename
def load_geo_corrected_dat(dat_file: str) -> Tuple[np.ndarray, dict]:
"""
读取地理校正后的dat文件
dat文件包含11个波段的原始数据
- 波段0-2: 前三个光谱波段
- 波段3: 列号
- 波段4: 行号
- 波段5: 航带号
- 波段6-10: 后五个光谱波段
使用spectral库读取dat文件
参数:
-----------
dat_file : str
dat文件路径
返回:
-----------
data : np.ndarray
图像数据 (pixels, 11)每个像素11个波段
metadata : dict
元数据信息
"""
if not SPECTRAL_AVAILABLE:
raise RuntimeError("需要spectral库来读取dat文件请安装: pip install spectral")
try:
# 查找对应的头文件
dat_path = Path(dat_file)
hdr_file = dat_path.with_suffix('.hdr')
if not hdr_file.exists():
# 首先读取数据大小来推断图像尺寸
data_temp = np.fromfile(dat_file, dtype=np.float32)
if data_temp.size % 11 != 0:
raise ValueError(f"数据大小 {data_temp.size} 不能被11整除可能不是正确的dat文件格式")
num_pixels = data_temp.size // 11
# 尝试推断图像尺寸
possible_rows = []
for rows in range(1000, int(np.sqrt(num_pixels)) + 1000, 100):
if num_pixels % rows == 0:
cols = num_pixels // rows
if cols > 0 and cols < 10000:
possible_rows.append((rows, cols))
if not possible_rows:
rows = int(np.sqrt(num_pixels))
cols = (num_pixels + rows - 1) // rows
else:
rows, cols = possible_rows[0]
# 创建临时的头文件
hdr_content = f"""ENVI
description = {{
高光谱地理校正数据 - 11波段格式
前3个光谱波段、列号、行号、航带号、后5个光谱波段}}
samples = {cols}
lines = {rows}
bands = 11
header offset = 0
file type = ENVI Standard
data type = 4
interleave = bip
byte order = 0
band names = {{
波段1, 波段2, 波段3, 列号, 行号, 航带号, 波段7, 波段8, 波段9, 波段10, 波段11}}
"""
with open(hdr_file, 'w', encoding='utf-8') as f:
f.write(hdr_content)
# 使用spectral读取
image_data = spectral.open_image(str(hdr_file))
data = image_data.load()
# 如果数据是3D的需要重新整形为2D (pixels, bands)
if data.ndim == 3:
data_reshaped = data.reshape(-1, data.shape[2])
else:
data_reshaped = data
# 确保是11波段
if data_reshaped.shape[1] != 11:
raise ValueError(f"数据波段数 {data_reshaped.shape[1]} 不等于期望的11波段")
# 检查坐标是否全部为0第4、5波段为列号、行号
all_coords_zero = (data_reshaped[:, 3].max() == 0 and data_reshaped[:, 4].max() == 0)
# 如果坐标都为0显示警告
if all_coords_zero:
print(f"警告: dat文件中的所有行列号都是0可能需要重新解释数据格式")
# 读取HDR文件中的地理信息直接复制原始格式
geo_info = {}
try:
# 直接读取HDR文件内容保留原始格式
with open(str(hdr_file), 'r', encoding='utf-8', errors='ignore') as f:
hdr_content = f.read()
# 提取map info行
import re
map_info_match = re.search(r'^map info\s*=\s*(.+)$', hdr_content, re.MULTILINE | re.IGNORECASE)
if map_info_match:
geo_info['map_info'] = map_info_match.group(1).strip()
# 提取coordinate system string行
coord_sys_match = re.search(r'^coordinate system string\s*=\s*(.+)$', hdr_content, re.MULTILINE | re.IGNORECASE)
if coord_sys_match:
geo_info['coordinate_system_string'] = coord_sys_match.group(1).strip()
# 提取projection info行如果有
proj_info_match = re.search(r'^projection info\s*=\s*(.+)$', hdr_content, re.MULTILINE | re.IGNORECASE)
if proj_info_match:
geo_info['projection_info'] = proj_info_match.group(1).strip()
except Exception as e:
print(f"警告: 无法读取geo文件的HDR地理信息: {e}")
metadata = {
'file_path': dat_file,
'hdr_file': str(hdr_file),
'data_type': str(data_reshaped.dtype),
'bands': 11,
'pixels': len(data_reshaped),
'lines': image_data.nrows,
'samples': image_data.ncols,
'band_names': ['band1', 'band2', 'band3', 'column', 'row', 'strip', 'band7', 'band8', 'band9', 'band10', 'band11'],
'col_idx': 3,
'row_idx': 4,
'strip_idx': 5,
'all_coords_zero': all_coords_zero,
'wavelengths': getattr(image_data.bands, 'centers', None),
'interleave': getattr(image_data, 'interleave', 'unknown'),
'geo_info': geo_info
}
return data_reshaped, metadata
except Exception as e:
print(f"spectral读取失败: {e}")
print("回退到numpy直接读取...")
# 备用方案使用numpy直接读取
try:
data = np.fromfile(dat_file, dtype=np.float32)
if data.size % 11 != 0:
raise ValueError(f"数据大小 {data.size} 不能被11整除可能不是正确的dat文件格式")
num_pixels = data.size // 11
data_reshaped = data.reshape(num_pixels, 11)
print(f"numpy直接读取成功: {dat_file}")
print(f"数据形状: {data_reshaped.shape} (pixels, bands)")
# 分析坐标信息
all_coords_zero = (data_reshaped[:, 3].max() == 0 and data_reshaped[:, 4].max() == 0)
metadata = {
'file_path': dat_file,
'data_type': 'float32',
'bands': 11,
'pixels': num_pixels,
'band_names': ['band1', 'band2', 'band3', 'column', 'row', 'strip', 'band7', 'band8', 'band9', 'band10', 'band11'],
'col_idx': 3,
'row_idx': 4,
'strip_idx': 5,
'all_coords_zero': all_coords_zero
}
return data_reshaped, metadata
except Exception as e2:
raise RuntimeError(f"读取dat文件失败: spectral错误: {e}, numpy错误: {e2}")
def load_original_bil(bil_file: str) -> Tuple[np.ndarray, dict]:
"""
读取原始高光谱bil文件
使用spectral库通过hdr头文件读取ENVI格式的高光谱数据
参数:
-----------
bil_file : str
bil文件路径
返回:
-----------
data : np.ndarray
高光谱数据 (lines, samples, bands)
metadata : dict
元数据信息
"""
if not SPECTRAL_AVAILABLE:
raise RuntimeError("需要spectral库来读取bil文件请安装: pip install spectral")
try:
# 查找对应的头文件
bil_path = Path(bil_file)
hdr_file = bil_path.with_suffix('.hdr')
if not hdr_file.exists():
hdr_file = bil_path.parent / f"{bil_path.name}.hdr"
if not hdr_file.exists():
hdr_file = bil_path.parent / f"{bil_path.stem}.hdr"
if not hdr_file.exists():
possible_hdrs = list(bil_path.parent.glob(f"{bil_path.stem}*.hdr"))
if possible_hdrs:
hdr_file = possible_hdrs[0]
else:
raise FileNotFoundError(f"未找到对应的头文件")
# 使用spectral读取ENVI格式文件
image_data = spectral.open_image(str(hdr_file))
data = image_data.load()
# 获取元数据
metadata = {
'file_path': bil_file,
'hdr_file': str(hdr_file),
'lines': image_data.nrows,
'samples': image_data.ncols,
'bands': image_data.nbands,
'wavelengths': image_data.bands.centers if hasattr(image_data.bands, 'centers') else None,
'data_type': str(data.dtype),
'interleave': getattr(image_data, 'interleave', 'unknown')
}
return data, metadata
except Exception as e:
raise RuntimeError(f"读取高光谱文件失败: {bil_file}, 错误: {e}")
def perform_geometric_transform(original_data: np.ndarray,
geo_data: np.ndarray,
geo_metadata: dict,
output_shape: Optional[Tuple[int, int]] = None,
chunk_size: Optional[int] = None) -> np.ndarray:
"""
向量化版本的地理变换
核心逻辑:
1. geo_data[:, 3]和geo_data[:, 4]是原始bil文件中的列号和行号geo从0开始bil从1开始需减1
2. geo像素中"非地理参考"的波段前3个和后5个不全为0的像素才需要替换输出保持0
3. 输出尺寸为geo图像的尺寸geo_metadata['lines'], geo_metadata['samples']
4. 支持可选分块以降低峰值内存
参数:
-----------
original_data : np.ndarray
原始高光谱数据 (orig_lines, orig_samples, bands)
geo_data : np.ndarray
地理校正数据 (pixels, 11) - geo图像中所有像素的序列
geo_metadata : dict
地理校正数据的元数据
output_shape : tuple, optional
输出图像的形状 (lines, samples)如果不指定则尝试从geo_metadata推断
chunk_size : int, optional
分块处理时的块大小,默认一次性处理所有像素
返回:
-----------
transformed_data : np.ndarray
变换后的高光谱数据尺寸为geo图像的尺寸
"""
try:
# 原始BIL尺寸
orig_lines, orig_samples, bands = original_data.shape
# 输出尺寸使用geo尺寸
if output_shape is None:
if 'lines' in geo_metadata and 'samples' in geo_metadata:
lines_out, samples_out = int(geo_metadata['lines']), int(geo_metadata['samples'])
else:
# 兜底按geo展平像素数推断一个尽量方的尺寸
total = len(geo_data)
lines_out = int(np.sqrt(total))
samples_out = (total + lines_out - 1) // lines_out
else:
lines_out, samples_out = output_shape
# 验证输出图像尺寸是否与geo_data像素数量匹配
expected_pixels = lines_out * samples_out
if expected_pixels != len(geo_data):
print(f"警告: 输出图像尺寸({lines_out}x{samples_out}={expected_pixels})与geo数据像素数({len(geo_data)})不匹配")
print("将调整输出尺寸以匹配geo数据像素数")
lines_out = len(geo_data) // samples_out
if lines_out * samples_out < len(geo_data):
lines_out += 1
# 预分配输出(忽略值=0
out = np.zeros((lines_out, samples_out, bands), dtype=original_data.dtype)
print(f"开始地理变换: 原始bil尺寸 {orig_lines}x{orig_samples}x{bands}")
print(f"输出geo图像尺寸: {lines_out}x{samples_out}x{bands}")
print(f"处理 {len(geo_data)} 个geo像素")
# 获取坐标索引从metadata中读取默认为3、4、5
col_idx = geo_metadata.get('col_idx', 3)
row_idx = geo_metadata.get('row_idx', 4)
# 有效掩码:
# 1) geo像素的"非地理参考"波段前col_idx个和后面的不全为0
# 对于11波段检查波段0-2和6-10是否不全为0
non_geo_bands = np.concatenate([np.arange(col_idx), np.arange(col_idx+3, geo_data.shape[1])])
non_zero_mask = ~(np.all(geo_data[:, non_geo_bands] == 0, axis=1))
# 2) 索引合法geo从0BIL从1因此索引时要减1
src_cols = geo_data[:, col_idx].astype(np.int64) - 1
src_rows = geo_data[:, row_idx].astype(np.int64) - 1
in_bounds = (src_rows >= 0) & (src_rows < orig_lines) & (src_cols >= 0) & (src_cols < orig_samples)
valid = non_zero_mask & in_bounds
if not np.any(valid):
print("地理变换完成: 没有有效像素需要处理")
return out
# 有效条目
valid_idx = np.flatnonzero(valid)
# 计算原始BIL扁平索引并批量取光谱
src_rows_v = src_rows[valid]
src_cols_v = src_cols[valid]
src_lin = src_rows_v * orig_samples + src_cols_v # (N_valid,)
orig_flat = original_data.reshape(-1, bands)
if chunk_size is None or len(valid_idx) <= chunk_size:
# 一次性
spectra = orig_flat[src_lin] # (N_valid, bands)
# 计算输出位置geo是按行优先展平
out_rows = valid_idx // samples_out
out_cols = valid_idx % samples_out
out[out_rows, out_cols, :] = spectra
else:
# 分块,降低峰值内存
for s in range(0, len(valid_idx), chunk_size):
e = min(s + chunk_size, len(valid_idx))
src_lin_chunk = src_lin[s:e]
spectra = orig_flat[src_lin_chunk]
idx_chunk = valid_idx[s:e]
out_rows = idx_chunk // samples_out
out_cols = idx_chunk % samples_out
out[out_rows, out_cols, :] = spectra
valid_count = len(valid_idx)
skipped_count = len(geo_data) - valid_count
print(f"地理变换完成: 成功处理 {valid_count} 个像素,跳过 {skipped_count} 个像素无效或全0")
return out
except Exception as e:
raise RuntimeError(f"地理变换失败: {e}")
def fill_nan_with_nearest(data: np.ndarray) -> np.ndarray:
"""
用最近邻值填充NaN值
参数:
-----------
data : np.ndarray
包含NaN的数组
返回:
-----------
filled_data : np.ndarray
填充后的数组
"""
# 简单实现:使用前向填充
filled_data = data.copy()
# 对于每个波段
for band in range(data.shape[2]):
band_data = data[:, :, band]
# 找到非NaN值的掩码
valid_mask = ~np.isnan(band_data)
if np.any(valid_mask):
# 使用最近邻插值(这里使用简单的行方向填充)
for i in range(band_data.shape[0]):
row_data = band_data[i, :]
valid_indices = np.where(~np.isnan(row_data))[0]
if len(valid_indices) > 0:
# 对每一行,用有效值填充
for j in range(len(row_data)):
if np.isnan(row_data[j]):
# 找到最近的有效值
distances = np.abs(valid_indices - j)
nearest_idx = valid_indices[np.argmin(distances)]
row_data[j] = row_data[nearest_idx]
filled_data[:, :, band] = band_data
return filled_data
def save_transformed_data(data: np.ndarray, output_file: str, wavelengths: Optional[np.ndarray] = None,
geo_info: Optional[dict] = None):
"""
保存变换后的高光谱数据为ENVI BIL格式
参数:
-----------
data : np.ndarray
要保存的数据 (lines, samples, bands)
output_file : str
输出文件路径 (.bil)
wavelengths : np.ndarray, optional
波长信息
"""
lines, samples, bands = data.shape
# 确保输出目录存在
output_path = Path(output_file)
output_path.parent.mkdir(parents=True, exist_ok=True)
# 输出文件路径
bil_file = str(output_path.with_suffix('.dat'))
hdr_file = str(output_path.with_suffix('.hdr'))
try:
if GDAL_AVAILABLE:
# 使用GDAL保存ENVI格式文件
save_with_gdal_envi(data, bil_file, wavelengths, geo_info)
else:
# 回退到numpy保存
save_with_numpy_envi(data, bil_file, hdr_file, wavelengths, geo_info)
print(f"✅ 成功保存地理变换结果:")
print(f" 数据文件: {bil_file}")
print(f" 头文件: {hdr_file}")
print(f" 数据尺寸: {lines} x {samples} x {bands}")
print(f" 保存方式: {'GDAL' if GDAL_AVAILABLE else 'NumPy'}")
except Exception as e:
raise RuntimeError(f"保存文件失败: {output_file}, 错误: {e}")
def save_with_gdal_envi(data: np.ndarray, bil_file: str, wavelengths: Optional[np.ndarray] = None,
geo_info: Optional[dict] = None):
"""
使用GDAL保存ENVI BIL格式文件
"""
lines, samples, bands = data.shape
hdr_file = bil_file.replace('.dat', '.hdr')
# 创建GDAL ENVI驱动
driver = gdal.GetDriverByName('ENVI')
# 创建数据集GDAL ENVI默认使用BSQ格式data type = 12 (uint16)
dataset = driver.Create(bil_file, samples, lines, bands, gdal.GDT_UInt16,
options=['INTERLEAVE=BSQ'])
if dataset is None:
raise RuntimeError(f"无法创建ENVI数据集: {bil_file}")
try:
# 设置元数据
metadata = dataset.GetMetadata()
metadata['DESCRIPTION'] = 'Geometrically transformed hyperspectral data'
metadata['SENSOR_TYPE'] = 'Hyperspectral'
metadata['DATA_UNITS'] = 'Reflectance'
metadata['PROCESSING_ALGORITHM'] = 'Geometric Transformation'
metadata['CREATION_DATE'] = str(np.datetime64('now'))
# 添加波长信息到元数据
if wavelengths is not None and len(wavelengths) == bands:
metadata['wavelength_units'] = 'nm'
for i, wl in enumerate(wavelengths):
metadata[f'wavelength_{i+1}'] = str(wl)
dataset.SetMetadata(metadata)
# 写入数据
for band_idx in range(bands):
band = dataset.GetRasterBand(band_idx + 1)
band_data = data[:, :, band_idx].astype(np.float32)
band.WriteArray(band_data)
band.SetNoDataValue(0.0) # 设置NoData值
# 设置波段描述
if wavelengths is not None and band_idx < len(wavelengths):
band.SetDescription(f'{wavelengths[band_idx]:.1f} nm')
else:
band.SetDescription(f'Band {band_idx + 1}')
finally:
# 关闭数据集
dataset = None
# 在数据集完全关闭后覆盖GDAL自动创建的HDR文件
import time
time.sleep(0.1) # 短暂等待确保GDAL完成写入
create_envi_header(hdr_file, lines, samples, bands, wavelengths, geo_info)
def save_with_numpy_envi(data: np.ndarray, bil_file: str, hdr_file: str,
wavelengths: Optional[np.ndarray] = None, geo_info: Optional[dict] = None):
"""
使用numpy保存ENVI BSQ格式文件GDAL不可用时的回退方案
"""
lines, samples, bands = data.shape
# 保存二进制数据 - BSQ格式按波段顺序存储data type = 12 (uint16)
with open(bil_file, 'wb') as f:
# BSQ格式对于每个波段存储所有像素
for band_idx in range(bands):
# 转换为uint16裁剪到有效范围
band_data = np.clip(data[:, :, band_idx], 0, 65535).astype(np.uint16)
band_data.tofile(f)
# 创建HDR头文件
create_envi_header(hdr_file, lines, samples, bands, wavelengths, geo_info)
def create_envi_header(hdr_file: str, lines: int, samples: int, bands: int,
wavelengths: Optional[np.ndarray] = None, geo_info: Optional[dict] = None):
"""
创建ENVI格式的HDR头文件
"""
with open(hdr_file, 'w', encoding='utf-8') as f:
f.write("ENVI\n")
f.write("description = {\n")
f.write(" Geometrically transformed hyperspectral data\n")
f.write(" Processed with Python geometric transformation}\n")
f.write(f"samples = {samples}\n")
f.write(f"lines = {lines}\n")
f.write(f"bands = {bands}\n")
f.write("header offset = 0\n")
f.write("file type = ENVI Standard\n")
f.write("data type = 12\n") # uint16
f.write("interleave = bsq\n")
f.write("sensor type = Hyperspectral\n")
f.write("byte order = 0\n") # little-endian
f.write("data ignore value = 0\n")
# 添加地理参考信息直接使用从原始HDR复制的格式
if geo_info:
if geo_info.get('map_info'):
f.write(f"map info = {geo_info['map_info']}\n")
if geo_info.get('coordinate_system_string'):
f.write(f"coordinate system string = {geo_info['coordinate_system_string']}\n")
if geo_info.get('projection_info'):
f.write(f"projection info = {geo_info['projection_info']}\n")
# 添加波长信息
if wavelengths is not None and len(wavelengths) == bands:
f.write("wavelength units = nm\n")
f.write("wavelength = { ")
for i, wl in enumerate(wavelengths):
f.write(f"{wl}")
if i < len(wavelengths) - 1:
f.write(",")
f.write(" }\n")
def process_file_pair(geo_dat_file: str, bil_file: str, output_dir: str) -> bool:
"""
处理一对匹配的文件
参数:
-----------
geo_dat_file : str
地理校正dat文件路径
bil_file : str
原始bil文件路径
output_dir : str
输出目录
返回:
-----------
success : bool
处理是否成功
"""
try:
# 读取地理校正数据
geo_data, geo_metadata = load_geo_corrected_dat(geo_dat_file)
# 读取原始高光谱数据
original_data, orig_metadata = load_original_bil(bil_file)
# 执行地理变换
transformed_data = perform_geometric_transform(original_data, geo_data, geo_metadata)
# 生成输出文件名
bil_name = Path(bil_file).stem
output_file = Path(output_dir) / f"{bil_name}_geo_corrected.dat"
# 保存结果
wavelengths = orig_metadata.get('wavelengths')
geo_info = geo_metadata.get('geo_info')
save_transformed_data(transformed_data, str(output_file), wavelengths, geo_info)
return True
except Exception as e:
print(f"处理失败: {e}")
return False
def find_matching_files(geo_dir: str, bil_dir: str) -> List[Tuple[str, str]]:
"""
查找匹配的文件对
参数:
-----------
geo_dir : str
地理校正文件目录
bil_dir : str
原始bil文件目录
返回:
-----------
file_pairs : List[Tuple[str, str]]
匹配的文件对列表 [(geo_file, bil_file), ...]
"""
geo_files = {}
bil_files = {}
# 收集地理校正文件
for file_path in Path(geo_dir).glob('*_rad_rgbxyz_geo_angles_registered.bip'):
key = extract_file_key(file_path.name)
geo_files[key] = str(file_path)
# 收集bil文件
for file_path in Path(bil_dir).glob('*_rad.bil'):
key = extract_file_key(file_path.name)
bil_files[key] = str(file_path)
# 找到匹配的对
matching_pairs = []
for key in geo_files.keys():
if key in bil_files:
matching_pairs.append((geo_files[key], bil_files[key]))
return matching_pairs
def batch_process(geo_dir: str, bil_dir: str, output_dir: str) -> dict:
"""
批量处理所有匹配的文件对
参数:
-----------
geo_dir : str
地理校正文件目录
bil_dir : str
原始bil文件目录
output_dir : str
输出目录
返回:
-----------
results : dict
处理结果统计
"""
# 确保输出目录存在
Path(output_dir).mkdir(parents=True, exist_ok=True)
# 查找匹配的文件对
file_pairs = find_matching_files(geo_dir, bil_dir)
if not file_pairs:
return {'total': 0, 'success': 0, 'failed': 0}
# 处理每一对文件
results = {'total': len(file_pairs), 'success': 0, 'failed': 0}
for geo_file, bil_file in file_pairs:
success = process_file_pair(geo_file, bil_file, output_dir)
if success:
results['success'] += 1
else:
results['failed'] += 1
return results
def main():
"""
主函数 - 示例用法
"""
# 示例路径(需要根据实际情况修改)
geo_corrected_dir = r"D:\BaiduNetdiskDownload\20250902\_3_52_52\316\jiaozhen" # 地理校正dat文件目录
original_bil_dir = r"D:\BaiduNetdiskDownload\20250902\_3_52_52\Geoout\Radout" # 原始bil文件目录
output_dir = r"D:\BaiduNetdiskDownload\20250902\_3_52_52\316\cube" # 输出目录
# 检查依赖
if not SPECTRAL_AVAILABLE:
print("错误: 需要安装spectral库")
return
# 批量处理
results = batch_process(geo_corrected_dir, original_bil_dir, output_dir)
if results['success'] > 0:
print(f"处理完成!成功处理了 {results['success']} 对文件")
else:
print("未成功处理任何文件,请检查文件路径和格式")
if __name__ == "__main__":
main()