diff --git a/README.md b/README.md index 8a773e5..db83cf8 100755 --- a/README.md +++ b/README.md @@ -1,22 +1,38 @@ -# ApDepth: Aiming for Precise Monocular Depth Estimation Based on Diffusion Models +
+

ApDepth

+

Aiming for Precise Monocular Depth Estimation Based on Diffusion Models

+
-This repository is based on [Marigold](https://marigoldmonodepth.github.io), CVPR 2024 Best Paper: [**Repurposing Diffusion-Based Image Generators for Monocular Depth Estimation**](https://arxiv.org/abs/2312.02145) +

+ ApDepth V2.1  + Project website  + Paper and citation  + Live demo  + Model weights  + Training recipes +

-[![Website](doc/badges/badge-website.svg)](https://haruko386.github.io/research) -[![License](https://img.shields.io/badge/License-Apache--2.0-929292)](https://www.apache.org/licenses/LICENSE-2.0) -[![Hugging Face Model](https://img.shields.io/badge/🤗%20Hugging%20Face-Model-green)](https://huggingface.co/developy/ApDepth) -[![Hugging Face Demo](https://img.shields.io/badge/🤗%20Hugging%20Face-Demo-purple)](https://huggingface.co/spaces/developy/ApDepth) +--- - +![ApDepth monocular depth estimation examples](doc/cover.png) -![cover](doc/cover.png) +## Overview -> We present **ApDepth**, a deterministic single-step diffusion framework for monocular depth estimation. Built upon Marigold (derived from Stable Diffusion) and fine-tuned on synthetic datasets (Hypersim and Virtual KITTI), ApDepth overcomes the feature representation bottlenecks of standard diffusion models. Ultimately, our framework achieves **highly competitive geometric accuracy** and **exceptional object edge refinement**, all while delivering significantly accelerated inference speeds. +**ApDepth** turns Stable Diffusion 2.1 into a deterministic, single-step +monocular depth estimator. It combines a frozen Depth Anything V2 prior with a +fine-tuned diffusion U-Net to recover accurate scene geometry and crisp object +boundaries without iterative denoising. -## 📢 News +> [!IMPORTANT] +> +> ApDepth builds on [**Marigold**](https://marigoldmonodepth.github.io), the +> CVPR 2024 Best Paper [*Repurposing Diffusion-Based Image Generators for +> Monocular Depth Estimation*](https://arxiv.org/abs/2312.02145). + +## News + +- **2026-09-22:** Preparing **ApDepth V2-1** with direct SD2.1 fine-tuning, + SDWT and optional FFT refinement. - **2026-04-06:** `ApDepth V2-0` is released! - **2026-04-03:** We officially release the code for **ApDepth**! Stage 1 feature-alignment training is maintained in [ApDepth_Stage1](https://github.com/Haruko386/ApDepth_Stage1); this repository provides Stage 2 training, inference and evaluation. - **2026-01-15:** We successfully introduce a spatial-preserving **Conv Adapter** and a **Cosine Similarity Loss** to enhance feature alignment, alongside a **Pixel-level $L_1$ Loss** to establish an accurate global metric scale. @@ -26,26 +42,23 @@ This repository is based on [Marigold](https://marigoldmonodepth.github.io), CVP - **2025-08-10:** Trying to make some optimizations in Feature Expression. - **2025-05-08:** Clone `Marigold` to local. -## 🚀 Usage - -**We offer several ways to interact with ApDepth**: - -1. A free online interactive demo is available here: +## Quick start -2. If you just want to see the examples, visit our gallery: +Try ApDepth in the [live demo](https://huggingface.co/spaces/developy/ApDepth), +browse the [project gallery](https://haruko386.github.io/research), or run it +locally using the instructions below. -3. Local development instructions with this codebase are given below. +### Requirements -## 🛠️ Setup -The Model was trained on: +The model was trained on: - Ubuntu 22.04 LTS, Python 3.12.9, CUDA 11.8, `NVIDIA RTX 6000 Ada Generation` -The inference code was tested on: +Inference was tested on: - Ubuntu 22.04 LTS, Python 3.12.9, CUDA 11.8, `NVIDIA GeForce RTX 4090` -### 🪧 A Note for Windows users +#### Windows We recommend running the code in WSL2: @@ -53,7 +66,7 @@ We recommend running the code in WSL2: 1. Install CUDA support for WSL following [installation guide](https://docs.nvidia.com/cuda/wsl-user-guide/index.html#cuda-support-for-wsl-2). 1. Find your drives in `/mnt//`; check [WSL FAQ](https://learn.microsoft.com/en-us/windows/wsl/faq#how-do-i-access-my-c--drive-) for more details. Navigate to the working directory of choice. -### 📦 Repository +### Installation Clone the repository (requires git): @@ -62,10 +75,9 @@ git clone https://github.com/Haruko386/ApDepth.git cd ApDepth ``` -### 💻 Dependencies +#### Conda - **Using Conda:** - Alternatively, create a Python native virtual environment and install dependencies into it: +Create and activate the project environment: ```bash conda create -n apdepth python==3.12.9 @@ -78,7 +90,7 @@ pip install -r requirements.txt > Keep the environment activated before running the inference script. > Activate the environment again after restarting the terminal session. -### 🐳 Docker Setup +### Docker For a streamlined setup, we provide a Docker environment that pre-installs all necessary dependencies, including PyTorch, CUDA, and evaluation tools. @@ -94,22 +106,24 @@ docker build -t apdepth:latest . To utilize GPU acceleration, ensure the NVIDIA Container Toolkit is installed. We recommend mounting your local input and output directories to easily access your inference results: -```Bash +```bash docker run --gpus all -it --rm \ -v $(pwd)/input:/workspace/ApDepth/input \ -v $(pwd)/output:/workspace/ApDepth/output \ apdepth:latest -Once inside the container, the apdepth conda environment is activated by default, and you can directly execute the inference or training scripts. ``` -## 🏃 Testing on your images -### 📷 Prepare images +Inside the container, the `apdepth` Conda environment is activated automatically. + +## Inference + +### Prepare images 1. Use selected images under `input` 1. Or place your images in a directory, for example, under `input/test-image`, and run the following inference command. -### 🎮 Run inference with paper setting +### Paper setting This setting corresponds to our paper. For academic comparison, please run with this setting. @@ -124,7 +138,7 @@ python run.py \ You can find all results in `output/example-1`. Enjoy! -### ⚙️ Inference settings +### Inference options The default settings are optimized for the best result. However, the behavior of the code can be customized: @@ -140,7 +154,7 @@ The default settings are optimized for the best result. However, the behavior of - `--color_map`: [Colormap](https://matplotlib.org/stable/users/explain/colors/colormaps.html) used to colorize the depth prediction. Default: Spectral. Set to `None` to skip colored depth map generation. - `--apple_silicon`: Use Apple Silicon MPS acceleration. -## 🦿 Evaluation on test datasets +## Evaluation Install additional dependencies: @@ -180,11 +194,21 @@ You can get the result under `output/eval` -## 🏋️ Training +## Training -The workflow is **Stage 1 feature alignment → Stage 2 main training → optional -[VKITTI far-depth post-training](#post-training)**. Complete Stage 2, including -its FFT refinement, before starting the optional post-training run. +Three training methods are retained. The mixed SDWT + FFT method is the +recommended recipe; the SDWT-only method is kept for controlled comparison, and the +original Stage 1 + legacy FFT workflow remains reproducible. + +| Method | Initialization | Objective | Config | +| --- | --- | --- | --- | +| 1. Mixed SDWT + FFT (recommended) | Original SD2.1 | MSE + pixel L1 + gradient, then gradual SDWT + low-weight FFT | `config/train_sd2_sdwt_fft.yaml` | +| 2. SDWT only | Original SD2.1 | MSE + pixel L1 + gradient, then gradual SDWT | `config/train_sd2_sdwt.yaml` | +| 3. Legacy ApDepth/FFT | Stage 1 U-Net checkpoint | Reconstruction, then the original latent FFT transition | `config/train_apdepth.yaml` | + +Methods 1 and 2 are single-run Stage 2 training methods and do not execute or +load Stage 1. Their implementation details and ablations are documented +[here](doc/sd2_sdwt_training.md). Based on the previously created environment, install extended requirements: @@ -207,19 +231,62 @@ Prepare [Hypersim](https://github.com/apple/ml-hypersim) and [Virtual KITTI 2](h ------------ -**Stage 1: feature alignment pre-training** +### Method 1: direct SD2 training with SDWT + FFT (recommended) -Stage 1 is maintained separately in -[Haruko386/ApDepth_Stage1](https://github.com/Haruko386/ApDepth_Stage1). -Follow that repository's setup and training instructions. This repository contains -only the main Stage 2 trainer; it does not include Stage 1 code or dependencies. +This method starts from the original SD2.1 weights. During iterations 0-8,000, +it learns the basic depth mapping with latent MSE, pixel L1 and gradient loss. +From iteration 8,000 to 12,000, SDWT increases from 0 to 1.0 while latent +FFT increases from 0 to 0.2. The reconstruction losses remain active for the +rest of training, and the VAE decoder is fine-tuned from iteration 8,000. ------------- +SDWT matches local depth distributions with an explicit pixel-displacement +cost. It subtracts entropic self-costs, evaluates both regular and half-window +shifted grids, and weights each window by its valid support. These changes keep +limited tolerance to noisy boundary labels without making the loss invariant to +arbitrary permutations inside a window. + +```bash +python train.py --config config/train_sd2_sdwt_fft.yaml --no_wandb +``` + +Do not pass `--init_checkpoint`. Resume an interrupted run with: + +```bash +python train.py \ + --resume_run output/train_sd2_sdwt_fft/checkpoint/latest --no_wandb +``` + +### Method 2: direct SD2 training with SDWT only + +This method uses the same original SD2.1 initialization, reconstruction-loss +schedule and VAE decoder adaptation as Method 1, but leaves latent FFT disabled. +It is the direct comparison for measuring the contribution of FFT. + +```bash +python train.py --config config/train_sd2_sdwt.yaml --no_wandb +``` + +Do not pass `--init_checkpoint`. Resume an interrupted run with: + +```bash +python train.py \ + --resume_run output/train_sd2_sdwt/checkpoint/latest --no_wandb +``` -**Stage 2: main ApDepth training** +For both direct-SD2 methods, `BASE_CKPT_DIR/stable-diffusion-2-1` must contain +the original SD2.1 Diffusers pipeline. Their checkpoints save both the U-Net and +the fine-tuned VAE. -To initialize Stage 2 from an existing Stage 1 checkpoint, start a new run with -`--init_checkpoint`. This loads only the U-Net; optimizer and iteration counters +### Method 3: legacy Stage 1 + ApDepth/FFT training (ApDepth v2-0) + +First complete the feature-alignment Stage 1 training. Stage 1 is maintained +separately in +[Haruko386/ApDepth_Stage1](https://github.com/Haruko386/ApDepth_Stage1). +Follow that repository's setup and training instructions. This repository contains +the legacy Stage 2 trainer, but does not include Stage 1 code or dependencies. + +Then initialize the legacy Stage 2 from the Stage 1 checkpoint with +`--init_checkpoint`. This loads the U-Net and a saved VAE if present; optimizer and iteration counters start fresh using the Stage 2 config. `config/train_apdepth.yaml` keeps far-depth supervision disabled throughout the main training stage: @@ -232,12 +299,6 @@ The initialization directory must contain `unet/diffusion_pytorch_model.safetensors`. `--init_checkpoint` rejects `.bin` checkpoints. -To train the main stage directly from the base model without Stage 1 initialization: - -```bash -python train.py --config config/train_apdepth.yaml --no_wandb -``` - The transition to latent frequency loss is controlled by `latent_freq_loss.gradual_transition` in `config/train_apdepth.yaml`. When `true`, the reconstruction loss weight decreases linearly from 1 to 0 between iteration @@ -252,13 +313,30 @@ Resume from a checkpoint, e.g. python train.py --resume_run output/train_apdepth/checkpoint/latest --no_wandb ``` +### Inference after Method 1 or Method 2 + +Direct-SD2 checkpoints are training-component checkpoints, so inference combines +the original SD2.1 pipeline with the saved U-Net and VAE. For Method 1: + +```bash +python run.py --checkpoint "${BASE_CKPT_DIR}/stable-diffusion-2-1" \ + --training_checkpoint output/train_sd2_sdwt_fft/checkpoint/iter_021000 \ + --input_rgb_dir input/example-1 --output_dir output/sd2_sdwt_fft \ + --ensemble_size 1 --processing_res 0 +``` + +For Method 2, replace `train_sd2_sdwt_fft` with `train_sd2_sdwt` in the checkpoint +path. `infer.py` also accepts `--training_checkpoint` for dataset evaluation. + ------------ -## 🌤️ Optional post-training after Stage 2 +## Optional post-training after Stage 2 **Start this step only after Stage 2 training has finished.** The new VKITTI far-depth supervision feature is enabled by `config/train_sky_finetune.yaml` for -a separate post-training run initialized from the completed Stage 2 U-Net. +a separate post-training run initialized from a completed checkpoint from any +of the three methods. For Methods 1 and 2, the saved VAE is loaded and retained +together with the U-Net. Measured depths in [80, 655.35] m supply an additional clipped far-depth target before VAE encoding; missing depth remains excluded. Evaluation masks and @@ -279,12 +357,19 @@ If preprocessing replaced the far-plane values with zero, restore the original depth files. Zero depth is not treated as sky. Adjust each dataset config's `dir` to match the actual layout under `BASE_DATA_DIR`. -Start a new post-training run from the final Stage 2 checkpoint (adjust the path -if Stage 2 was saved elsewhere): +Select the corresponding completed checkpoint: + +| Method | Example checkpoint | +| --- | --- | +| 1. SDWT + FFT | `output/train_sd2_sdwt_fft/checkpoint/iter_021000` | +| 2. SDWT only | `output/train_sd2_sdwt/checkpoint/iter_021000` | +| 3. Legacy ApDepth/FFT | `output/train_apdepth/checkpoint/iter_021000` | + +Then start a new post-training run, adjusting the path if needed: ```bash python train.py --config config/train_sky_finetune.yaml \ - --init_checkpoint output/train_apdepth/checkpoint/iter_021000 --no_wandb + --init_checkpoint /path/to/completed/checkpoint/iter_021000 --no_wandb ``` This resets the optimizer, learning-rate schedule and iteration counter, then @@ -292,7 +377,7 @@ runs 6000 new optimization steps at LR 5e-6 with 100 warmup steps and saves backups every 1000 steps in `output/train_sky_finetune/checkpoint`. It retains the 90% Hypersim / 10% VKITTI sampling, original batch settings and periodic validation. These 6000 steps use latent MSE + pixel L1 reconstruction plus the new far-depth -loss; the Stage 2 FFT refinement has already finished. Initialization requires +loss; the selected Stage 2 objective has already finished. Initialization requires `unet/diffusion_pytorch_model.safetensors` in the supplied checkpoint directory. If this post-training run is interrupted, resume its own checkpoint: @@ -312,7 +397,11 @@ alone does not establish a metric improvement. ## Evaluating trained checkpoints -Stage 2 and optional post-training update and save the U-Net. For inference, copy a complete +The new direct-SD2 recipe saves both U-Net and VAE; use `--training_checkpoint` +as shown above to load them together. The following instructions apply to legacy +U-Net-only checkpoints. + +Legacy Stage 2 and optional post-training update and save the U-Net. For inference, copy a complete ApDepth pipeline checkpoint to a new directory, then replace that copy's `unet/` folder with the selected training checkpoint's `unet/`. The pipeline's VAE, tokenizer, text encoder and scheduler are still required; a training checkpoint @@ -324,11 +413,11 @@ alone is not a complete inference pipeline. Then refer to [evaluation](#evaluati -## ✏️ Contributing +## Contributing Please refer to [this](CONTRIBUTING.md) instruction. -## 🤔 Troubleshooting +## Troubleshooting | Problem | Solution | | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | @@ -341,7 +430,7 @@ Please refer to [this](CONTRIBUTING.md) instruction. -## 🎓 Citation +## Citation Please cite our paper: ```bibtex @@ -353,10 +442,8 @@ Please cite our paper: } ``` -## 🎫 License +## License This work is licensed under the Apache License, Version 2.0 (as defined in the [LICENSE](LICENSE.txt)). -By downloading and using the code and model you agree to the terms in the [LICENSE](LICENSE.txt). - -[![License](https://img.shields.io/badge/License-Apache--2.0-929292)](https://www.apache.org/licenses/LICENSE-2.0) +By downloading and using the code and model you agree to the terms in the [LICENSE](LICENSE.txt). diff --git a/doc/badges/v21-demo.svg b/doc/badges/v21-demo.svg new file mode 100644 index 0000000..d821362 --- /dev/null +++ b/doc/badges/v21-demo.svg @@ -0,0 +1,7 @@ + + Live demo + + + + Live Demo + diff --git a/doc/badges/v21-paper.svg b/doc/badges/v21-paper.svg new file mode 100644 index 0000000..bce8d0a --- /dev/null +++ b/doc/badges/v21-paper.svg @@ -0,0 +1,7 @@ + + Paper and citation + + + + Paper + diff --git a/doc/badges/v21-training.svg b/doc/badges/v21-training.svg new file mode 100644 index 0000000..524748a --- /dev/null +++ b/doc/badges/v21-training.svg @@ -0,0 +1,7 @@ + + Training recipes + + + + Training + diff --git a/doc/badges/v21-version.svg b/doc/badges/v21-version.svg new file mode 100644 index 0000000..c127127 --- /dev/null +++ b/doc/badges/v21-version.svg @@ -0,0 +1,7 @@ + + ApDepth v2-1 + + + + v2-1 + diff --git a/doc/badges/v21-website.svg b/doc/badges/v21-website.svg new file mode 100644 index 0000000..8ba559a --- /dev/null +++ b/doc/badges/v21-website.svg @@ -0,0 +1,7 @@ + + Project website + + + + Website + diff --git a/doc/badges/v21-weights.svg b/doc/badges/v21-weights.svg new file mode 100644 index 0000000..7c7ccc0 --- /dev/null +++ b/doc/badges/v21-weights.svg @@ -0,0 +1,7 @@ + + Model weights + + + + Weights + diff --git a/doc/cover.jpg b/doc/cover.jpg deleted file mode 100644 index a445bff..0000000 Binary files a/doc/cover.jpg and /dev/null differ diff --git a/doc/sd2_sdwt_training.md b/doc/sd2_sdwt_training.md new file mode 100644 index 0000000..21ed4e5 --- /dev/null +++ b/doc/sd2_sdwt_training.md @@ -0,0 +1,140 @@ +# 从原版 SD2 直接训练:SDWT 二阶段方案 + +本方案从原始 Stable Diffusion 2.1 权重直接开始一次连续训练,不依赖一阶段 +checkpoint。前 8,000 步使用 latent MSE、pixel L1 和梯度损失建立基本深度映射; +8,000 至 12,000 步逐渐加入本文的 **Spatially Debiased Window Transport +(SDWT) Loss** 并解冻 VAE decoder。 + +SDWT 受到 Marigold V2 局部最优传输思路的启发,但不是 SinkLoss 的改名版本。 +它针对原方法的四个限制重新定义了代价、目标函数、窗口划分和聚合方式。 + +## 原局部匹配的限制 + +1. **忽略空间位置。** 仅使用深度差构造代价时,同一窗口内任意像素排列都可能 + 获得近似相同的损失。它能容忍边缘标注错位,也可能接受错误的局部几何。 +2. **熵偏差。** 带熵正则的交叉传输成本在预测等于真值时通常仍不为零,损失的 + 数值和梯度会受温度影响。 +3. **固定窗口接缝。** 非重叠窗口无法匹配落在相邻窗口两侧的同一条边缘。 +4. **稀疏窗口权重过大。** 按非空窗口平均时,只有一个有效像素的窗口与完整窗口 + 权重相同。 + +## SDWT + +对窗口中的预测深度 `p_i`、目标深度 `g_j` 和归一化坐标 `x_i`、`x_j`, +SDWT 使用联合代价 + +```text +C_ij = rho(p_i - g_j) + lambda_s * ||x_i - x_j||_1 +rho(e) = sqrt(e^2 + epsilon^2) - epsilon +``` + +其中空间项限制远距离交换,Charbonnier 项在零点平滑,同时保留对异常深度误差 +的鲁棒性。无效像素在构造传输矩阵之前被精确移除,不再用极大哨兵值参与 +Sinkhorn 归一化。 + +令带熵正则的局部传输目标为 `OT_tau(A, B)`,最终目标使用去偏形式 + +```text +SDWT(A, B) = OT_tau(A, B) + - 0.5 * OT_tau(A, A) + - 0.5 * OT_tau(B, B) +``` + +因此相同预测和目标的损失为零。每张图同时计算原始窗口网格和偏移半个窗口的 +网格,以覆盖原网格边界;最后按每个窗口的有效像素数聚合。默认参数为 5×5 +窗口、10 次传输归一化、温度 0.1、空间权重 0.15。 + +去偏项和双网格需要额外的传输计算,因此 SDWT 会比单次局部匹配更慢。实现按 +有效像素数分组、分块计算并使用激活重算,目标自传输项不建立梯度图,以限制显存 +增长。论文实验应同时报告训练吞吐与峰值显存。 + +## 总训练目标 + +令已完成更新数为 `s`: + +```text +r = clip((s - 8000) / 4000, 0, 1) + +L = (1 - 0.5r) L_latent_MSE + + (1 - 0.75r) L_pixel_L1 + + (0.5 - 0.4r) L_gradient + + r L_SDWT +``` + +- `s < 8000`:训练 U-Net,VAE 保持冻结。 +- `8000 <= s < 12000`:逐渐加入 SDWT,并开始微调 decoder 和 + `post_quant_conv`。 +- `s >= 12000`:保留全部基础重建项,SDWT 权重保持 1.0。 + +推荐配置额外将 latent FFT 从 0 渐增到 0.2。FFT 约束全局频谱,SDWT 处理带 +有限位移容忍度的局部几何,两者作用不同。上述超参数是 SD2 的实验起点,需要 +通过验证集和消融实验确定最终论文设置。 + +## 训练 + +推荐的 SDWT + FFT: + +```bash +python train.py --config config/train_sd2_sdwt_fft.yaml --no_wandb +``` + +不使用 FFT 的对照: + +```bash +python train.py --config config/train_sd2_sdwt.yaml --no_wandb +``` + +这两个配置都不能传入 `--init_checkpoint`。恢复训练: + +```bash +python train.py \ + --resume_run output/train_sd2_sdwt_fft/checkpoint/latest --no_wandb +``` + +推理时组合原始 SD2.1、训练后的 U-Net 和 VAE: + +```bash +python run.py --checkpoint /path/to/stable-diffusion-2-1 \ + --training_checkpoint output/train_sd2_sdwt_fft/checkpoint/iter_021000 \ + --input_rgb_dir input/example-1 --output_dir output/sd2_sdwt_fft \ + --ensemble_size 1 --processing_res 0 +``` + +## 论文消融 + +所有实验应保持初始化、数据、随机种子、训练步数与评估协议一致。 + +| 配置 | 验证内容 | +| --- | --- | +| `config/train_sd2_sdwt_fft.yaml` | 完整 SDWT + FFT | +| `config/train_sd2_sdwt.yaml` | 去除 FFT | +| `config/ablation/sd2_sdwt_no_transport.yaml` | 去除整个 SDWT 项 | +| `config/ablation/sd2_sdwt_no_spatial.yaml` | 去除空间位移代价 | +| `config/ablation/sd2_sdwt_no_debias.yaml` | 去除自成本校正 | +| `config/ablation/sd2_sdwt_single_grid.yaml` | 去除半窗口偏移网格 | +| `config/ablation/sd2_sdwt_equal_windows.yaml` | 改回非空窗口等权 | +| `config/ablation/sd2_sdwt_no_decoder.yaml` | 保持 VAE decoder 冻结 | + +除常规 AbsRel 和 delta1 外,应报告边缘指标、细结构区域指标、不同有效像素率区间 +的误差,以及训练显存和耗时。只有在完整方法相对各项消融取得可重复改进后,才能 +把这些设计写成实证贡献。 + +TensorBoard 记录 `train/sdwt_loss`、`train/sdwt_weight`、 +`train/gradient_loss`、`train/latent_mse`、`train/pixel_l1` 和 +`train/freq_loss_weight`。 + +CPU 验证: + +```bash +python -m pytest tests/test_sdwt_training.py -q +``` + +## 方法来源 + +局部最优传输的研究方向来自: + +> Pavlovic et al., “Marigold V2: Revisiting Diffusion Transformers for +> Monocular Depth Estimation,” 2026, arXiv:2609.08084. + +论文写作中应明确引用该工作,并将 SDWT 表述为空间约束、去偏、双网格和 +有效支持聚合方面的扩展。 diff --git a/input/example-0/01.jpg b/input/example-0/01.jpg new file mode 100644 index 0000000..9721ec4 Binary files /dev/null and b/input/example-0/01.jpg differ diff --git a/input/example-0/02.png b/input/example-0/02.png new file mode 100644 index 0000000..b1098e5 Binary files /dev/null and b/input/example-0/02.png differ diff --git a/input/example-0/03.jpg b/input/example-0/03.jpg new file mode 100644 index 0000000..253d9da Binary files /dev/null and b/input/example-0/03.jpg differ diff --git a/input/example-0/04.jpg b/input/example-0/04.jpg new file mode 100644 index 0000000..10d877d Binary files /dev/null and b/input/example-0/04.jpg differ diff --git a/input/example-0/05.jpg b/input/example-0/05.jpg new file mode 100644 index 0000000..fab3862 Binary files /dev/null and b/input/example-0/05.jpg differ diff --git a/input/example-0/06.jpg b/input/example-0/06.jpg new file mode 100644 index 0000000..a1c5482 Binary files /dev/null and b/input/example-0/06.jpg differ