Initial commit

This commit is contained in:
2026-04-10 16:46:45 +08:00
commit 4fd1b0a203
165 changed files with 25698 additions and 0 deletions

783
Flexbrdf/scripts/rad2geo.py Normal file
View File

@ -0,0 +1,783 @@
#!/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()