# diffsim **Repository Path**: bestaone/diffsim ## Basic Information - **Project Name**: diffsim - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 10 - **Created**: 2026-03-23 - **Last Updated**: 2026-04-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # DiffSim - AI 驱动的建筑变化检测平台 DiffSim 是一个基于深度学习的航拍/卫星图像建筑变化检测系统,通过对比同一地区不同时间点的图像,自动识别建筑新建、改建或拆除等结构性变化。 **主要应用场景:** - 城市规划中的建筑变化监测 - 基础设施巡检与违建检测 - 时序变化分析(施工进度、灾后评估等) --- ## 目录 - [功能概览](#功能概览) - [技术栈](#技术栈) - [系统架构](#系统架构) - [核心模块](#核心模块) - [处理流程](#处理流程) - [关键算法](#关键算法) - [启动与调试](#启动与调试) - [配置说明](#配置说明) - [目录结构](#目录结构) --- ## 功能概览 系统提供三种处理模式: | 模式 | 功能 | 输入 | 输出 | |------|------|------|------| | **SAM3 模式** | 建筑语义分割 | 1-2 张图像 | 建筑掩码图 | | **DINO 模式** | 差异热力图生成 | 2 张图像 | 变化热力图 | | **Pipeline 模式** | 端到端完整流程 | 2 张图像(前/后) | 配准图 + 掩码 + 热力图 + 变化框选 | --- ## 技术栈 ### 深度学习模型 | 模型 | 用途 | 说明 | |------|------|------| | **LoFTR** (Local Feature TRansformer) | 图像配准 | Transformer 特征匹配 + RANSAC 单应性估计,消除视角/旋转差异 | | **SAM3** (Segment Anything Model 3) | 建筑分割 | 文本引导语义分割(prompt: "building"),支持 Zero-DCE 低光增强 | | **DINOv3** + **DreamSim** | 变化检测 | 滑动窗口 patch 特征提取 + 余弦相似度比较 + 自适应阈值 | ### 前端 & 后端 | 组件 | 技术 | 说明 | |------|------|------| | 前端 Web UI | **Streamlit** (Python) | 图像上传、参数调节、实时可视化 | | 后端 API | **Go / Gin** | RESTful 接口,编排三阶段处理流程 | | 容器化 | **Docker** + NVIDIA CUDA 12.4 | 支持 RTX 50 系列 GPU | | 分布式队列 | **PostgreSQL** | 可选,用于多 Worker 批处理 | ### 主要依赖库 - PyTorch(GPU 推理) - OpenCV(图像处理) - NumPy(数值计算) - HuggingFace Transformers(模型加载) --- ## 系统架构 ``` ┌─────────────────────────────────────────────────────────┐ │ Streamlit Web UI (Frontend) │ │ 图像上传 / 参数配置 / 结果可视化展示 │ └─────────────────────┬───────────────────────────────────┘ │ HTTP / REST ┌─────────────────────▼───────────────────────────────────┐ │ Go/Gin 后端 API Server (:8080) │ │ 请求路由 / 文件管理 / 流程编排 / 响应组装 │ └────────┬─────────────────┬──────────────────┬───────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │ SAM3 路径 │ │ DINO 路径 │ │ Pipeline 路径 │ │ (Docker) │ │ (本地 Python) │ │ 三阶段串行流 │ └─────────────┘ └──────────────┘ └──────────────────┘ ``` ### 三种处理路径 ``` SAM3 Mode: 图像 → [Zero-DCE 增强] → SAM3 分割 → 建筑掩码 DINO Mode: 图像对 → LoFTR 配准 → DINOv3 特征比较 → 变化热力图 Pipeline Mode: 图像对 → LoFTR 配准 → SAM3 建筑提取 → DINOv3 差异分析 → 带标注热力图 ``` --- ## 核心模块 ### 入口文件 | 文件 | 说明 | |------|------| | `app.py` | Streamlit 前端,UI 逻辑、文件上传、结果渲染 | | `main.go` | Go 后端,API 接口定义与流程编排 | | `main_dreamsim.py` | DINOv3 差异检测主脚本 | ### `/core/` - 核心推理模块 | 文件 | 说明 | |------|------| | `loftr_engine.py` | LoFTR 引擎:图像配准、特征匹配、单应性变换 | | `sam3.py` | SAM3 分割:模型初始化、Zero-DCE 增强、掩码后处理 | | `main_dreamsim.py` | DINOv3 推理:patch 特征提取、热力图生成 | | `register_all.py` | 批量配准脚本(历史版本) | ### `/worker/` - 分布式 Worker(可选) | 文件 | 说明 | |------|------| | `base_worker.py` | Worker 主循环:轮询 DB → 认领任务 → 执行 → 心跳 | | `launcher.py` | 进程管理器:动态伸缩 N 个 Worker 进程 | | `engine_dreamsim.py` | DreamSim 推理引擎(实现 EngineInterface) | | `engine_sam3.py` | SAM3 推理引擎(实现 EngineInterface) | ### `/shared/` - 共享工具 | 文件 | 说明 | |------|------| | `config.py` | 环境变量统一配置(数据库、模型路径、Worker 扩缩容参数) | | `protocol.py` | 数据结构与抽象(`JobMeta`, `TaskDescriptor`, `EngineInterface`, `ENGINE_REGISTRY`) | ### `/sam3/` - SAM3 独立推理脚本 | 文件 | 说明 | |------|------| | `inference.py` | 独立运行的 SAM3 推理,从 checkpoint 构建模型 | | `sam3_dce.py` | 集成 DCE 增强的 SAM3 变体 | | `sam3_native_dce.py` | 原生 DCE 实现版本 | ### 设计模式 - **工厂模式**:`create_engine()` 创建 LoFTR 实例 - **策略模式**:SAM3 / DINO / Pipeline 三种算法路径 - **注册表模式**:`@register_engine()` 装饰器动态注册推理引擎 - **Worker 池模式**:`launcher.py` 动态进程扩缩容 --- ## 处理流程 以 **Pipeline 模式** 为例,完整端到端流程: ``` 1. 用户上传图像对(前时相 t1 + 后时相 t2) ↓ 2. Streamlit 保存文件至 temp_uploads/,POST 到 Go 后端 ↓ 3. Go 后端解析请求,路由至 handlePipelineAlgo() ↓ 4. [阶段 1] LoFTR 图像配准 - 灰度化 + 缩放至 max_size=1024 - Transformer 特征匹配 → mkpts0_f / mkpts1_f - RANSAC 估计单应性矩阵 H - cv2.warpPerspective() 将后时相对齐到前时相坐标系 - 输出:registered_before.jpg / registered_after.jpg ↓ 5. [阶段 2] SAM3 建筑提取 - docker exec sam3_fixed python3 building_extractor.py - 文本提示 "building" → 掩码 + 置信度 + 边界框 - 置信度过滤(conf_thresh=0.25) - 形态学膨胀 + 填洞后处理 - 输出:building_t1.jpg / building_t2.jpg / mask_*.png ↓ 6. [阶段 3] DINOv3 差异分析 - 空间同步(valid_mask 交集)+ LAB 颜色对齐 - DINOv3 提取 patch 特征(224×224,stride=16) - 余弦相似度 → 距离热力图 - 自适应阈值(μ + 3σ vs. max × peak_ratio 取最大) - 轮廓检测 → 面积过滤 → 矩形框标注 - 输出:result.jpg / result_clean.jpg ↓ 7. Go 后端将输出图像转 Base64,组装 JSON 响应 ↓ 8. Streamlit 展示:配准图对 / 建筑掩码 / 变化热力图 / 日志 ``` --- ## 关键算法 ### 1. LoFTR 图像配准 ``` 输入:before_img, after_img ↓ 灰度化 + 缩放(max_size=1024) ↓ LoFTR Transformer 前向传播 ↓ RANSAC 单应性估计(阈值 5.0px) ↓ 尺度修正(补偿灰度缩放引起的坐标偏移) ↓ cv2.warpPerspective() 透视变换对齐 输出:配准后的后时相图像 ``` ### 2. SAM3 建筑分割 ``` 输入:image, prompt="building" ↓ [可选] Zero-DCE 低光增强(8 次递归亮度曲线调整) ↓ SAM3 图像嵌入 + CLIP 文本嵌入交叉注意力匹配 ↓ 置信度过滤(conf_thresh) ↓ 形态学膨胀 + 填洞 ↓ 建筑区域保留原始像素,背景置黑 输出:建筑提取图 + 二值掩码 ``` ### 3. DINOv3 变化检测 ``` 输入:before_img, after_img(已对齐) ↓ 空间同步:计算 valid_mask 交集,清零无效区域 ↓ LAB 颜色迁移:将 after 的颜色统计对齐到 before ↓ DINOv3 提取空间 patch 特征(L2 归一化) ↓ 余弦距离:D = 1 - cos_similarity(feat1, feat2) ↓ 热力图上采样 + 高斯平滑 ↓ 自适应阈值:max(μ+3σ, max×peak_ratio, dino_conf) ↓ 轮廓检测(面积 > 0.3%)→ 边界框 + 峰值分数标注 输出:变化热力图 + 带标注结果图 ``` ### 4. 自适应阈值策略 系统使用**三层阈值融合**策略,平衡漏检与误检: | 策略 | 公式 | 作用 | |------|------|------| | 统计异常检测 | `μ + 3σ` | 检测统计意义上的显著变化,对全局光照变化鲁棒 | | 峰值比例启发式 | `max × peak_ratio (0.6)` | 定位最显著变化区域,自适应图像内容 | | 绝对下限 | `dino_conf`(用户可调) | 防止低对比度场景的过度平滑 | **最终阈值 = max(统计阈值, 峰值阈值, 绝对下限)** --- ## 启动与调试 ### 前置条件 - Docker + NVIDIA Container Toolkit - NVIDIA GPU(推荐 RTX 30/40/50 系列) - CUDA 12.4+ - Go 1.21+(仅本地开发后端时需要) --- ### 服务组成 系统由三个独立进程构成,需要分别启动: | 服务 | 运行位置 | 端口 | 说明 | |------|----------|------|------| | `diffsim_runner` 容器 | Docker | — | Python 环境主容器 | | Streamlit 前端 | 容器内 | 8501 → 宿主机 8601 | Web UI | | Go 后端 API | 容器内或宿主机 | 8080 | 流程编排服务 | | `sam3_fixed` 容器 | Docker | — | SAM3 推理专用容器(需提前准备) | --- ### 第一步:准备模型权重 ```bash # 在项目根目录创建权重目录 mkdir -p checkpoints # 将以下文件放入 checkpoints/ checkpoints/ ├── sam3.pt # SAM3 模型权重 └── Zero-DCE.pth # Zero-DCE 低光增强权重 ``` DINOv3 权重首次运行时自动从 HuggingFace 下载(已配置国内镜像): ```bash # docker-compose.yaml 中已设置,无需手动操作 HF_ENDPOINT=https://hf-mirror.com ``` --- ### 第二步:创建 Docker 网络 `docker-compose.yaml` 使用外部网络,首次需手动创建: ```bash docker network create diffsim_default ``` --- ### 第三步:构建并启动主容器 ```bash # 构建镜像(首次或 Dockerfile 变更后执行) docker build -t diffsim:latest . # 启动主容器(后台运行,保持待命状态) docker compose up -d # 确认容器已运行 docker ps | grep diffsim_runner ``` --- ### 第四步:启动 Go 后端 ```bash # 进入容器 docker exec -it diffsim_runner bash # 容器内:编译并启动 Go 后端 cd /app go run main.go # 输出:🚀 后端已启动 -> http://localhost:8080 ``` > 如果宿主机已安装 Go,也可以直接在宿主机运行(需确保路径和 Docker Socket 一致): > ```bash > go run main.go > ``` --- ### 第五步:启动 Streamlit 前端 **新开一个终端窗口**,进入容器: ```bash docker exec -it diffsim_runner bash # 容器内:启动 Streamlit cd /app streamlit run app.py --server.port 8501 --server.address 0.0.0.0 ``` 访问 Web UI: ``` http://localhost:8601 ``` --- ### SAM3 容器配置 系统依赖名为 `sam3_fixed` 的独立容器执行建筑分割,需提前准备: ```bash # 确认 SAM3 容器已运行 docker ps | grep sam3_fixed # 若未运行,使用 SAM3 镜像启动(根据实际镜像名调整) docker run -d \ --name sam3_fixed \ --gpus all \ --network diffsim_default \ -v /path/to/sam3/checkpoints:/app/checkpoints \ sam3:latest \ tail -f /dev/null ``` --- ### 快速开始(一键脚本) 进入容器后,可以用以下命令同时启动后端和前端: ```bash docker exec -it diffsim_runner bash -c " cd /app go run main.go & sleep 2 streamlit run app.py --server.port 8501 --server.address 0.0.0.0 " ``` --- ### 调试指南 #### 查看容器日志 ```bash # 查看主容器日志 docker logs -f diffsim_runner # 查看 SAM3 容器日志 docker logs -f sam3_fixed ``` #### Go 后端调试 ```bash # 开启 Gin 调试模式(默认 ReleaseMode,调试时改为 debug) # 修改 main.go 第 119 行: gin.SetMode(gin.DebugMode) # 改这里 # 然后重新运行 go run main.go ``` 调试模式下会输出所有路由注册信息和请求日志。 #### Streamlit 前端调试 ```bash # 开启热重载(代码修改后自动刷新) streamlit run app.py --server.runOnSave true # 关闭文件监视(资源占用高时使用) streamlit run app.py --server.fileWatcherType none ``` #### 手动测试 API ```bash # 测试后端接口是否正常(在容器内或宿主机执行) curl -X POST http://localhost:8080/api/process \ -F "algo_type=SAM3" \ -F "t1=@/path/to/test_image.jpg" \ -F "sam_prompt=building" \ -F "conf_thresh=0.25" ``` #### 手动运行 DINOv3 脚本 ```bash # 容器内直接调用差异检测脚本 docker exec -it diffsim_runner bash cd /app python3 main_dreamsim.py \ /app/data/before.jpg \ /app/data/after.jpg \ /app/data/result.jpg \ --dino_conf 0.2 \ --peak_ratio 0.6 ``` #### 手动运行 SAM3 分割 ```bash # 在 SAM3 容器内执行 docker exec -it sam3_fixed bash cd /app python3 inference.py \ --input /app/data/test.jpg \ --output /app/outputs/ \ --text_prompt "building" \ --conf_thresh 0.25 ``` #### 常见问题排查 | 现象 | 排查方向 | |------|----------| | 前端无响应 / 报错 502 | 检查 Go 后端是否已启动:`curl http://localhost:8080/api/process` | | SAM3 阶段失败 | 检查 `sam3_fixed` 容器是否在运行,网络是否在同一 `diffsim_default` | | CUDA out of memory | 降低 `process_size`,或减少同时运行的模型数量 | | HuggingFace 模型下载超时 | 确认 `HF_ENDPOINT=https://hf-mirror.com` 已设置 | | Go 编译失败 | 执行 `go mod tidy` 更新依赖 | | 图像处理结果全黑 | 检查输入图像路径是否正确,`docker cp` 是否成功 | #### 进入容器交互调试 ```bash # 进入主容器 docker exec -it diffsim_runner bash # 进入 SAM3 容器 docker exec -it sam3_fixed bash # 查看 GPU 使用情况 nvidia-smi # 检查 Python 环境 python3 -c "import torch; print(torch.cuda.is_available(), torch.version.cuda)" ``` ### 模型权重 将以下权重文件放入 `checkpoints/` 目录: ``` checkpoints/ ├── sam3.pt # SAM3 模型权重 └── Zero-DCE.pth # Zero-DCE 低光增强权重 ``` DINOv3 权重通过 HuggingFace 自动下载(需配置镜像或代理): ```bash # 使用国内镜像(已在 docker-compose.yml 中配置) HF_ENDPOINT=https://hf-mirror.com ``` --- ## 配置说明 ### 环境变量(`shared/config.py`) ```bash # 数据库(可选,用于分布式批处理) BATCH_PG_HOST=localhost BATCH_PG_PORT=5432 BATCH_PG_DB=diffsim BATCH_PG_USER=postgres BATCH_PG_PASS=password # Worker 伸缩 MIN_WORKERS_PER_GPU=1 MAX_WORKERS_PER_GPU=4 SCALE_UP_MULTIPLIER=2 SCALE_UP_SUSTAIN_SEC=10 # 模型路径 SAM3_MODEL_PATH=/app/checkpoints/sam3.pt SAM3_DCE_WEIGHTS=/app/checkpoints/Zero-DCE.pth DREAMSIM_MODEL_TYPE=ensemble ``` ### Web UI 参数说明 | 参数 | 说明 | 默认值 | |------|------|--------| | `conf_thresh` | SAM3 分割置信度阈值 | 0.25 | | `dino_conf` | DINOv3 变化检测绝对下限 | 可调 | | `peak_ratio` | 峰值比例阈值系数 | 0.6 | | `process_size` | 处理分辨率(像素) | 1024 | | `DCE 增强` | 是否开启低光增强 | 关闭 | | `SAM prompt` | 分割文本提示词 | "building" | --- ## 目录结构 ``` diffsim/ ├── app.py # Streamlit 前端入口 ├── main.go # Go 后端 API 入口 ├── main_dreamsim.py # DINOv3 差异检测脚本 ├── Dockerfile # CUDA 12.4 + PyTorch 镜像 ├── docker-compose.yml # 容器编排(GPU + 卷映射) ├── config.json # DINOv3 模型配置 ├── preprocessor_config.json # 图像预处理配置 │ ├── core/ # 核心推理模块 │ ├── loftr_engine.py # LoFTR 图像配准引擎 │ ├── sam3.py # SAM3 分割模块 │ └── register_all.py # 批量配准脚本 │ ├── worker/ # 分布式 Worker(可选) │ ├── base_worker.py # Worker 基类与主循环 │ ├── launcher.py # 进程管理器 │ ├── engine_dreamsim.py # DreamSim 引擎 │ └── engine_sam3.py # SAM3 引擎 │ ├── shared/ # 共享工具 │ ├── config.py # 统一配置管理 │ └── protocol.py # 数据结构与接口定义 │ ├── sam3/ # SAM3 独立脚本 │ ├── inference.py # SAM3 推理入口 │ ├── sam3_dce.py # DCE 增强版本 │ └── sam3_native_dce.py # 原生 DCE 版本 │ ├── data/ # 输入图像目录 ├── checkpoints/ # 模型权重 └── hf_cache/ # HuggingFace 模型缓存 ``` --- ## 性能参考 | 指标 | 参考值 | |------|--------| | 单对图像处理时间 | 约 2-5 秒(GPU 推理) | | 推荐输入分辨率 | 512×512 ~ 2048×2048 | | 最大处理分辨率 | 1024px(可配置) | | GPU 显存需求 | 约 6GB+(所有模型同时加载) |