fix: 多项稳定性修复与打包优化
- PyInstaller: runtime hook 预加载 osgeo DLL 避免 Qt5 符号冲突; spec 纳入 osgeo .py 文件 + 运行时 DLL 依赖 (ffi/lzma/bz2/expat/sqlite3); 移除 DLL 双副本防止 segfault - GDAL 环境: 新增 _MEIPASS/osgeo/data/gdal 路径搜索,改善打包后 GDAL_DATA 检测 - 预览生成器: 掩膜与底图同分辨率时跳过 Warp 加速读取 - 专题图: ConvexHull 坐标中心化修复 UTM 大坐标精度退化; 边界采样兜底防止外扩点为空; TIFF 已含 NaN 掩膜时跳过矢量擦除; 形态学闭运算填充掩膜小孔洞 - NDWI: int16→float32 防止减法溢出 - 面板注册表: 步骤模块分组重构 (模块一/二/三/四重划分)
This commit is contained in:
@ -74,16 +74,12 @@ PANEL_REGISTRY = [
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 模块二 特征工程与数据
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step4_sampling',
|
||||
'class_ref': Step4SamplingPanel,
|
||||
'title': '采样点布设',
|
||||
'icon': '4.png',
|
||||
'stage': '模块二 特征工程与数据',
|
||||
'stage': '模块一 影像预处理',
|
||||
'display_name': '4. 采样点布设',
|
||||
# 架构解耦(2026-06-22):dict 键名 = 下游目标控件真实属性名;
|
||||
# 第三元素 source_attr = 上游源控件真实属性名(panel_factory 回放端使用)
|
||||
@ -95,12 +91,15 @@ PANEL_REGISTRY = [
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 模块二 光谱建模与反演
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step5_clean',
|
||||
'class_ref': Step5CleanPanel,
|
||||
'title': '数据清洗',
|
||||
'icon': '5.png',
|
||||
'stage': '模块二 特征工程与数据',
|
||||
'stage': '模块二 光谱建模与反演',
|
||||
'display_name': '5. 数据清洗',
|
||||
# 业务要求保持输入源独立,不自动抓取 step4_sampling 的输出
|
||||
'dependencies': None,
|
||||
@ -111,7 +110,7 @@ PANEL_REGISTRY = [
|
||||
'class_ref': Step6FeaturePanel,
|
||||
'title': '光谱特征',
|
||||
'icon': '6.png',
|
||||
'stage': '模块二 特征工程与数据',
|
||||
'stage': '模块二 光谱建模与反演',
|
||||
'display_name': '6. 光谱特征提取',
|
||||
# 架构解耦(2026-06-22):dict 键名 = 下游目标控件真实属性名
|
||||
'dependencies': {
|
||||
@ -131,7 +130,7 @@ PANEL_REGISTRY = [
|
||||
'class_ref': Step7InversionPanel,
|
||||
'title': '水质光谱指数计算',
|
||||
'icon': '7.png',
|
||||
'stage': '模块二 特征工程与数据',
|
||||
'stage': '模块二 光谱建模与反演',
|
||||
'display_name': '7. 水质指数计算',
|
||||
# 架构解耦(2026-06-22):dict 键名 = 下游目标控件真实属性名;
|
||||
# 第三元素 source_attr = 上游源控件真实属性名
|
||||
@ -142,15 +141,12 @@ PANEL_REGISTRY = [
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 模块三 模型训练与反演
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step8_ml_train',
|
||||
'class_ref': Step8MlTrainPanel,
|
||||
'title': '机器学习建模',
|
||||
'icon': '8.png',
|
||||
'stage': '模块三 模型训练与反演',
|
||||
'stage': '模块二 光谱建模与反演',
|
||||
'display_name': '8. 机器学习建模',
|
||||
# 架构解耦(2026-06-22):dict 键名 = 下游目标控件真实属性名
|
||||
'dependencies': {
|
||||
@ -160,15 +156,12 @@ PANEL_REGISTRY = [
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 模块三 模型训练与反演(续)→ 模块四 制图与成果汇编
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step9_ml_predict',
|
||||
'class_ref': Step9MlPredictPanel,
|
||||
'title': '机器学习预测',
|
||||
'icon': '9.png',
|
||||
'stage': '模块三 模型训练与反演',
|
||||
'stage': '模块二 光谱建模与反演',
|
||||
'display_name': '9. 机器学习预测',
|
||||
# 架构解耦(2026-06-22):dict 键名 = 下游目标控件真实属性名;
|
||||
# 第三元素 source_attr = 上游源控件真实属性名
|
||||
@ -178,12 +171,16 @@ PANEL_REGISTRY = [
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 模块三 物理公式反演
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step10_watercolor',
|
||||
'class_ref': Step10WatercolorPanel,
|
||||
'title': '水色指数反演',
|
||||
'icon': '10.png',
|
||||
'stage': '模块三 模型训练与反演',
|
||||
'stage': '模块三 物理公式反演',
|
||||
'display_name': '10. 水色指数反演',
|
||||
# 架构解耦(2026-06-22):dict 键名 = 下游目标控件真实属性名;
|
||||
# 第三元素 source_attr = 上游源控件真实属性名
|
||||
@ -194,12 +191,16 @@ PANEL_REGISTRY = [
|
||||
},
|
||||
'constructor_kwargs': None,
|
||||
},
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# 模块四 制图与成果输出
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
{
|
||||
'step_id': 'step11_map',
|
||||
'class_ref': Step11MapPanel,
|
||||
'title': '专题图生成',
|
||||
'icon': '11.png',
|
||||
'stage': '模块四 制图与成果汇编',
|
||||
'stage': '模块四 制图与成果输出',
|
||||
'display_name': '11. 分布图生成',
|
||||
# 架构解耦(2026-06-22):dict 键名 = 下游目标控件真实属性名
|
||||
'dependencies': {
|
||||
@ -217,7 +218,7 @@ PANEL_REGISTRY = [
|
||||
'class_ref': Step12VizPanel,
|
||||
'title': '可视化',
|
||||
'icon': '9.png',
|
||||
'stage': '模块四 制图与成果汇编',
|
||||
'stage': '模块四 制图与成果输出',
|
||||
'display_name': '12. 可视化展示',
|
||||
'dependencies': None,
|
||||
'constructor_kwargs': None,
|
||||
@ -227,7 +228,7 @@ PANEL_REGISTRY = [
|
||||
'class_ref': Step13ReportPanel,
|
||||
'title': '报告生成',
|
||||
'icon': '13.png',
|
||||
'stage': '模块四 制图与成果汇编',
|
||||
'stage': '模块四 制图与成果输出',
|
||||
'display_name': '13. 分析报告生成',
|
||||
'dependencies': None,
|
||||
'constructor_kwargs': {'main_window'}, # 需要注入 main_window=self
|
||||
|
||||
@ -78,9 +78,12 @@ def _find_and_set_gdal_env():
|
||||
return None
|
||||
|
||||
def _find_gdal_in_prefix(prefix):
|
||||
"""在指定前缀下查找 Library/share/gdal"""
|
||||
"""在指定前缀下查找 GDAL data 目录(Library/share/gdal 或 osgeo/data/gdal)"""
|
||||
# Conda 路径:Library/share/gdal
|
||||
# pip wheel / PyInstaller 打包后:osgeo/data/gdal
|
||||
for sub in ("Library/share/gdal", "share/gdal",
|
||||
"Library\\share\\gdal", "share\\gdal"):
|
||||
"Library\\share\\gdal", "share\\gdal",
|
||||
"osgeo/data/gdal", "osgeo\\data\\gdal"):
|
||||
path = os.path.join(prefix, sub)
|
||||
if os.path.isdir(path):
|
||||
for marker in ("gdalvrt.xsd", "pcs.csv", "gcs.csv"):
|
||||
@ -110,6 +113,12 @@ def _find_and_set_gdal_env():
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 2b) PyInstaller 打包后的解包目录 (_MEIPASS)
|
||||
# sys.prefix 在 PyInstaller 中已指向 _MEIPASS,但显式加入确保不被遗漏
|
||||
_meipass = getattr(sys, '_MEIPASS', None)
|
||||
if _meipass and _meipass not in prefixes:
|
||||
prefixes.insert(0, _meipass)
|
||||
|
||||
# 3) 从 sys.path 中 site-packages 位置回推所有可能的 conda/env 前缀
|
||||
try:
|
||||
for sp in sys.path:
|
||||
@ -236,10 +245,10 @@ def _find_and_set_gdal_env():
|
||||
# 不设置的话 Fiona 会使用自带的旧版 proj.db (VERSION.MINOR=2),
|
||||
# 导致投影解析错误 → 矢量图层错位 → 水体被错误擦除 → 有效像元为 0
|
||||
os.environ["PROJ_DATA"] = proj_lib
|
||||
print(f"[ENV] PROJ_LIB → {proj_lib}")
|
||||
print(f"[ENV] PROJ_DATA → {proj_lib}")
|
||||
print(f"[ENV] PROJ_LIB -> {proj_lib}")
|
||||
print(f"[ENV] PROJ_DATA -> {proj_lib}")
|
||||
else:
|
||||
print("[ENV] ⚠ 未找到兼容的 proj.db (需要 PROJ v6+),PROJ_LIB/PROJ_DATA 保持系统默认")
|
||||
print("[ENV] [WARN] 未找到兼容的 proj.db (需要 PROJ v6+),PROJ_LIB/PROJ_DATA 保持系统默认")
|
||||
print(f"[ENV] (已搜索 {len(prefixes)} 个前缀: {[os.path.basename(p) for p in prefixes[:5]]}...)")
|
||||
print("[ENV] 如果 step11 地图渲染报 PROJ 版本错误,")
|
||||
print("[ENV] 请手动设置: set PROJ_LIB=<conda环境>\\Library\\share\\proj")
|
||||
@ -247,9 +256,9 @@ def _find_and_set_gdal_env():
|
||||
|
||||
if gdal_data:
|
||||
os.environ["GDAL_DATA"] = gdal_data
|
||||
print(f"[ENV] GDAL_DATA → {gdal_data}")
|
||||
print(f"[ENV] GDAL_DATA -> {gdal_data}")
|
||||
else:
|
||||
print("[ENV] ⚠ 未找到 GDAL data 目录,GDAL_DATA 保持系统默认")
|
||||
print("[ENV] [WARN] 未找到 GDAL data 目录,GDAL_DATA 保持系统默认")
|
||||
print(f"[ENV] (已搜索 {len(prefixes)} 个前缀)")
|
||||
|
||||
# ── 屏蔽 Fiona 内部旧版 PROJ 路径 ──
|
||||
@ -260,7 +269,7 @@ def _find_and_set_gdal_env():
|
||||
if "PROJ_DATA" in os.environ:
|
||||
print("[ENV] 已屏蔽 Fiona 内部旧版 PROJ 数据库,全进程统一使用上述 proj.db")
|
||||
if _fiona_v2_path:
|
||||
print(f"[ENV] ⚠ 检测到 Fiona 自带的旧版 proj.db (v2) 位于:")
|
||||
print(f"[ENV] [WARN] 检测到 Fiona 自带的旧版 proj.db (v2) 位于:")
|
||||
print(f" {_fiona_v2_path}")
|
||||
print(f" PROJ_DATA 已指向 v6+ 版本,此旧版将被忽略")
|
||||
if proj_lib:
|
||||
|
||||
Reference in New Issue
Block a user