初始上传:珊瑚语义分割项目(代码+模型+数据)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +0 -0
- README.md +138 -0
- coral_seg/README.md +106 -0
- coral_seg/configs/final_dual.yaml +58 -0
- coral_seg/coral_seg/__init__.py +2 -0
- coral_seg/coral_seg/__pycache__/__init__.cpython-312.pyc +0 -0
- coral_seg/coral_seg/__pycache__/dataset.cpython-312.pyc +0 -0
- coral_seg/coral_seg/__pycache__/losses.cpython-312.pyc +0 -0
- coral_seg/coral_seg/__pycache__/model_convnext_fpn.cpython-312.pyc +0 -0
- coral_seg/coral_seg/__pycache__/splits.cpython-312.pyc +0 -0
- coral_seg/coral_seg/__pycache__/utils.cpython-312.pyc +0 -0
- coral_seg/coral_seg/dataset.py +144 -0
- coral_seg/coral_seg/losses.py +101 -0
- coral_seg/coral_seg/model_convnext_fpn.py +82 -0
- coral_seg/coral_seg/splits.py +44 -0
- coral_seg/coral_seg/utils.py +140 -0
- coral_seg/docs/operation-guide.md +575 -0
- coral_seg/docs/technical-report.md +566 -0
- coral_seg/logs/convnext_train.log +0 -0
- coral_seg/logs/mask2former_train.log +0 -0
- coral_seg/pretrained/convnext_large-ea097f82.pth +3 -0
- coral_seg/pretrained/mask2former-swin-base-ade-semantic/.gitattributes +34 -0
- coral_seg/pretrained/mask2former-swin-base-ade-semantic/config.json +454 -0
- coral_seg/pretrained/mask2former-swin-base-ade-semantic/model.safetensors +3 -0
- coral_seg/pretrained/mask2former-swin-base-ade-semantic/preprocessor_config.json +27 -0
- coral_seg/pretrained/mask2former-swin-base-ade-semantic/pytorch_model.bin +3 -0
- coral_seg/requirements.txt +11 -0
- coral_seg/splits/train.txt +2550 -0
- coral_seg/splits/train_full.txt +3000 -0
- coral_seg/splits/val.txt +450 -0
- coral_seg/submissions/results.zip +3 -0
- coral_seg/tools/__pycache__/check_data.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/create_splits.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/download_pretrained.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/eval_ensemble_val.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/eval_predictions.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/infer_ensemble.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/train_convnext.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/train_mask2former.cpython-312.pyc +0 -0
- coral_seg/tools/__pycache__/visualize_results.cpython-312.pyc +0 -0
- coral_seg/tools/check_data.py +35 -0
- coral_seg/tools/create_splits.py +31 -0
- coral_seg/tools/download_pretrained.py +54 -0
- coral_seg/tools/eval_ensemble_val.py +90 -0
- coral_seg/tools/eval_predictions.py +99 -0
- coral_seg/tools/infer_ensemble.py +189 -0
- coral_seg/tools/train_convnext.py +212 -0
- coral_seg/tools/train_mask2former.py +226 -0
- coral_seg/tools/visualize_results.py +102 -0
- coral_seg/vis_results/image_0001.png +3 -0
.gitattributes
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
tags:
|
| 3 |
+
- image-segmentation
|
| 4 |
+
- semantic-segmentation
|
| 5 |
+
- coral
|
| 6 |
+
- underwater
|
| 7 |
+
- pytorch
|
| 8 |
+
- convnext
|
| 9 |
+
- mask2former
|
| 10 |
+
license: mit
|
| 11 |
+
language:
|
| 12 |
+
- zh
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# 珊瑚语义分割(Coral Segmentation)
|
| 16 |
+
|
| 17 |
+
水下珊瑚遥感图像语义分割项目,采用 **Mask2Former-Swin-B + ConvNeXt-L-FPN** 双模型融合方案,将 `256×256` RGB 水下图像分割为四类:
|
| 18 |
+
|
| 19 |
+
| 类别编号 | 类别名称 | 说明 |
|
| 20 |
+
|---------|---------|------|
|
| 21 |
+
| 0 | 背景 | 非珊瑚区域 |
|
| 22 |
+
| 1 | 活珊瑚 | 健康存活的珊瑚 |
|
| 23 |
+
| 2 | 死珊瑚 | 已死亡的珊瑚 |
|
| 24 |
+
| 3 | 白化珊瑚 | 白化状态的珊瑚 |
|
| 25 |
+
|
| 26 |
+
## 项目结构
|
| 27 |
+
|
| 28 |
+
```
|
| 29 |
+
coral-segmentation/
|
| 30 |
+
├── coral_seg/ # 核心代码与模型
|
| 31 |
+
│ ├── coral_seg/ # Python 包(数据集、模型、损失函数)
|
| 32 |
+
│ ├── configs/ # 训练配置(final_dual.yaml)
|
| 33 |
+
│ ├── tools/ # 训练、推理、评测、可视化脚本
|
| 34 |
+
│ ├── pretrained/ # 预训练权重
|
| 35 |
+
│ ├── work_dirs/ # 训练好的模型 checkpoint
|
| 36 |
+
│ ├── splits/ # 训练/验证集划分
|
| 37 |
+
│ ├── vis_results/ # 可视化结果示例
|
| 38 |
+
│ ├── submissions/ # 推理输出(results.zip)
|
| 39 |
+
│ ├── docs/ # 技术报告与操作指南
|
| 40 |
+
│ └── logs/ # 训练日志
|
| 41 |
+
├── data_fresh/ # 原始数据
|
| 42 |
+
│ ├── train_bsdtar/ # 训练数据
|
| 43 |
+
│ └── test_raw/ # 测试数据
|
| 44 |
+
└── README.md
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
## 模型方案
|
| 48 |
+
|
| 49 |
+
### ConvNeXt-L-FPN
|
| 50 |
+
|
| 51 |
+
- **骨干网络**:ConvNeXt-Large(ImageNet-1K 预训练)
|
| 52 |
+
- **解码器**:FPN(Feature Pyramid Network),四尺度特征融合
|
| 53 |
+
- **输入尺寸**:512×512
|
| 54 |
+
- **训练**:120 epochs,AdamW,lr=6e-5,混合精度
|
| 55 |
+
|
| 56 |
+
### Mask2Former-Swin-B
|
| 57 |
+
|
| 58 |
+
- **骨干网络**:Swin Transformer Base(ADE20K 预训练)
|
| 59 |
+
- **解码器**:Mask2Former mask classification
|
| 60 |
+
- **输入尺寸**:384×384
|
| 61 |
+
- **训练**:80 epochs,AdamW,lr=3e-5,梯度检查点
|
| 62 |
+
|
| 63 |
+
### 融合推理
|
| 64 |
+
|
| 65 |
+
```
|
| 66 |
+
prob = 0.55 × prob_mask2former + 0.45 × prob_convnext
|
| 67 |
+
pred = argmax(prob)
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
支持 TTA(原图 + 水平翻转)。
|
| 71 |
+
|
| 72 |
+
## 环境安装
|
| 73 |
+
|
| 74 |
+
```bash
|
| 75 |
+
pip install -r coral_seg/requirements.txt
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
主要依赖:
|
| 79 |
+
|
| 80 |
+
- PyTorch 2.3.0
|
| 81 |
+
- Transformers 4.46.3
|
| 82 |
+
- timm 1.0.27
|
| 83 |
+
- albumentations 2.0.8
|
| 84 |
+
|
| 85 |
+
## 快速开始
|
| 86 |
+
|
| 87 |
+
### 1. 检查数据
|
| 88 |
+
|
| 89 |
+
```bash
|
| 90 |
+
python coral_seg/tools/check_data.py --config coral_seg/configs/final_dual.yaml
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
### 2. 训练 ConvNeXt-L-FPN
|
| 94 |
+
|
| 95 |
+
```bash
|
| 96 |
+
python coral_seg/tools/train_convnext.py --config coral_seg/configs/final_dual.yaml
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
### 3. 训练 Mask2Former-Swin-B
|
| 100 |
+
|
| 101 |
+
```bash
|
| 102 |
+
python coral_seg/tools/train_mask2former.py --config coral_seg/configs/final_dual.yaml
|
| 103 |
+
```
|
| 104 |
+
|
| 105 |
+
### 4. 融合推理
|
| 106 |
+
|
| 107 |
+
```bash
|
| 108 |
+
python coral_seg/tools/infer_ensemble.py \
|
| 109 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 110 |
+
--convnext-checkpoint coral_seg/work_dirs/convnext_l_fpn/best.pth \
|
| 111 |
+
--mask2former-checkpoint coral_seg/work_dirs/mask2former_swin_b/best_hf
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
### 5. 验证集评测
|
| 115 |
+
|
| 116 |
+
```bash
|
| 117 |
+
python coral_seg/tools/eval_ensemble_val.py --config coral_seg/configs/final_dual.yaml
|
| 118 |
+
```
|
| 119 |
+
|
| 120 |
+
## 训练策略
|
| 121 |
+
|
| 122 |
+
- **损失函数**:CE + Dice + 0.5×Lovasz(ConvNeXt);Mask2Former 内置组合损失
|
| 123 |
+
- **Label Smoothing**:0.05
|
| 124 |
+
- **学习率调度**:warmup + cosine decay
|
| 125 |
+
- **骨干网络低学习率**:ConvNeXt backbone 使用 0.25× 基础学习率
|
| 126 |
+
- **数据增强**:翻转、旋转、仿射变换、亮度/对比度/饱和度扰动、CLAHE、高斯模糊、运动模糊
|
| 127 |
+
|
| 128 |
+
## 复现条件
|
| 129 |
+
|
| 130 |
+
- GPU:A30 24GB(或同等显存)
|
| 131 |
+
- 训练+推理总时间 < 24 小时
|
| 132 |
+
- 固定随机种子(seed: 2026)
|
| 133 |
+
- 固定 train/val split
|
| 134 |
+
|
| 135 |
+
## 文档
|
| 136 |
+
|
| 137 |
+
- [操作指南](coral_seg/docs/operation-guide.md) — 完整的部署、训练、推理流程
|
| 138 |
+
- [技术报告](coral_seg/docs/technical-report.md) — 算法设计、模型选择、损失函数等技术细节
|
coral_seg/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 珊瑚语义分割项目说明
|
| 2 |
+
|
| 3 |
+
本项目用于完成水下珊瑚遥感图像语义分割任务,目标是将每张 `256x256` RGB 图像分割为四类:
|
| 4 |
+
|
| 5 |
+
```text
|
| 6 |
+
0 背景
|
| 7 |
+
1 活珊瑚
|
| 8 |
+
2 死珊瑚
|
| 9 |
+
3 白化珊瑚
|
| 10 |
+
```
|
| 11 |
+
|
| 12 |
+
当前实现采用双模型融合方案:
|
| 13 |
+
|
| 14 |
+
```text
|
| 15 |
+
Mask2Former-Swin-B + ConvNeXt-L-FPN
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
其中:
|
| 19 |
+
|
| 20 |
+
```text
|
| 21 |
+
Mask2Former-Swin-B 负责复杂区域和全局语义建模
|
| 22 |
+
ConvNeXt-L-FPN 负责局部纹理、边界和卷积稳定性
|
| 23 |
+
最终通过概率加权融合生成 results.zip
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
## 文档索引
|
| 27 |
+
|
| 28 |
+
完整操作流程,包括环境部署、数据解压、模型下载、训练、推理、评测和压缩提交:
|
| 29 |
+
|
| 30 |
+
```text
|
| 31 |
+
docs/operation-guide.md
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
算法与技术说明,包括模型选择、训练策略、损失函数、数据增强、融合推理和 mIoU 计算原理:
|
| 35 |
+
|
| 36 |
+
```text
|
| 37 |
+
docs/technical-report.md
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
预训练模型部署详见操作指南第 5 节,当前工程使用的本地路径为:
|
| 41 |
+
|
| 42 |
+
```text
|
| 43 |
+
coral_seg/pretrained/mask2former-swin-base-ade-semantic/
|
| 44 |
+
coral_seg/pretrained/convnext_large-ea097f82.pth
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
## 推荐运行目录
|
| 48 |
+
|
| 49 |
+
当前配置文件中的数据路径、权重路径和输出路径默认指向:
|
| 50 |
+
|
| 51 |
+
```text
|
| 52 |
+
/root/autodl-tmp/coral/data_fresh
|
| 53 |
+
/root/autodl-tmp/coral/coral_seg
|
| 54 |
+
```
|
| 55 |
+
|
| 56 |
+
因此推荐从以下目录执行命令:
|
| 57 |
+
|
| 58 |
+
```bash
|
| 59 |
+
cd /root/autodl-tmp/coral
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
## 快速训练与推理
|
| 63 |
+
|
| 64 |
+
下载或检查预训练模型:
|
| 65 |
+
|
| 66 |
+
```bash
|
| 67 |
+
python coral_seg/tools/download_pretrained.py --config coral_seg/configs/final_dual.yaml
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
检查数据:
|
| 71 |
+
|
| 72 |
+
```bash
|
| 73 |
+
python coral_seg/tools/check_data.py --config coral_seg/configs/final_dual.yaml
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
训练 ConvNeXt-L-FPN:
|
| 77 |
+
|
| 78 |
+
```bash
|
| 79 |
+
mkdir -p coral_seg/logs
|
| 80 |
+
python coral_seg/tools/train_convnext.py \
|
| 81 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 82 |
+
2>&1 | tee coral_seg/logs/convnext_train.log
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
训练 Mask2Former-Swin-B:
|
| 86 |
+
|
| 87 |
+
```bash
|
| 88 |
+
python coral_seg/tools/train_mask2former.py \
|
| 89 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 90 |
+
2>&1 | tee coral_seg/logs/mask2former_train.log
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
融合推理并生成提交文件:
|
| 94 |
+
|
| 95 |
+
```bash
|
| 96 |
+
python coral_seg/tools/infer_ensemble.py \
|
| 97 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 98 |
+
--convnext-checkpoint coral_seg/work_dirs/convnext_l_fpn/best.pth \
|
| 99 |
+
--mask2former-checkpoint coral_seg/work_dirs/mask2former_swin_b/best_hf
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
最终提交文件:
|
| 103 |
+
|
| 104 |
+
```text
|
| 105 |
+
/root/autodl-tmp/coral/coral_seg/submissions/results.zip
|
| 106 |
+
```
|
coral_seg/configs/final_dual.yaml
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
seed: 2026
|
| 2 |
+
num_classes: 4
|
| 3 |
+
class_names:
|
| 4 |
+
- background
|
| 5 |
+
- live_coral
|
| 6 |
+
- dead_coral
|
| 7 |
+
- bleached_coral
|
| 8 |
+
|
| 9 |
+
data:
|
| 10 |
+
train_images: /root/autodl-tmp/coral/data_fresh/train_bsdtar/train/image
|
| 11 |
+
train_masks: /root/autodl-tmp/coral/data_fresh/train_bsdtar/train/label
|
| 12 |
+
test_images: /root/autodl-tmp/coral/data_fresh/test_raw/PrecisionLabel800/images
|
| 13 |
+
split_dir: /root/autodl-tmp/coral/coral_seg/splits
|
| 14 |
+
val_ratio: 0.15
|
| 15 |
+
|
| 16 |
+
train:
|
| 17 |
+
num_workers: 8
|
| 18 |
+
amp: true
|
| 19 |
+
grad_clip_norm: 1.0
|
| 20 |
+
print_freq: 50
|
| 21 |
+
|
| 22 |
+
convnext:
|
| 23 |
+
image_size: 512
|
| 24 |
+
batch_size: 4
|
| 25 |
+
epochs: 120
|
| 26 |
+
lr: 0.00006
|
| 27 |
+
backbone_lr_mult: 0.25
|
| 28 |
+
weight_decay: 0.01
|
| 29 |
+
warmup_epochs: 5
|
| 30 |
+
pretrained: true
|
| 31 |
+
pretrained_path: /root/autodl-tmp/coral/coral_seg/pretrained/convnext_large-ea097f82.pth
|
| 32 |
+
work_dir: /root/autodl-tmp/coral/coral_seg/work_dirs/convnext_l_fpn
|
| 33 |
+
loss:
|
| 34 |
+
ce: 1.0
|
| 35 |
+
dice: 1.0
|
| 36 |
+
lovasz: 0.5
|
| 37 |
+
label_smoothing: 0.05
|
| 38 |
+
|
| 39 |
+
mask2former:
|
| 40 |
+
image_size: 384
|
| 41 |
+
batch_size: 2
|
| 42 |
+
epochs: 80
|
| 43 |
+
lr: 0.00003
|
| 44 |
+
weight_decay: 0.05
|
| 45 |
+
warmup_epochs: 5
|
| 46 |
+
pretrained_name: facebook/mask2former-swin-base-ade-semantic
|
| 47 |
+
pretrained_dir: /root/autodl-tmp/coral/coral_seg/pretrained/mask2former-swin-base-ade-semantic
|
| 48 |
+
gradient_checkpointing: true
|
| 49 |
+
work_dir: /root/autodl-tmp/coral/coral_seg/work_dirs/mask2former_swin_b
|
| 50 |
+
|
| 51 |
+
infer:
|
| 52 |
+
convnext_weight: 0.45
|
| 53 |
+
mask2former_weight: 0.55
|
| 54 |
+
convnext_sizes: [512]
|
| 55 |
+
mask2former_sizes: [384]
|
| 56 |
+
tta_flips: [none, h]
|
| 57 |
+
out_dir: /root/autodl-tmp/coral/coral_seg/submissions/results
|
| 58 |
+
zip_path: /root/autodl-tmp/coral/coral_seg/submissions/results.zip
|
coral_seg/coral_seg/__init__.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Coral reef semantic segmentation training package."""
|
| 2 |
+
|
coral_seg/coral_seg/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (216 Bytes). View file
|
|
|
coral_seg/coral_seg/__pycache__/dataset.cpython-312.pyc
ADDED
|
Binary file (8.01 kB). View file
|
|
|
coral_seg/coral_seg/__pycache__/losses.cpython-312.pyc
ADDED
|
Binary file (7.07 kB). View file
|
|
|
coral_seg/coral_seg/__pycache__/model_convnext_fpn.cpython-312.pyc
ADDED
|
Binary file (5.77 kB). View file
|
|
|
coral_seg/coral_seg/__pycache__/splits.cpython-312.pyc
ADDED
|
Binary file (2.88 kB). View file
|
|
|
coral_seg/coral_seg/__pycache__/utils.cpython-312.pyc
ADDED
|
Binary file (10.5 kB). View file
|
|
|
coral_seg/coral_seg/dataset.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
from typing import Dict, List, Optional
|
| 3 |
+
|
| 4 |
+
import albumentations as A
|
| 5 |
+
import cv2
|
| 6 |
+
import numpy as np
|
| 7 |
+
import torch
|
| 8 |
+
from torch.utils.data import Dataset
|
| 9 |
+
|
| 10 |
+
from .splits import read_ids
|
| 11 |
+
from .utils import IMAGENET_MEAN, IMAGENET_STD, list_pngs, read_image, read_mask
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def build_train_transform(size: int) -> A.Compose:
|
| 15 |
+
return A.Compose(
|
| 16 |
+
[
|
| 17 |
+
A.HorizontalFlip(p=0.5),
|
| 18 |
+
A.VerticalFlip(p=0.5),
|
| 19 |
+
A.RandomRotate90(p=0.5),
|
| 20 |
+
A.Affine(
|
| 21 |
+
scale=(0.75, 1.25),
|
| 22 |
+
translate_percent=(-0.06, 0.06),
|
| 23 |
+
rotate=(-25, 25),
|
| 24 |
+
shear=(-5, 5),
|
| 25 |
+
interpolation=cv2.INTER_LINEAR,
|
| 26 |
+
mask_interpolation=cv2.INTER_NEAREST,
|
| 27 |
+
border_mode=cv2.BORDER_REFLECT_101,
|
| 28 |
+
p=0.65,
|
| 29 |
+
),
|
| 30 |
+
A.OneOf(
|
| 31 |
+
[
|
| 32 |
+
A.RandomBrightnessContrast(brightness_limit=0.25, contrast_limit=0.25, p=1.0),
|
| 33 |
+
A.HueSaturationValue(hue_shift_limit=8, sat_shift_limit=18, val_shift_limit=18, p=1.0),
|
| 34 |
+
A.RandomGamma(gamma_limit=(75, 130), p=1.0),
|
| 35 |
+
A.CLAHE(clip_limit=(1, 3), tile_grid_size=(8, 8), p=1.0),
|
| 36 |
+
],
|
| 37 |
+
p=0.85,
|
| 38 |
+
),
|
| 39 |
+
A.OneOf(
|
| 40 |
+
[
|
| 41 |
+
A.GaussianBlur(blur_limit=(3, 5), p=1.0),
|
| 42 |
+
A.MotionBlur(blur_limit=3, p=1.0),
|
| 43 |
+
],
|
| 44 |
+
p=0.20,
|
| 45 |
+
),
|
| 46 |
+
A.Resize(size, size, interpolation=cv2.INTER_LINEAR, mask_interpolation=cv2.INTER_NEAREST),
|
| 47 |
+
A.Normalize(mean=IMAGENET_MEAN, std=IMAGENET_STD),
|
| 48 |
+
]
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def build_val_transform(size: int) -> A.Compose:
|
| 53 |
+
return A.Compose(
|
| 54 |
+
[
|
| 55 |
+
A.Resize(size, size, interpolation=cv2.INTER_LINEAR, mask_interpolation=cv2.INTER_NEAREST),
|
| 56 |
+
A.Normalize(mean=IMAGENET_MEAN, std=IMAGENET_STD),
|
| 57 |
+
]
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
class CoralSegDataset(Dataset):
|
| 62 |
+
def __init__(
|
| 63 |
+
self,
|
| 64 |
+
image_dir: str,
|
| 65 |
+
mask_dir: Optional[str] = None,
|
| 66 |
+
split_file: Optional[str] = None,
|
| 67 |
+
transform: Optional[A.Compose] = None,
|
| 68 |
+
) -> None:
|
| 69 |
+
self.image_dir = Path(image_dir)
|
| 70 |
+
self.mask_dir = Path(mask_dir) if mask_dir else None
|
| 71 |
+
self.transform = transform
|
| 72 |
+
|
| 73 |
+
if split_file:
|
| 74 |
+
ids = read_ids(split_file)
|
| 75 |
+
self.image_paths = [self.image_dir / f"{sample_id}.png" for sample_id in ids]
|
| 76 |
+
else:
|
| 77 |
+
self.image_paths = list_pngs(self.image_dir)
|
| 78 |
+
|
| 79 |
+
if not self.image_paths:
|
| 80 |
+
raise RuntimeError(f"No PNG images found in {self.image_dir}")
|
| 81 |
+
|
| 82 |
+
def __len__(self) -> int:
|
| 83 |
+
return len(self.image_paths)
|
| 84 |
+
|
| 85 |
+
def __getitem__(self, idx: int) -> Dict[str, torch.Tensor | str]:
|
| 86 |
+
image_path = self.image_paths[idx]
|
| 87 |
+
image = read_image(image_path)
|
| 88 |
+
mask = None
|
| 89 |
+
if self.mask_dir is not None:
|
| 90 |
+
mask_path = self.mask_dir / image_path.name
|
| 91 |
+
mask = read_mask(mask_path)
|
| 92 |
+
|
| 93 |
+
if self.transform is not None:
|
| 94 |
+
if mask is None:
|
| 95 |
+
transformed = self.transform(image=image)
|
| 96 |
+
image = transformed["image"]
|
| 97 |
+
else:
|
| 98 |
+
transformed = self.transform(image=image, mask=mask)
|
| 99 |
+
image, mask = transformed["image"], transformed["mask"]
|
| 100 |
+
|
| 101 |
+
image_tensor = torch.from_numpy(image.transpose(2, 0, 1)).float()
|
| 102 |
+
sample: Dict[str, torch.Tensor | str] = {
|
| 103 |
+
"image": image_tensor,
|
| 104 |
+
"name": image_path.name,
|
| 105 |
+
}
|
| 106 |
+
if mask is not None:
|
| 107 |
+
sample["mask"] = torch.from_numpy(mask.astype(np.int64))
|
| 108 |
+
return sample
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def segmentation_collate(batch: List[Dict[str, torch.Tensor | str]]) -> Dict[str, torch.Tensor | List[str]]:
|
| 112 |
+
images = torch.stack([item["image"] for item in batch]) # type: ignore[arg-type]
|
| 113 |
+
names = [str(item["name"]) for item in batch]
|
| 114 |
+
result: Dict[str, torch.Tensor | List[str]] = {"image": images, "name": names}
|
| 115 |
+
if "mask" in batch[0]:
|
| 116 |
+
result["mask"] = torch.stack([item["mask"] for item in batch]) # type: ignore[arg-type]
|
| 117 |
+
return result
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def mask2former_collate(
|
| 121 |
+
batch: List[Dict[str, torch.Tensor | str]],
|
| 122 |
+
num_classes: int,
|
| 123 |
+
) -> Dict[str, torch.Tensor | List[torch.Tensor] | List[str]]:
|
| 124 |
+
images = torch.stack([item["image"] for item in batch]) # type: ignore[arg-type]
|
| 125 |
+
names = [str(item["name"]) for item in batch]
|
| 126 |
+
result: Dict[str, torch.Tensor | List[torch.Tensor] | List[str]] = {"image": images, "name": names}
|
| 127 |
+
if "mask" not in batch[0]:
|
| 128 |
+
return result
|
| 129 |
+
|
| 130 |
+
masks = [item["mask"].long() for item in batch] # type: ignore[union-attr]
|
| 131 |
+
mask_labels: List[torch.Tensor] = []
|
| 132 |
+
class_labels: List[torch.Tensor] = []
|
| 133 |
+
for mask in masks:
|
| 134 |
+
labels = torch.unique(mask)
|
| 135 |
+
labels = labels[(labels >= 0) & (labels < num_classes)]
|
| 136 |
+
labels = labels.sort()[0]
|
| 137 |
+
binary_masks = torch.stack([(mask == cls).float() for cls in labels], dim=0)
|
| 138 |
+
mask_labels.append(binary_masks)
|
| 139 |
+
class_labels.append(labels.long())
|
| 140 |
+
|
| 141 |
+
result["raw_mask"] = torch.stack(masks)
|
| 142 |
+
result["mask_labels"] = mask_labels
|
| 143 |
+
result["class_labels"] = class_labels
|
| 144 |
+
return result
|
coral_seg/coral_seg/losses.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
import torch.nn as nn
|
| 5 |
+
import torch.nn.functional as F
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class DiceLoss(nn.Module):
|
| 9 |
+
def __init__(self, num_classes: int, smooth: float = 1.0, ignore_index: int = 255) -> None:
|
| 10 |
+
super().__init__()
|
| 11 |
+
self.num_classes = num_classes
|
| 12 |
+
self.smooth = smooth
|
| 13 |
+
self.ignore_index = ignore_index
|
| 14 |
+
|
| 15 |
+
def forward(self, logits: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
|
| 16 |
+
probs = torch.softmax(logits, dim=1)
|
| 17 |
+
valid = target != self.ignore_index
|
| 18 |
+
target_safe = target.clamp(0, self.num_classes - 1)
|
| 19 |
+
one_hot = F.one_hot(target_safe, self.num_classes).permute(0, 3, 1, 2).float()
|
| 20 |
+
valid = valid.unsqueeze(1).float()
|
| 21 |
+
probs = probs * valid
|
| 22 |
+
one_hot = one_hot * valid
|
| 23 |
+
dims = (0, 2, 3)
|
| 24 |
+
intersection = torch.sum(probs * one_hot, dims)
|
| 25 |
+
cardinality = torch.sum(probs + one_hot, dims)
|
| 26 |
+
dice = (2.0 * intersection + self.smooth) / (cardinality + self.smooth)
|
| 27 |
+
return 1.0 - dice.mean()
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def lovasz_grad(gt_sorted: torch.Tensor) -> torch.Tensor:
|
| 31 |
+
gts = gt_sorted.sum()
|
| 32 |
+
intersection = gts - gt_sorted.float().cumsum(0)
|
| 33 |
+
union = gts + (1 - gt_sorted).float().cumsum(0)
|
| 34 |
+
jaccard = 1.0 - intersection / union.clamp_min(1e-6)
|
| 35 |
+
if gt_sorted.numel() > 1:
|
| 36 |
+
jaccard[1:] = jaccard[1:] - jaccard[:-1]
|
| 37 |
+
return jaccard
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def lovasz_softmax_flat(probs: torch.Tensor, labels: torch.Tensor, num_classes: int) -> torch.Tensor:
|
| 41 |
+
losses = []
|
| 42 |
+
for cls in range(num_classes):
|
| 43 |
+
fg = (labels == cls).float()
|
| 44 |
+
if fg.sum() == 0:
|
| 45 |
+
continue
|
| 46 |
+
class_pred = probs[:, cls]
|
| 47 |
+
errors = (fg - class_pred).abs()
|
| 48 |
+
errors_sorted, perm = torch.sort(errors, descending=True)
|
| 49 |
+
fg_sorted = fg[perm]
|
| 50 |
+
losses.append(torch.dot(errors_sorted, lovasz_grad(fg_sorted)))
|
| 51 |
+
if not losses:
|
| 52 |
+
return probs.sum() * 0.0
|
| 53 |
+
return torch.stack(losses).mean()
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
class LovaszSoftmaxLoss(nn.Module):
|
| 57 |
+
def __init__(self, num_classes: int, ignore_index: int = 255) -> None:
|
| 58 |
+
super().__init__()
|
| 59 |
+
self.num_classes = num_classes
|
| 60 |
+
self.ignore_index = ignore_index
|
| 61 |
+
|
| 62 |
+
def forward(self, logits: torch.Tensor, target: torch.Tensor) -> torch.Tensor:
|
| 63 |
+
probs = torch.softmax(logits, dim=1).permute(0, 2, 3, 1).reshape(-1, self.num_classes)
|
| 64 |
+
labels = target.reshape(-1)
|
| 65 |
+
valid = labels != self.ignore_index
|
| 66 |
+
if valid.sum() == 0:
|
| 67 |
+
return logits.sum() * 0.0
|
| 68 |
+
return lovasz_softmax_flat(probs[valid], labels[valid], self.num_classes)
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
class ComboSegLoss(nn.Module):
|
| 72 |
+
def __init__(
|
| 73 |
+
self,
|
| 74 |
+
num_classes: int,
|
| 75 |
+
ce_weight: float = 1.0,
|
| 76 |
+
dice_weight: float = 1.0,
|
| 77 |
+
lovasz_weight: float = 0.5,
|
| 78 |
+
label_smoothing: float = 0.05,
|
| 79 |
+
ignore_index: int = 255,
|
| 80 |
+
) -> None:
|
| 81 |
+
super().__init__()
|
| 82 |
+
self.ce_weight = ce_weight
|
| 83 |
+
self.dice_weight = dice_weight
|
| 84 |
+
self.lovasz_weight = lovasz_weight
|
| 85 |
+
self.label_smoothing = label_smoothing
|
| 86 |
+
self.ignore_index = ignore_index
|
| 87 |
+
self.dice = DiceLoss(num_classes, ignore_index=ignore_index)
|
| 88 |
+
self.lovasz = LovaszSoftmaxLoss(num_classes, ignore_index=ignore_index)
|
| 89 |
+
|
| 90 |
+
def forward(self, logits: torch.Tensor, target: torch.Tensor, epoch: Optional[int] = None) -> torch.Tensor:
|
| 91 |
+
ce = F.cross_entropy(
|
| 92 |
+
logits,
|
| 93 |
+
target,
|
| 94 |
+
ignore_index=self.ignore_index,
|
| 95 |
+
label_smoothing=self.label_smoothing,
|
| 96 |
+
)
|
| 97 |
+
dice = self.dice(logits, target)
|
| 98 |
+
loss = self.ce_weight * ce + self.dice_weight * dice
|
| 99 |
+
if self.lovasz_weight > 0:
|
| 100 |
+
loss = loss + self.lovasz_weight * self.lovasz(logits, target)
|
| 101 |
+
return loss
|
coral_seg/coral_seg/model_convnext_fpn.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
from typing import List
|
| 3 |
+
|
| 4 |
+
import torch
|
| 5 |
+
import torch.nn as nn
|
| 6 |
+
import torch.nn.functional as F
|
| 7 |
+
from torchvision.models import ConvNeXt_Large_Weights, convnext_large
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class ConvBNAct(nn.Module):
|
| 11 |
+
def __init__(self, in_channels: int, out_channels: int, kernel_size: int = 3, dropout: float = 0.0) -> None:
|
| 12 |
+
super().__init__()
|
| 13 |
+
padding = kernel_size // 2
|
| 14 |
+
layers: List[nn.Module] = [
|
| 15 |
+
nn.Conv2d(in_channels, out_channels, kernel_size, padding=padding, bias=False),
|
| 16 |
+
nn.BatchNorm2d(out_channels),
|
| 17 |
+
nn.GELU(),
|
| 18 |
+
]
|
| 19 |
+
if dropout > 0:
|
| 20 |
+
layers.append(nn.Dropout2d(dropout))
|
| 21 |
+
self.block = nn.Sequential(*layers)
|
| 22 |
+
|
| 23 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 24 |
+
return self.block(x)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class ConvNeXtFPN(nn.Module):
|
| 28 |
+
def __init__(
|
| 29 |
+
self,
|
| 30 |
+
num_classes: int = 4,
|
| 31 |
+
fpn_channels: int = 256,
|
| 32 |
+
pretrained: bool = True,
|
| 33 |
+
pretrained_path: str | None = None,
|
| 34 |
+
dropout: float = 0.1,
|
| 35 |
+
) -> None:
|
| 36 |
+
super().__init__()
|
| 37 |
+
if pretrained and pretrained_path and Path(pretrained_path).is_file():
|
| 38 |
+
backbone = convnext_large(weights=None)
|
| 39 |
+
state = torch.load(pretrained_path, map_location="cpu")
|
| 40 |
+
if isinstance(state, dict) and "model" in state:
|
| 41 |
+
state = state["model"]
|
| 42 |
+
backbone.load_state_dict(state, strict=True)
|
| 43 |
+
else:
|
| 44 |
+
weights = ConvNeXt_Large_Weights.IMAGENET1K_V1 if pretrained else None
|
| 45 |
+
backbone = convnext_large(weights=weights)
|
| 46 |
+
self.features = backbone.features
|
| 47 |
+
in_channels = [192, 384, 768, 1536]
|
| 48 |
+
self.lateral = nn.ModuleList([nn.Conv2d(c, fpn_channels, 1) for c in in_channels])
|
| 49 |
+
self.smooth = nn.ModuleList([ConvBNAct(fpn_channels, fpn_channels, 3) for _ in in_channels])
|
| 50 |
+
self.decoder = nn.Sequential(
|
| 51 |
+
ConvBNAct(fpn_channels * 4, fpn_channels, 3, dropout=dropout),
|
| 52 |
+
ConvBNAct(fpn_channels, fpn_channels, 3, dropout=dropout),
|
| 53 |
+
nn.Conv2d(fpn_channels, num_classes, 1),
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
def forward_features(self, x: torch.Tensor) -> List[torch.Tensor]:
|
| 57 |
+
feats: List[torch.Tensor] = []
|
| 58 |
+
for idx, layer in enumerate(self.features):
|
| 59 |
+
x = layer(x)
|
| 60 |
+
if idx in (1, 3, 5, 7):
|
| 61 |
+
feats.append(x)
|
| 62 |
+
return feats
|
| 63 |
+
|
| 64 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 65 |
+
input_size = x.shape[-2:]
|
| 66 |
+
feats = self.forward_features(x)
|
| 67 |
+
pyramid = [lat(feat) for lat, feat in zip(self.lateral, feats)]
|
| 68 |
+
for i in range(len(pyramid) - 1, 0, -1):
|
| 69 |
+
pyramid[i - 1] = pyramid[i - 1] + F.interpolate(
|
| 70 |
+
pyramid[i],
|
| 71 |
+
size=pyramid[i - 1].shape[-2:],
|
| 72 |
+
mode="bilinear",
|
| 73 |
+
align_corners=False,
|
| 74 |
+
)
|
| 75 |
+
pyramid = [smooth(feat) for smooth, feat in zip(self.smooth, pyramid)]
|
| 76 |
+
target_size = pyramid[0].shape[-2:]
|
| 77 |
+
pyramid = [
|
| 78 |
+
feat if feat.shape[-2:] == target_size else F.interpolate(feat, size=target_size, mode="bilinear", align_corners=False)
|
| 79 |
+
for feat in pyramid
|
| 80 |
+
]
|
| 81 |
+
logits = self.decoder(torch.cat(pyramid, dim=1))
|
| 82 |
+
return F.interpolate(logits, size=input_size, mode="bilinear", align_corners=False)
|
coral_seg/coral_seg/splits.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
from typing import Iterable, List, Tuple
|
| 3 |
+
|
| 4 |
+
import numpy as np
|
| 5 |
+
|
| 6 |
+
from .utils import ensure_dir, list_pngs
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def create_split_files(
|
| 10 |
+
image_dir: str,
|
| 11 |
+
mask_dir: str,
|
| 12 |
+
split_dir: str,
|
| 13 |
+
val_ratio: float = 0.15,
|
| 14 |
+
seed: int = 2026,
|
| 15 |
+
) -> Tuple[Path, Path, Path]:
|
| 16 |
+
image_paths = list_pngs(image_dir)
|
| 17 |
+
mask_dir_path = Path(mask_dir)
|
| 18 |
+
ids = []
|
| 19 |
+
for image_path in image_paths:
|
| 20 |
+
if not (mask_dir_path / image_path.name).exists():
|
| 21 |
+
raise FileNotFoundError(f"Missing mask for {image_path.name}")
|
| 22 |
+
ids.append(image_path.stem)
|
| 23 |
+
|
| 24 |
+
rng = np.random.default_rng(seed)
|
| 25 |
+
ids = np.array(ids)
|
| 26 |
+
order = rng.permutation(len(ids))
|
| 27 |
+
val_count = max(1, int(round(len(ids) * val_ratio)))
|
| 28 |
+
val_ids = sorted(ids[order[:val_count]].tolist())
|
| 29 |
+
train_ids = sorted(ids[order[val_count:]].tolist())
|
| 30 |
+
full_ids = sorted(ids.tolist())
|
| 31 |
+
|
| 32 |
+
split_path = ensure_dir(split_dir)
|
| 33 |
+
train_file = split_path / "train.txt"
|
| 34 |
+
val_file = split_path / "val.txt"
|
| 35 |
+
full_file = split_path / "train_full.txt"
|
| 36 |
+
train_file.write_text("\n".join(train_ids) + "\n", encoding="utf-8")
|
| 37 |
+
val_file.write_text("\n".join(val_ids) + "\n", encoding="utf-8")
|
| 38 |
+
full_file.write_text("\n".join(full_ids) + "\n", encoding="utf-8")
|
| 39 |
+
return train_file, val_file, full_file
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def read_ids(path: str | Path) -> List[str]:
|
| 43 |
+
p = Path(path)
|
| 44 |
+
return [line.strip() for line in p.read_text(encoding="utf-8").splitlines() if line.strip()]
|
coral_seg/coral_seg/utils.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import math
|
| 3 |
+
import os
|
| 4 |
+
import random
|
| 5 |
+
import time
|
| 6 |
+
import zipfile
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
|
| 9 |
+
|
| 10 |
+
import numpy as np
|
| 11 |
+
import torch
|
| 12 |
+
import yaml
|
| 13 |
+
from PIL import Image
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
IMAGENET_MEAN = (0.485, 0.456, 0.406)
|
| 17 |
+
IMAGENET_STD = (0.229, 0.224, 0.225)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def load_config(path: str | os.PathLike[str]) -> Dict[str, Any]:
|
| 21 |
+
with open(path, "r", encoding="utf-8") as f:
|
| 22 |
+
return yaml.safe_load(f)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def ensure_dir(path: str | os.PathLike[str]) -> Path:
|
| 26 |
+
p = Path(path)
|
| 27 |
+
p.mkdir(parents=True, exist_ok=True)
|
| 28 |
+
return p
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def set_seed(seed: int) -> None:
|
| 32 |
+
random.seed(seed)
|
| 33 |
+
np.random.seed(seed)
|
| 34 |
+
torch.manual_seed(seed)
|
| 35 |
+
torch.cuda.manual_seed_all(seed)
|
| 36 |
+
torch.backends.cudnn.benchmark = True
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def read_image(path: str | os.PathLike[str]) -> np.ndarray:
|
| 40 |
+
return np.array(Image.open(path).convert("RGB"))
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def read_mask(path: str | os.PathLike[str]) -> np.ndarray:
|
| 44 |
+
return np.array(Image.open(path), dtype=np.uint8)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def save_mask(path: str | os.PathLike[str], mask: np.ndarray) -> None:
|
| 48 |
+
mask = np.asarray(mask, dtype=np.uint8)
|
| 49 |
+
Image.fromarray(mask, mode="L").save(path)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def normalize_tensor(image: np.ndarray) -> torch.Tensor:
|
| 53 |
+
image = image.astype(np.float32) / 255.0
|
| 54 |
+
mean = np.array(IMAGENET_MEAN, dtype=np.float32)
|
| 55 |
+
std = np.array(IMAGENET_STD, dtype=np.float32)
|
| 56 |
+
image = (image - mean) / std
|
| 57 |
+
return torch.from_numpy(image.transpose(2, 0, 1)).float()
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def denormalize_tensor(x: torch.Tensor) -> torch.Tensor:
|
| 61 |
+
mean = torch.tensor(IMAGENET_MEAN, device=x.device).view(1, 3, 1, 1)
|
| 62 |
+
std = torch.tensor(IMAGENET_STD, device=x.device).view(1, 3, 1, 1)
|
| 63 |
+
return x * std + mean
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class AverageMeter:
|
| 67 |
+
def __init__(self) -> None:
|
| 68 |
+
self.reset()
|
| 69 |
+
|
| 70 |
+
def reset(self) -> None:
|
| 71 |
+
self.sum = 0.0
|
| 72 |
+
self.count = 0
|
| 73 |
+
|
| 74 |
+
@property
|
| 75 |
+
def avg(self) -> float:
|
| 76 |
+
return self.sum / max(1, self.count)
|
| 77 |
+
|
| 78 |
+
def update(self, value: float, n: int = 1) -> None:
|
| 79 |
+
self.sum += float(value) * n
|
| 80 |
+
self.count += n
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def fast_hist(pred: np.ndarray, target: np.ndarray, num_classes: int, ignore_index: int = 255) -> np.ndarray:
|
| 84 |
+
pred = pred.reshape(-1)
|
| 85 |
+
target = target.reshape(-1)
|
| 86 |
+
valid = (target != ignore_index) & (target >= 0) & (target < num_classes)
|
| 87 |
+
hist = np.bincount(
|
| 88 |
+
num_classes * target[valid].astype(np.int64) + pred[valid].astype(np.int64),
|
| 89 |
+
minlength=num_classes**2,
|
| 90 |
+
)
|
| 91 |
+
return hist.reshape(num_classes, num_classes)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def compute_iou(hist: np.ndarray) -> Tuple[np.ndarray, float]:
|
| 95 |
+
denom = hist.sum(1) + hist.sum(0) - np.diag(hist)
|
| 96 |
+
iou = np.divide(np.diag(hist), denom, out=np.full_like(denom, np.nan, dtype=np.float64), where=denom != 0)
|
| 97 |
+
return iou, float(np.nanmean(iou))
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def format_metrics(iou: np.ndarray, miou: float, class_names: Sequence[str]) -> str:
|
| 101 |
+
parts = [f"mIoU={miou:.5f}"]
|
| 102 |
+
for name, value in zip(class_names, iou):
|
| 103 |
+
parts.append(f"{name}={value:.5f}" if not np.isnan(value) else f"{name}=nan")
|
| 104 |
+
return " ".join(parts)
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def save_json(path: str | os.PathLike[str], obj: Dict[str, Any]) -> None:
|
| 108 |
+
with open(path, "w", encoding="utf-8") as f:
|
| 109 |
+
json.dump(obj, f, indent=2, ensure_ascii=False)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
def cosine_warmup_lambda(
|
| 113 |
+
current_step: int,
|
| 114 |
+
*,
|
| 115 |
+
total_steps: int,
|
| 116 |
+
warmup_steps: int,
|
| 117 |
+
min_factor: float = 0.01,
|
| 118 |
+
) -> float:
|
| 119 |
+
if current_step < warmup_steps:
|
| 120 |
+
return float(current_step + 1) / float(max(1, warmup_steps))
|
| 121 |
+
progress = float(current_step - warmup_steps) / float(max(1, total_steps - warmup_steps))
|
| 122 |
+
cosine = 0.5 * (1.0 + math.cos(math.pi * progress))
|
| 123 |
+
return min_factor + (1.0 - min_factor) * cosine
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def make_results_zip(results_dir: str | os.PathLike[str], zip_path: str | os.PathLike[str]) -> None:
|
| 127 |
+
results_dir = Path(results_dir)
|
| 128 |
+
zip_path = Path(zip_path)
|
| 129 |
+
ensure_dir(zip_path.parent)
|
| 130 |
+
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
|
| 131 |
+
for path in sorted(results_dir.glob("*.png")):
|
| 132 |
+
zf.write(path, arcname=f"results/{path.name}")
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def list_pngs(path: str | os.PathLike[str]) -> List[Path]:
|
| 136 |
+
return sorted(Path(path).glob("*.png"))
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def timestamp() -> str:
|
| 140 |
+
return time.strftime("%Y-%m-%d %H:%M:%S")
|
coral_seg/docs/operation-guide.md
ADDED
|
@@ -0,0 +1,575 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 完整操作指南
|
| 2 |
+
|
| 3 |
+
本文档说明如何从环境部署开始,完成数据解压、预训练模型下载、模型训练、结果推理、可视化、mIoU 评估和 `results.zip` 压缩提交。
|
| 4 |
+
|
| 5 |
+
## 1. 运行目录
|
| 6 |
+
|
| 7 |
+
推荐从工作区根目录执行所有命令:
|
| 8 |
+
|
| 9 |
+
```bash
|
| 10 |
+
cd /root/autodl-tmp/coral
|
| 11 |
+
```
|
| 12 |
+
|
| 13 |
+
当前配置默认使用以下路径:
|
| 14 |
+
|
| 15 |
+
```text
|
| 16 |
+
训练图像:/root/autodl-tmp/coral/data_fresh/train_bsdtar/train/image
|
| 17 |
+
训练标签:/root/autodl-tmp/coral/data_fresh/train_bsdtar/train/label
|
| 18 |
+
测试图像:/root/autodl-tmp/coral/data_fresh/test_raw/PrecisionLabel800/images
|
| 19 |
+
工程目录:/root/autodl-tmp/coral/coral_seg
|
| 20 |
+
```
|
| 21 |
+
|
| 22 |
+
## 2. 环境部署
|
| 23 |
+
|
| 24 |
+
本项目没有单独新建 conda 环境,直接使用当前默认 Python 环境。
|
| 25 |
+
|
| 26 |
+
检查当前环境:
|
| 27 |
+
|
| 28 |
+
```bash
|
| 29 |
+
which python
|
| 30 |
+
python -V
|
| 31 |
+
python -c "import torch; print(torch.__version__, torch.cuda.is_available())"
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
当前已验证版本:
|
| 35 |
+
|
| 36 |
+
```text
|
| 37 |
+
Python 3.12.3
|
| 38 |
+
PyTorch 2.3.0+cu121
|
| 39 |
+
torchvision 0.18.0+cu121
|
| 40 |
+
transformers 4.46.3
|
| 41 |
+
timm 1.0.27
|
| 42 |
+
albumentations 2.0.8
|
| 43 |
+
opencv-python-headless 4.13.0.92
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
如果需要重新安装依赖:
|
| 47 |
+
|
| 48 |
+
```bash
|
| 49 |
+
python -m pip install -U \
|
| 50 |
+
transformers==4.46.3 \
|
| 51 |
+
timm==1.0.27 \
|
| 52 |
+
albumentations==2.0.8 \
|
| 53 |
+
opencv-python-headless==4.13.0.92 \
|
| 54 |
+
safetensors \
|
| 55 |
+
accelerate \
|
| 56 |
+
PyYAML \
|
| 57 |
+
huggingface-hub
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
不要随意升级 `torch` 和 `torchvision`,当前训练代码已经按现有版本验证通过。
|
| 61 |
+
|
| 62 |
+
## 3. 数据解压
|
| 63 |
+
|
| 64 |
+
如果 `data_fresh/` 已经存在且检查正常,可以跳过本节。
|
| 65 |
+
|
| 66 |
+
外层数据包:
|
| 67 |
+
|
| 68 |
+
```text
|
| 69 |
+
/root/autodl-tmp/比赛data.zip
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
解压外层 zip:
|
| 73 |
+
|
| 74 |
+
```bash
|
| 75 |
+
mkdir -p extracted_zip
|
| 76 |
+
unzip -q -o '比赛data.zip' -d extracted_zip
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
外层解压后包含:
|
| 80 |
+
|
| 81 |
+
```text
|
| 82 |
+
比赛data/train.rar
|
| 83 |
+
比赛data/test.zip
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
训练集建议使用 `bsdtar` 解压。旧版 `7z` 对该 RAR5 压缩方式可能报 `Unsupported Method`。
|
| 87 |
+
|
| 88 |
+
```bash
|
| 89 |
+
mkdir -p data_fresh/train_bsdtar
|
| 90 |
+
bsdtar -xf 'extracted_zip/比赛data/train.rar' -C data_fresh/train_bsdtar
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
测试集解压:
|
| 94 |
+
|
| 95 |
+
```bash
|
| 96 |
+
mkdir -p data_fresh/test_raw
|
| 97 |
+
unzip -q -o 'extracted_zip/比赛data/test.zip' -d data_fresh/test_raw
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
清理旧数据和临时目录:
|
| 101 |
+
|
| 102 |
+
```bash
|
| 103 |
+
rm -rf data data_fresh/train_raw extracted_zip
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
## 4. 检查数据
|
| 107 |
+
|
| 108 |
+
执行:
|
| 109 |
+
|
| 110 |
+
```bash
|
| 111 |
+
python coral_seg/tools/check_data.py --config coral_seg/configs/final_dual.yaml
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
正常输出应包含:
|
| 115 |
+
|
| 116 |
+
```text
|
| 117 |
+
train_images 3000 0000.png 2999.png
|
| 118 |
+
train_masks 3000 0000.png 2999.png
|
| 119 |
+
test_images 800 image_0001.png image_0800.png
|
| 120 |
+
mask values: [0, 1, 2, 3]
|
| 121 |
+
bad masks: 0 []
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
如果 `bad masks` 不为 0,说明训练标签像素值异常,不应继续训练。
|
| 125 |
+
|
| 126 |
+
## 5. 预训练模型部署和下载
|
| 127 |
+
|
| 128 |
+
本方案需要两类预训练模型,均通过配置文件显式指定路径。
|
| 129 |
+
|
| 130 |
+
```text
|
| 131 |
+
Mask2Former-Swin-B:facebook/mask2former-swin-base-ade-semantic
|
| 132 |
+
ConvNeXt-L:torchvision convnext_large ImageNet-1K 权重
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
配置位置:
|
| 136 |
+
|
| 137 |
+
```text
|
| 138 |
+
coral_seg/configs/final_dual.yaml
|
| 139 |
+
```
|
| 140 |
+
|
| 141 |
+
对应字段:
|
| 142 |
+
|
| 143 |
+
```text
|
| 144 |
+
mask2former.pretrained_name: facebook/mask2former-swin-base-ade-semantic
|
| 145 |
+
mask2former.pretrained_dir: /root/autodl-tmp/coral/coral_seg/pretrained/mask2former-swin-base-ade-semantic
|
| 146 |
+
convnext.pretrained_path: /root/autodl-tmp/coral/coral_seg/pretrained/convnext_large-ea097f82.pth
|
| 147 |
+
```
|
| 148 |
+
|
| 149 |
+
### 5.1 在线下载
|
| 150 |
+
|
| 151 |
+
如果机器可以访问 HuggingFace 和 PyTorch 权重源,直接执行:
|
| 152 |
+
|
| 153 |
+
```bash
|
| 154 |
+
python coral_seg/tools/download_pretrained.py --config coral_seg/configs/final_dual.yaml
|
| 155 |
+
```
|
| 156 |
+
|
| 157 |
+
该脚本会完成两件事:
|
| 158 |
+
|
| 159 |
+
```text
|
| 160 |
+
1. 下载 Mask2Former-Swin-B 到 coral_seg/pretrained/mask2former-swin-base-ade-semantic/
|
| 161 |
+
2. 下载 ConvNeXt-L 的 torchvision 权重,并复制到 coral_seg/pretrained/convnext_large-ea097f82.pth
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
下载完成后,工程内应存在:
|
| 165 |
+
|
| 166 |
+
```text
|
| 167 |
+
coral_seg/pretrained/
|
| 168 |
+
├── convnext_large-ea097f82.pth
|
| 169 |
+
└── mask2former-swin-base-ade-semantic/
|
| 170 |
+
├── config.json
|
| 171 |
+
├── preprocessor_config.json
|
| 172 |
+
├── model.safetensors
|
| 173 |
+
└── pytorch_model.bin
|
| 174 |
+
```
|
| 175 |
+
|
| 176 |
+
`model.safetensors` 和 `pytorch_model.bin` 至少保留一个即可;当前目录同时保留两者,便于不同版本 `transformers` 加载。
|
| 177 |
+
|
| 178 |
+
### 5.2 离线部署
|
| 179 |
+
|
| 180 |
+
如果复现环境不能联网,需要提前把预训练模型放到以下位置。
|
| 181 |
+
|
| 182 |
+
Mask2Former 目录:
|
| 183 |
+
|
| 184 |
+
```text
|
| 185 |
+
/root/autodl-tmp/coral/coral_seg/pretrained/mask2former-swin-base-ade-semantic/
|
| 186 |
+
```
|
| 187 |
+
|
| 188 |
+
该目录至少需要包含:
|
| 189 |
+
|
| 190 |
+
```text
|
| 191 |
+
config.json
|
| 192 |
+
preprocessor_config.json
|
| 193 |
+
model.safetensors 或 pytorch_model.bin
|
| 194 |
+
```
|
| 195 |
+
|
| 196 |
+
ConvNeXt-L 权重文件:
|
| 197 |
+
|
| 198 |
+
```text
|
| 199 |
+
/root/autodl-tmp/coral/coral_seg/pretrained/convnext_large-ea097f82.pth
|
| 200 |
+
```
|
| 201 |
+
|
| 202 |
+
如果当前机器已经有 torchvision 缓存,可以复制到工程目录:
|
| 203 |
+
|
| 204 |
+
```bash
|
| 205 |
+
mkdir -p coral_seg/pretrained
|
| 206 |
+
cp /root/.cache/torch/hub/checkpoints/convnext_large-ea097f82.pth \
|
| 207 |
+
coral_seg/pretrained/convnext_large-ea097f82.pth
|
| 208 |
+
```
|
| 209 |
+
|
| 210 |
+
训练代码会优先读取 `convnext.pretrained_path`。只要该文件存在,就不会依赖 `/root/.cache/torch` 中的缓存。
|
| 211 |
+
|
| 212 |
+
### 5.3 完整性检查
|
| 213 |
+
|
| 214 |
+
执行以下命令检查预训练模型文件是否齐全:
|
| 215 |
+
|
| 216 |
+
```bash
|
| 217 |
+
python - <<'PY_CHECK'
|
| 218 |
+
from pathlib import Path
|
| 219 |
+
|
| 220 |
+
root = Path('coral_seg/pretrained')
|
| 221 |
+
mask2former = root / 'mask2former-swin-base-ade-semantic'
|
| 222 |
+
convnext = root / 'convnext_large-ea097f82.pth'
|
| 223 |
+
|
| 224 |
+
required = [
|
| 225 |
+
mask2former / 'config.json',
|
| 226 |
+
mask2former / 'preprocessor_config.json',
|
| 227 |
+
convnext,
|
| 228 |
+
]
|
| 229 |
+
missing = [str(p) for p in required if not p.is_file()]
|
| 230 |
+
has_weight = (mask2former / 'model.safetensors').is_file() or (mask2former / 'pytorch_model.bin').is_file()
|
| 231 |
+
if not has_weight:
|
| 232 |
+
missing.append(str(mask2former / 'model.safetensors 或 pytorch_model.bin'))
|
| 233 |
+
|
| 234 |
+
print('missing:', missing)
|
| 235 |
+
print('mask2former_dir:', mask2former.resolve())
|
| 236 |
+
print('convnext_weight:', convnext.resolve(), convnext.stat().st_size if convnext.is_file() else 0)
|
| 237 |
+
PY_CHECK
|
| 238 |
+
```
|
| 239 |
+
|
| 240 |
+
正常情况下:
|
| 241 |
+
|
| 242 |
+
```text
|
| 243 |
+
missing: []
|
| 244 |
+
```
|
| 245 |
+
|
| 246 |
+
### 5.4 加载说明
|
| 247 |
+
|
| 248 |
+
ConvNeXt 分支:
|
| 249 |
+
|
| 250 |
+
```text
|
| 251 |
+
coral_seg/model_convnext_fpn.py 会优先读取 convnext.pretrained_path
|
| 252 |
+
如果该文件不存在,才会退回到 torchvision 自动下载或缓存加载
|
| 253 |
+
```
|
| 254 |
+
|
| 255 |
+
Mask2Former 分支:
|
| 256 |
+
|
| 257 |
+
```text
|
| 258 |
+
train_mask2former.py 会从 mask2former.pretrained_dir 加载本地目录
|
| 259 |
+
分类头从 ADE20K 的 150 类改为本任务的 4 类,因此分类头重新初始化是正常现象
|
| 260 |
+
```
|
| 261 |
+
|
| 262 |
+
常见日志:
|
| 263 |
+
|
| 264 |
+
```text
|
| 265 |
+
class_predictor shape mismatch
|
| 266 |
+
```
|
| 267 |
+
|
| 268 |
+
这是正常现象,不是权重损坏。
|
| 269 |
+
|
| 270 |
+
如果在线下载时出现网络超时,可以改用离线部署方式,只要上述文件清单完整即可继续训练。
|
| 271 |
+
|
| 272 |
+
## 6. 生成训练和验证划分
|
| 273 |
+
|
| 274 |
+
执行:
|
| 275 |
+
|
| 276 |
+
```bash
|
| 277 |
+
python coral_seg/tools/create_splits.py --config coral_seg/configs/final_dual.yaml
|
| 278 |
+
```
|
| 279 |
+
|
| 280 |
+
生成:
|
| 281 |
+
|
| 282 |
+
```text
|
| 283 |
+
coral_seg/splits/train.txt
|
| 284 |
+
coral_seg/splits/val.txt
|
| 285 |
+
coral_seg/splits/train_full.txt
|
| 286 |
+
```
|
| 287 |
+
|
| 288 |
+
默认划分:
|
| 289 |
+
|
| 290 |
+
```text
|
| 291 |
+
85% 训练集
|
| 292 |
+
15% 验证集
|
| 293 |
+
seed = 2026
|
| 294 |
+
```
|
| 295 |
+
|
| 296 |
+
## 7. 训练 ConvNeXt-L-FPN
|
| 297 |
+
|
| 298 |
+
建议先训练 ConvNeXt 分支,因为它更稳定、速度更快。
|
| 299 |
+
|
| 300 |
+
```bash
|
| 301 |
+
mkdir -p coral_seg/logs
|
| 302 |
+
|
| 303 |
+
python coral_seg/tools/train_convnext.py \
|
| 304 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 305 |
+
2>&1 | tee coral_seg/logs/convnext_train.log
|
| 306 |
+
```
|
| 307 |
+
|
| 308 |
+
主要配置:
|
| 309 |
+
|
| 310 |
+
```text
|
| 311 |
+
输入尺寸:512
|
| 312 |
+
batch size:4
|
| 313 |
+
epoch:120
|
| 314 |
+
优化器:AdamW
|
| 315 |
+
学习率:6e-5
|
| 316 |
+
损失函数:CE + Dice + Lovasz
|
| 317 |
+
label smoothing:0.05
|
| 318 |
+
```
|
| 319 |
+
|
| 320 |
+
训练产物:
|
| 321 |
+
|
| 322 |
+
```text
|
| 323 |
+
coral_seg/work_dirs/convnext_l_fpn/best.pth
|
| 324 |
+
coral_seg/work_dirs/convnext_l_fpn/latest.pth
|
| 325 |
+
```
|
| 326 |
+
|
| 327 |
+
查看日志:
|
| 328 |
+
|
| 329 |
+
```bash
|
| 330 |
+
tail -f coral_seg/logs/convnext_train.log
|
| 331 |
+
```
|
| 332 |
+
|
| 333 |
+
查看验证集 mIoU:
|
| 334 |
+
|
| 335 |
+
```bash
|
| 336 |
+
grep "convnext val" coral_seg/logs/convnext_train.log
|
| 337 |
+
```
|
| 338 |
+
|
| 339 |
+
## 8. 训练 Mask2Former-Swin-B
|
| 340 |
+
|
| 341 |
+
ConvNeXt 训练完成后,训练 Mask2Former:
|
| 342 |
+
|
| 343 |
+
```bash
|
| 344 |
+
python coral_seg/tools/train_mask2former.py \
|
| 345 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 346 |
+
2>&1 | tee coral_seg/logs/mask2former_train.log
|
| 347 |
+
```
|
| 348 |
+
|
| 349 |
+
主要配置:
|
| 350 |
+
|
| 351 |
+
```text
|
| 352 |
+
输入尺寸:384
|
| 353 |
+
batch size:2
|
| 354 |
+
epoch:80
|
| 355 |
+
优化器:AdamW
|
| 356 |
+
学习率:3e-5
|
| 357 |
+
预训练权重:facebook/mask2former-swin-base-ade-semantic
|
| 358 |
+
```
|
| 359 |
+
|
| 360 |
+
训练产物:
|
| 361 |
+
|
| 362 |
+
```text
|
| 363 |
+
coral_seg/work_dirs/mask2former_swin_b/best.pth
|
| 364 |
+
coral_seg/work_dirs/mask2former_swin_b/latest.pth
|
| 365 |
+
coral_seg/work_dirs/mask2former_swin_b/best_hf/
|
| 366 |
+
```
|
| 367 |
+
|
| 368 |
+
查看日志:
|
| 369 |
+
|
| 370 |
+
```bash
|
| 371 |
+
tail -f coral_seg/logs/mask2former_train.log
|
| 372 |
+
```
|
| 373 |
+
|
| 374 |
+
查看验证集 mIoU:
|
| 375 |
+
|
| 376 |
+
```bash
|
| 377 |
+
grep "mask2former val" coral_seg/logs/mask2former_train.log
|
| 378 |
+
```
|
| 379 |
+
|
| 380 |
+
常见日志说明:
|
| 381 |
+
|
| 382 |
+
```text
|
| 383 |
+
class_predictor shape mismatch
|
| 384 |
+
```
|
| 385 |
+
|
| 386 |
+
这是正常现象。ADE20K 预训练模型是 150 类,本任务是 4 类,分类头需要重新初始化。
|
| 387 |
+
|
| 388 |
+
```text
|
| 389 |
+
Gradient checkpointing is not supported
|
| 390 |
+
```
|
| 391 |
+
|
| 392 |
+
这是正常现象。本地 transformers 的 Mask2Former 类不支持梯度检查点,代码会自动跳过。
|
| 393 |
+
|
| 394 |
+
## 9. 查看 GPU 状态
|
| 395 |
+
|
| 396 |
+
```bash
|
| 397 |
+
nvidia-smi
|
| 398 |
+
```
|
| 399 |
+
|
| 400 |
+
持续刷新:
|
| 401 |
+
|
| 402 |
+
```bash
|
| 403 |
+
watch -n 2 nvidia-smi
|
| 404 |
+
```
|
| 405 |
+
|
| 406 |
+
## 10. 中断后继续训练
|
| 407 |
+
|
| 408 |
+
ConvNeXt 继续训练:
|
| 409 |
+
|
| 410 |
+
```bash
|
| 411 |
+
python coral_seg/tools/train_convnext.py \
|
| 412 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 413 |
+
--resume coral_seg/work_dirs/convnext_l_fpn/latest.pth
|
| 414 |
+
```
|
| 415 |
+
|
| 416 |
+
Mask2Former 继续训练:
|
| 417 |
+
|
| 418 |
+
```bash
|
| 419 |
+
python coral_seg/tools/train_mask2former.py \
|
| 420 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 421 |
+
--resume coral_seg/work_dirs/mask2former_swin_b/latest.pth
|
| 422 |
+
```
|
| 423 |
+
|
| 424 |
+
## 11. 验证集融合 mIoU
|
| 425 |
+
|
| 426 |
+
两个模型都训练完成后,计算验证集双模型融合 mIoU:
|
| 427 |
+
|
| 428 |
+
```bash
|
| 429 |
+
python coral_seg/tools/eval_ensemble_val.py \
|
| 430 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 431 |
+
--convnext-checkpoint coral_seg/work_dirs/convnext_l_fpn/best.pth \
|
| 432 |
+
--mask2former-checkpoint coral_seg/work_dirs/mask2former_swin_b/best_hf
|
| 433 |
+
```
|
| 434 |
+
|
| 435 |
+
## 12. 测试集推理
|
| 436 |
+
|
| 437 |
+
双模型融合推理:
|
| 438 |
+
|
| 439 |
+
```bash
|
| 440 |
+
python coral_seg/tools/infer_ensemble.py \
|
| 441 |
+
--config coral_seg/configs/final_dual.yaml \
|
| 442 |
+
--convnext-checkpoint coral_seg/work_dirs/convnext_l_fpn/best.pth \
|
| 443 |
+
--mask2former-checkpoint coral_seg/work_dirs/mask2former_swin_b/best_hf
|
| 444 |
+
```
|
| 445 |
+
|
| 446 |
+
推理输出:
|
| 447 |
+
|
| 448 |
+
```text
|
| 449 |
+
coral_seg/submissions/results/
|
| 450 |
+
coral_seg/submissions/results.zip
|
| 451 |
+
```
|
| 452 |
+
|
| 453 |
+
`results/` 中应包含 800 张单通道 PNG:
|
| 454 |
+
|
| 455 |
+
```text
|
| 456 |
+
image_0001.png
|
| 457 |
+
image_0002.png
|
| 458 |
+
...
|
| 459 |
+
image_0800.png
|
| 460 |
+
```
|
| 461 |
+
|
| 462 |
+
每张 PNG 的像素值只能是:
|
| 463 |
+
|
| 464 |
+
```text
|
| 465 |
+
0, 1, 2, 3
|
| 466 |
+
```
|
| 467 |
+
|
| 468 |
+
## 13. 检查并压缩 results
|
| 469 |
+
|
| 470 |
+
推理脚本会自动压缩 `results.zip`。如果需要手动检查:
|
| 471 |
+
|
| 472 |
+
```bash
|
| 473 |
+
python - <<'PY_CHECK'
|
| 474 |
+
import zipfile
|
| 475 |
+
from pathlib import Path
|
| 476 |
+
from PIL import Image
|
| 477 |
+
import numpy as np
|
| 478 |
+
|
| 479 |
+
zip_path = Path('coral_seg/submissions/results.zip')
|
| 480 |
+
with zipfile.ZipFile(zip_path) as zf:
|
| 481 |
+
names = zf.namelist()
|
| 482 |
+
print('num files:', len(names))
|
| 483 |
+
print('first:', names[:3])
|
| 484 |
+
print('last:', names[-3:])
|
| 485 |
+
|
| 486 |
+
values = set()
|
| 487 |
+
for p in sorted(Path('coral_seg/submissions/results').glob('*.png')):
|
| 488 |
+
arr = np.array(Image.open(p))
|
| 489 |
+
values |= set(np.unique(arr).tolist())
|
| 490 |
+
print('values:', sorted(values))
|
| 491 |
+
PY_CHECK
|
| 492 |
+
```
|
| 493 |
+
|
| 494 |
+
正常结果:
|
| 495 |
+
|
| 496 |
+
```text
|
| 497 |
+
num files: 800
|
| 498 |
+
first: ['results/image_0001.png', ...]
|
| 499 |
+
values: [0, 1, 2, 3]
|
| 500 |
+
```
|
| 501 |
+
|
| 502 |
+
如果需要手动重新压缩:
|
| 503 |
+
|
| 504 |
+
```bash
|
| 505 |
+
cd coral_seg/submissions
|
| 506 |
+
zip -r results.zip results
|
| 507 |
+
cd /root/autodl-tmp/coral
|
| 508 |
+
```
|
| 509 |
+
|
| 510 |
+
压缩包内部结构必须是:
|
| 511 |
+
|
| 512 |
+
```text
|
| 513 |
+
results.zip
|
| 514 |
+
└── results/
|
| 515 |
+
├── image_0001.png
|
| 516 |
+
├── image_0002.png
|
| 517 |
+
├── ...
|
| 518 |
+
└── image_0800.png
|
| 519 |
+
```
|
| 520 |
+
|
| 521 |
+
## 14. 生成可视化结果
|
| 522 |
+
|
| 523 |
+
```bash
|
| 524 |
+
python coral_seg/tools/visualize_results.py \
|
| 525 |
+
--image-dir data_fresh/test_raw/PrecisionLabel800/images \
|
| 526 |
+
--pred-dir coral_seg/submissions/results \
|
| 527 |
+
--out-dir coral_seg/vis_results \
|
| 528 |
+
--num 24
|
| 529 |
+
```
|
| 530 |
+
|
| 531 |
+
输出目录:
|
| 532 |
+
|
| 533 |
+
```text
|
| 534 |
+
coral_seg/vis_results/
|
| 535 |
+
```
|
| 536 |
+
|
| 537 |
+
每张可视化图包含:
|
| 538 |
+
|
| 539 |
+
```text
|
| 540 |
+
原图
|
| 541 |
+
预测彩色 mask
|
| 542 |
+
预测叠加图
|
| 543 |
+
```
|
| 544 |
+
|
| 545 |
+
## 15. 本地 test mIoU
|
| 546 |
+
|
| 547 |
+
只有当 `data_fresh/test_raw/PrecisionLabel800/mask` 确认为官方测试集真值时,下面的 test mIoU 才有意义。
|
| 548 |
+
|
| 549 |
+
当前识别到该目录是 RGB 彩色 mask,颜色映射为:
|
| 550 |
+
|
| 551 |
+
```text
|
| 552 |
+
(0, 0, 0) -> 0 背景
|
| 553 |
+
(240, 110, 170) -> 1 活珊瑚
|
| 554 |
+
(240, 171, 203) -> 2 死珊瑚
|
| 555 |
+
(0, 162, 232) -> 3 白化珊瑚
|
| 556 |
+
```
|
| 557 |
+
|
| 558 |
+
计算命令:
|
| 559 |
+
|
| 560 |
+
```bash
|
| 561 |
+
python coral_seg/tools/eval_predictions.py \
|
| 562 |
+
--pred-dir coral_seg/submissions/results \
|
| 563 |
+
--gt-dir data_fresh/test_raw/PrecisionLabel800/mask \
|
| 564 |
+
--color-map '0,0,0:0;240,110,170:1;240,171,203:2;0,162,232:3'
|
| 565 |
+
```
|
| 566 |
+
|
| 567 |
+
如果该 `mask` 目录不是官方真值,而只是参考或占位 mask,则最终测试集成绩以竞赛平台为准。
|
| 568 |
+
|
| 569 |
+
## 16. 最终提交文件
|
| 570 |
+
|
| 571 |
+
最终提交文件位置:
|
| 572 |
+
|
| 573 |
+
```text
|
| 574 |
+
/root/autodl-tmp/coral/coral_seg/submissions/results.zip
|
| 575 |
+
```
|
coral_seg/docs/technical-report.md
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 方法与技术细节说明
|
| 2 |
+
|
| 3 |
+
本文档说明本项目解决水下珊瑚语义分割任务的完整技术方案,包括任务分析、模型设计、训练策略、损失函数、数据增强、融合推理、mIoU 计算和复现设计。
|
| 4 |
+
|
| 5 |
+
## 1. 任务定义
|
| 6 |
+
|
| 7 |
+
输入为 `256x256` RGB 水下图像,输出为同尺寸单通道语义分割图。
|
| 8 |
+
|
| 9 |
+
类别定义:
|
| 10 |
+
|
| 11 |
+
```text
|
| 12 |
+
0 背景
|
| 13 |
+
1 活珊瑚
|
| 14 |
+
2 死珊瑚
|
| 15 |
+
3 白化珊瑚
|
| 16 |
+
```
|
| 17 |
+
|
| 18 |
+
评价指标为 mIoU。
|
| 19 |
+
|
| 20 |
+
比赛限制:
|
| 21 |
+
|
| 22 |
+
```text
|
| 23 |
+
只允许使用官方训练集
|
| 24 |
+
测试集只允许用于推理
|
| 25 |
+
不得使用伪标签、自训练或测试集分布统计更新
|
| 26 |
+
预训练模型必须是 2026-01-01 前公开发布的开源模型
|
| 27 |
+
最终复现要求在 A30 单卡 24G 上训练和推理总时间不超过 24 小时
|
| 28 |
+
```
|
| 29 |
+
|
| 30 |
+
## 2. 数据难点
|
| 31 |
+
|
| 32 |
+
水下珊瑚图像相比普通自然图像有明显差异:
|
| 33 |
+
|
| 34 |
+
```text
|
| 35 |
+
光照不均
|
| 36 |
+
颜色偏移
|
| 37 |
+
水体浑浊
|
| 38 |
+
悬浮颗粒干扰
|
| 39 |
+
珊瑚边界不规则
|
| 40 |
+
活珊瑚、死珊瑚、白化珊瑚外观相似
|
| 41 |
+
标签存在噪声
|
| 42 |
+
```
|
| 43 |
+
|
| 44 |
+
因此,模型需要同时利用:
|
| 45 |
+
|
| 46 |
+
```text
|
| 47 |
+
局部纹理
|
| 48 |
+
边界形态
|
| 49 |
+
多尺度上下文
|
| 50 |
+
全局语义信息
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
单纯依赖颜色容易失败,尤其在水下颜色失真严重时。
|
| 54 |
+
|
| 55 |
+
## 3. 总体方案
|
| 56 |
+
|
| 57 |
+
最终采用双模型融合:
|
| 58 |
+
|
| 59 |
+
```text
|
| 60 |
+
Mask2Former-Swin-B + ConvNeXt-L-FPN
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
职责划分:
|
| 64 |
+
|
| 65 |
+
```text
|
| 66 |
+
Mask2Former-Swin-B:负责复杂区域、全局上下文和 mask 级建模
|
| 67 |
+
ConvNeXt-L-FPN:负责局部纹理、边界细节和卷积稳定性
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
融合方式:
|
| 71 |
+
|
| 72 |
+
```text
|
| 73 |
+
final_prob = 0.55 * prob_mask2former + 0.45 * prob_convnext
|
| 74 |
+
prediction = argmax(final_prob)
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
选择异构融合的原因:
|
| 78 |
+
|
| 79 |
+
```text
|
| 80 |
+
两类模型错误模式不同
|
| 81 |
+
Transformer 更擅长全局关系
|
| 82 |
+
卷积模型更擅长局部纹理和边界
|
| 83 |
+
概率融合可以降低单模型偶然错误
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
## 4. ConvNeXt-L-FPN 分支
|
| 87 |
+
|
| 88 |
+
### 4.1 ConvNeXt-L 骨干
|
| 89 |
+
|
| 90 |
+
ConvNeXt 是现代卷积网络,吸收了 Transformer 时代的一些结构设计,例如:
|
| 91 |
+
|
| 92 |
+
```text
|
| 93 |
+
大卷积核深度卷积
|
| 94 |
+
更合理的 stage 设计
|
| 95 |
+
GELU 激活
|
| 96 |
+
LayerNorm 风格结构
|
| 97 |
+
倒瓶颈结构
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
本项目使用 torchvision 的 `convnext_large`,并加载 ImageNet-1K 预训练权重。
|
| 101 |
+
|
| 102 |
+
优势:
|
| 103 |
+
|
| 104 |
+
```text
|
| 105 |
+
原生 torchvision 支持,环境稳定
|
| 106 |
+
卷积归纳偏置强,适合小数据和纹理任务
|
| 107 |
+
局部边界表达能力好
|
| 108 |
+
训练速度可控
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
### 4.2 FPN 解码器
|
| 112 |
+
|
| 113 |
+
ConvNeXt-L 输出四个尺度特征:
|
| 114 |
+
|
| 115 |
+
```text
|
| 116 |
+
192, 384, 768, 1536 channels
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
FPN 解码流程:
|
| 120 |
+
|
| 121 |
+
```text
|
| 122 |
+
1. 每层特征用 1x1 卷积投影到 256 通道
|
| 123 |
+
2. 高层特征逐级上采样并与低层相加
|
| 124 |
+
3. 每层用 3x3 卷积平滑
|
| 125 |
+
4. 所有尺度上采样到同一分辨率
|
| 126 |
+
5. 拼接后输出 4 类 logits
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
FPN 的作用:
|
| 130 |
+
|
| 131 |
+
```text
|
| 132 |
+
高层特征提供语义
|
| 133 |
+
低层特征提供边界
|
| 134 |
+
多尺度融合提升小目标和复杂区域分割效果
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
### 4.3 ConvNeXt 训练配置
|
| 138 |
+
|
| 139 |
+
```text
|
| 140 |
+
输入尺寸:512
|
| 141 |
+
batch size:4
|
| 142 |
+
epoch:120
|
| 143 |
+
优化器:AdamW
|
| 144 |
+
基础学习率:6e-5
|
| 145 |
+
backbone 学习率:基础学习率的 0.25
|
| 146 |
+
weight decay:0.01
|
| 147 |
+
学习率策略:warmup + cosine decay
|
| 148 |
+
混合精度:开启
|
| 149 |
+
```
|
| 150 |
+
|
| 151 |
+
骨干网络使用更低学习率,是为了保护预训练特征,降低小数据噪声标签导致的过拟合风险。
|
| 152 |
+
|
| 153 |
+
## 5. Mask2Former-Swin-B 分支
|
| 154 |
+
|
| 155 |
+
### 5.1 Mask2Former 思想
|
| 156 |
+
|
| 157 |
+
Mask2Former 将分割任务建模为 mask classification。
|
| 158 |
+
|
| 159 |
+
普通语义分割直接输出每个像素的类别;Mask2Former 则预测一组 query,每个 query 包含:
|
| 160 |
+
|
| 161 |
+
```text
|
| 162 |
+
类别概率
|
| 163 |
+
对应的二值 mask
|
| 164 |
+
```
|
| 165 |
+
|
| 166 |
+
最终语义分割通过:
|
| 167 |
+
|
| 168 |
+
```text
|
| 169 |
+
类别概率 x mask 概率
|
| 170 |
+
```
|
| 171 |
+
|
| 172 |
+
组合成每个类别的像素概率图。
|
| 173 |
+
|
| 174 |
+
这种方式对复杂、不规则区域更友好,适合珊瑚这类边界复杂的对象。
|
| 175 |
+
|
| 176 |
+
### 5.2 Swin Transformer 骨干
|
| 177 |
+
|
| 178 |
+
Swin Transformer 使用窗口注意力机制:
|
| 179 |
+
|
| 180 |
+
```text
|
| 181 |
+
局部窗口 self-attention 降低计算量
|
| 182 |
+
shifted window 实现跨窗口信息交互
|
| 183 |
+
分层结构输出多尺度特征
|
| 184 |
+
```
|
| 185 |
+
|
| 186 |
+
它同时具备 Transformer 的上下文建模能力和类似 CNN 的层级特征结构。
|
| 187 |
+
|
| 188 |
+
### 5.3 预训练模型
|
| 189 |
+
|
| 190 |
+
Mask2Former 分支使用:
|
| 191 |
+
|
| 192 |
+
```text
|
| 193 |
+
facebook/mask2former-swin-base-ade-semantic
|
| 194 |
+
```
|
| 195 |
+
|
| 196 |
+
该模型是 ADE20K 语义分割预训练模型。ADE20K 为 150 类,本任务为 4 类,因此加载时分类头会重新初始化,这是正常现象。
|
| 197 |
+
|
| 198 |
+
ConvNeXt 分支使用:
|
| 199 |
+
|
| 200 |
+
```text
|
| 201 |
+
torchvision convnext_large ImageNet-1K 权重
|
| 202 |
+
```
|
| 203 |
+
|
| 204 |
+
本地部署路径由配置文件固定:
|
| 205 |
+
|
| 206 |
+
```text
|
| 207 |
+
mask2former.pretrained_dir = /root/autodl-tmp/coral/coral_seg/pretrained/mask2former-swin-base-ade-semantic
|
| 208 |
+
convnext.pretrained_path = /root/autodl-tmp/coral/coral_seg/pretrained/convnext_large-ea097f82.pth
|
| 209 |
+
```
|
| 210 |
+
|
| 211 |
+
这样复现时不依赖临时下载缓存;联网环境可以运行 `tools/download_pretrained.py` 下载,离线环境只需要提前放入对应文件。
|
| 212 |
+
|
| 213 |
+
### 5.4 标签格式转换
|
| 214 |
+
|
| 215 |
+
原始标签格式:
|
| 216 |
+
|
| 217 |
+
```text
|
| 218 |
+
H x W,像素值为 0/1/2/3
|
| 219 |
+
```
|
| 220 |
+
|
| 221 |
+
Mask2Former 训练需要转换为:
|
| 222 |
+
|
| 223 |
+
```text
|
| 224 |
+
class_labels:当前图像中出现过的类别编号
|
| 225 |
+
mask_labels:每个类别对应一个二值 mask
|
| 226 |
+
```
|
| 227 |
+
|
| 228 |
+
例如图像中出现类别 0、1、3,则:
|
| 229 |
+
|
| 230 |
+
```text
|
| 231 |
+
class_labels = [0, 1, 3]
|
| 232 |
+
mask_labels.shape = [3, H, W]
|
| 233 |
+
```
|
| 234 |
+
|
| 235 |
+
## 6. 数据增强
|
| 236 |
+
|
| 237 |
+
水下图像受光照、水体和成像条件影响明显,因此增强策略重点覆盖几何变化和颜色变化。
|
| 238 |
+
|
| 239 |
+
使用增强:
|
| 240 |
+
|
| 241 |
+
```text
|
| 242 |
+
HorizontalFlip
|
| 243 |
+
VerticalFlip
|
| 244 |
+
RandomRotate90
|
| 245 |
+
Affine scale/translate/rotate/shear
|
| 246 |
+
RandomBrightnessContrast
|
| 247 |
+
HueSaturationValue
|
| 248 |
+
RandomGamma
|
| 249 |
+
CLAHE
|
| 250 |
+
GaussianBlur
|
| 251 |
+
MotionBlur
|
| 252 |
+
Resize
|
| 253 |
+
Normalize
|
| 254 |
+
```
|
| 255 |
+
|
| 256 |
+
几何增强模拟:
|
| 257 |
+
|
| 258 |
+
```text
|
| 259 |
+
拍摄方向变化
|
| 260 |
+
视角变化
|
| 261 |
+
尺度变化
|
| 262 |
+
轻微形变
|
| 263 |
+
```
|
| 264 |
+
|
| 265 |
+
颜色增强模拟:
|
| 266 |
+
|
| 267 |
+
```text
|
| 268 |
+
水下光照变化
|
| 269 |
+
色偏
|
| 270 |
+
对比度变化
|
| 271 |
+
相机白平衡差异
|
| 272 |
+
```
|
| 273 |
+
|
| 274 |
+
模糊增强模拟:
|
| 275 |
+
|
| 276 |
+
```text
|
| 277 |
+
水体浑浊
|
| 278 |
+
运动模糊
|
| 279 |
+
散射导致的细节损失
|
| 280 |
+
```
|
| 281 |
+
|
| 282 |
+
## 7. 损失函数
|
| 283 |
+
|
| 284 |
+
ConvNeXt 分支使用组合损失:
|
| 285 |
+
|
| 286 |
+
```text
|
| 287 |
+
Loss = CE + Dice + 0.5 * Lovasz
|
| 288 |
+
```
|
| 289 |
+
|
| 290 |
+
### 7.1 交叉熵损失
|
| 291 |
+
|
| 292 |
+
交叉熵用于像素级分类监督:
|
| 293 |
+
|
| 294 |
+
```text
|
| 295 |
+
CE = -log P(correct_class)
|
| 296 |
+
```
|
| 297 |
+
|
| 298 |
+
优点是稳定、收敛快。
|
| 299 |
+
|
| 300 |
+
### 7.2 Dice Loss
|
| 301 |
+
|
| 302 |
+
Dice 衡量预测区域与真实区域的重叠程度:
|
| 303 |
+
|
| 304 |
+
```text
|
| 305 |
+
Dice = 2 * intersection / (prediction + target)
|
| 306 |
+
```
|
| 307 |
+
|
| 308 |
+
适合类别不均衡和小区域分割。
|
| 309 |
+
|
| 310 |
+
### 7.3 Lovasz Loss
|
| 311 |
+
|
| 312 |
+
Lovasz Softmax 是 IoU 的可优化近似,更贴近比赛 mIoU 指标。
|
| 313 |
+
|
| 314 |
+
作用:
|
| 315 |
+
|
| 316 |
+
```text
|
| 317 |
+
优化目标更接近 mIoU
|
| 318 |
+
提升区域交并比表现
|
| 319 |
+
```
|
| 320 |
+
|
| 321 |
+
### 7.4 Label Smoothing
|
| 322 |
+
|
| 323 |
+
使用:
|
| 324 |
+
|
| 325 |
+
```text
|
| 326 |
+
label_smoothing = 0.05
|
| 327 |
+
```
|
| 328 |
+
|
| 329 |
+
作用:
|
| 330 |
+
|
| 331 |
+
```text
|
| 332 |
+
降低模型对噪声标签的过度自信
|
| 333 |
+
提高泛化能力
|
| 334 |
+
缓解标注误差
|
| 335 |
+
```
|
| 336 |
+
|
| 337 |
+
Mask2Former 分支使用模型内部的分类、mask 和 dice 损失组合。
|
| 338 |
+
|
| 339 |
+
## 8. 学习率策略
|
| 340 |
+
|
| 341 |
+
两个模型均使用:
|
| 342 |
+
|
| 343 |
+
```text
|
| 344 |
+
warmup + cosine decay
|
| 345 |
+
```
|
| 346 |
+
|
| 347 |
+
warmup 作用:
|
| 348 |
+
|
| 349 |
+
```text
|
| 350 |
+
避免训练初期学习率过大破坏预训练权重
|
| 351 |
+
降低 loss 震荡
|
| 352 |
+
提升训练稳定性
|
| 353 |
+
```
|
| 354 |
+
|
| 355 |
+
cosine decay 作用:
|
| 356 |
+
|
| 357 |
+
```text
|
| 358 |
+
后期平滑降低学习率
|
| 359 |
+
帮助模型收敛到更稳定的局部最优
|
| 360 |
+
```
|
| 361 |
+
|
| 362 |
+
## 9. 噪声标签处理
|
| 363 |
+
|
| 364 |
+
当前方案通过以下方式降低噪声标签影响:
|
| 365 |
+
|
| 366 |
+
```text
|
| 367 |
+
使用强预训练模型
|
| 368 |
+
使用 label smoothing
|
| 369 |
+
使用 Dice 和 Lovasz 关注区域级一致性
|
| 370 |
+
强数据增强提升泛化
|
| 371 |
+
保存验证集 best checkpoint
|
| 372 |
+
双模型融合降低单模型噪声敏感性
|
| 373 |
+
```
|
| 374 |
+
|
| 375 |
+
没有使用测试集伪标签、自训练或测试集分布统计,符合比赛规则。
|
| 376 |
+
|
| 377 |
+
## 10. 融合推理
|
| 378 |
+
|
| 379 |
+
两个模型分别输出每个类别的概率图:
|
| 380 |
+
|
| 381 |
+
```text
|
| 382 |
+
prob_convnext: [4, H, W]
|
| 383 |
+
prob_mask2former: [4, H, W]
|
| 384 |
+
```
|
| 385 |
+
|
| 386 |
+
融合:
|
| 387 |
+
|
| 388 |
+
```text
|
| 389 |
+
prob = 0.45 * prob_convnext + 0.55 * prob_mask2former
|
| 390 |
+
pred = argmax(prob)
|
| 391 |
+
```
|
| 392 |
+
|
| 393 |
+
使用概率融合而不是硬投票的原因:
|
| 394 |
+
|
| 395 |
+
```text
|
| 396 |
+
可以保留模型置信度
|
| 397 |
+
对边界和混淆区域更平滑
|
| 398 |
+
高置信模型可以纠正低置信模型
|
| 399 |
+
```
|
| 400 |
+
|
| 401 |
+
## 11. TTA 推理
|
| 402 |
+
|
| 403 |
+
当前使用:
|
| 404 |
+
|
| 405 |
+
```text
|
| 406 |
+
原图
|
| 407 |
+
水平翻转
|
| 408 |
+
```
|
| 409 |
+
|
| 410 |
+
流程:
|
| 411 |
+
|
| 412 |
+
```text
|
| 413 |
+
1. 原图推理得到概率
|
| 414 |
+
2. 水平翻转图像推理
|
| 415 |
+
3. 将翻转预测翻回原方向
|
| 416 |
+
4. 对概率求平均
|
| 417 |
+
```
|
| 418 |
+
|
| 419 |
+
TTA 可以降低方向相关误差,提升预测稳定性。
|
| 420 |
+
|
| 421 |
+
## 12. mIoU 计算原理
|
| 422 |
+
|
| 423 |
+
对每个类别 c:
|
| 424 |
+
|
| 425 |
+
```text
|
| 426 |
+
TP_c:预测为 c 且真值为 c 的像素数
|
| 427 |
+
FP_c:预测为 c 但真值不是 c 的像素数
|
| 428 |
+
FN_c:真值为 c 但预测不是 c 的像素数
|
| 429 |
+
```
|
| 430 |
+
|
| 431 |
+
类别 IoU:
|
| 432 |
+
|
| 433 |
+
```text
|
| 434 |
+
IoU_c = TP_c / (TP_c + FP_c + FN_c)
|
| 435 |
+
```
|
| 436 |
+
|
| 437 |
+
最终:
|
| 438 |
+
|
| 439 |
+
```text
|
| 440 |
+
mIoU = mean(IoU_0, IoU_1, IoU_2, IoU_3)
|
| 441 |
+
```
|
| 442 |
+
|
| 443 |
+
这里的“区域”是同一类别的像素集合,不是实例框、连通块或单独目标实例。
|
| 444 |
+
|
| 445 |
+
## 13. 本地 test mask 说明
|
| 446 |
+
|
| 447 |
+
`data_fresh/test_raw/PrecisionLabel800/mask` 是 RGB 彩色图,不是标准单通道标签。
|
| 448 |
+
|
| 449 |
+
统计到的颜色:
|
| 450 |
+
|
| 451 |
+
```text
|
| 452 |
+
(0, 0, 0)
|
| 453 |
+
(240, 110, 170)
|
| 454 |
+
(240, 171, 203)
|
| 455 |
+
(0, 162, 232)
|
| 456 |
+
```
|
| 457 |
+
|
| 458 |
+
当前最合理颜色映射:
|
| 459 |
+
|
| 460 |
+
```text
|
| 461 |
+
(0, 0, 0) -> 0 背景
|
| 462 |
+
(240, 110, 170) -> 1 活珊瑚
|
| 463 |
+
(240, 171, 203) -> 2 死珊瑚
|
| 464 |
+
(0, 162, 232) -> 3 白化珊瑚
|
| 465 |
+
```
|
| 466 |
+
|
| 467 |
+
如果该目录不是官方真值,则该结果不能代表平台成绩。
|
| 468 |
+
|
| 469 |
+
## 14. 复现性设计
|
| 470 |
+
|
| 471 |
+
为满足 A30 单卡 24G、24 小时内复现,方案做了以下取舍:
|
| 472 |
+
|
| 473 |
+
```text
|
| 474 |
+
不使用 5-fold
|
| 475 |
+
不使用第三个大模型
|
| 476 |
+
不使用超大输入尺寸
|
| 477 |
+
不使用测试集伪标签
|
| 478 |
+
不使用测试集统计更新
|
| 479 |
+
固定 seed
|
| 480 |
+
保存固定 train/val split
|
| 481 |
+
保存 best/latest checkpoint
|
| 482 |
+
提供完整训练、推理和打包脚本
|
| 483 |
+
```
|
| 484 |
+
|
| 485 |
+
推荐复现流程:
|
| 486 |
+
|
| 487 |
+
```text
|
| 488 |
+
1. 检查数据
|
| 489 |
+
2. 下载预训练权重
|
| 490 |
+
3. 训练 ConvNeXt-L-FPN
|
| 491 |
+
4. 训练 Mask2Former-Swin-B
|
| 492 |
+
5. 验证集融合评估
|
| 493 |
+
6. 测试集融合推理
|
| 494 |
+
7. 生成 results.zip
|
| 495 |
+
```
|
| 496 |
+
|
| 497 |
+
## 15. 代码模块说明
|
| 498 |
+
|
| 499 |
+
```text
|
| 500 |
+
coral_seg/coral_seg/dataset.py
|
| 501 |
+
```
|
| 502 |
+
|
| 503 |
+
负责图像读取、标签读取、数据增强和 Mask2Former 标签格式转换。
|
| 504 |
+
|
| 505 |
+
```text
|
| 506 |
+
coral_seg/coral_seg/model_convnext_fpn.py
|
| 507 |
+
```
|
| 508 |
+
|
| 509 |
+
负责 ConvNeXt-L 骨��和 FPN 解码器。
|
| 510 |
+
|
| 511 |
+
```text
|
| 512 |
+
coral_seg/coral_seg/losses.py
|
| 513 |
+
```
|
| 514 |
+
|
| 515 |
+
负责 CE、Dice、Lovasz 和组合损失。
|
| 516 |
+
|
| 517 |
+
```text
|
| 518 |
+
coral_seg/tools/train_convnext.py
|
| 519 |
+
```
|
| 520 |
+
|
| 521 |
+
负责 ConvNeXt 分支训练、验证和 checkpoint 保存。
|
| 522 |
+
|
| 523 |
+
```text
|
| 524 |
+
coral_seg/tools/train_mask2former.py
|
| 525 |
+
```
|
| 526 |
+
|
| 527 |
+
负责 Mask2Former 分支训练、验证和 HuggingFace 格式权重保存。
|
| 528 |
+
|
| 529 |
+
```text
|
| 530 |
+
coral_seg/tools/infer_ensemble.py
|
| 531 |
+
```
|
| 532 |
+
|
| 533 |
+
负责双模型 TTA 推理、概率融合、PNG 输出和 `results.zip` 生成。
|
| 534 |
+
|
| 535 |
+
```text
|
| 536 |
+
coral_seg/tools/eval_ensemble_val.py
|
| 537 |
+
```
|
| 538 |
+
|
| 539 |
+
负责验证集双模型融合 mIoU 计算。
|
| 540 |
+
|
| 541 |
+
```text
|
| 542 |
+
coral_seg/tools/eval_predictions.py
|
| 543 |
+
```
|
| 544 |
+
|
| 545 |
+
负责已有预测和标签目录之间的 mIoU 计算,支持 RGB 标签颜色映射。
|
| 546 |
+
|
| 547 |
+
```text
|
| 548 |
+
coral_seg/tools/visualize_results.py
|
| 549 |
+
```
|
| 550 |
+
|
| 551 |
+
负责预测结果彩色化和叠加可视化。
|
| 552 |
+
|
| 553 |
+
## 16. 可提升方向
|
| 554 |
+
|
| 555 |
+
如果后续还有时间,可以尝试:
|
| 556 |
+
|
| 557 |
+
```text
|
| 558 |
+
调整融合权重,例如 0.50/0.50 或 0.60/0.40
|
| 559 |
+
对白化珊瑚增加类别权重
|
| 560 |
+
增加轻量多尺度 TTA
|
| 561 |
+
人工清洗明显错误标签
|
| 562 |
+
最终阶段使用 train_full.txt 全量复训
|
| 563 |
+
后处理去除极小孤立区域
|
| 564 |
+
```
|
| 565 |
+
|
| 566 |
+
正式复现阶段应优先保持当前稳定配置,避免引入不可控变量。
|
coral_seg/logs/convnext_train.log
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
coral_seg/logs/mask2former_train.log
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
coral_seg/pretrained/convnext_large-ea097f82.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ea097f822cdb2cab40905cec3949f4bdf6d6bf1d546c3ec5e43f0b1c6275e144
|
| 3 |
+
size 791189585
|
coral_seg/pretrained/mask2former-swin-base-ade-semantic/.gitattributes
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
coral_seg/pretrained/mask2former-swin-base-ade-semantic/config.json
ADDED
|
@@ -0,0 +1,454 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_commit_hash": null,
|
| 3 |
+
"activation_function": "relu",
|
| 4 |
+
"architectures": [
|
| 5 |
+
"Mask2FormerForUniversalSegmentation"
|
| 6 |
+
],
|
| 7 |
+
"backbone_config": {
|
| 8 |
+
"_name_or_path": "",
|
| 9 |
+
"add_cross_attention": false,
|
| 10 |
+
"architectures": null,
|
| 11 |
+
"attention_probs_dropout_prob": 0.0,
|
| 12 |
+
"bad_words_ids": null,
|
| 13 |
+
"begin_suppress_tokens": null,
|
| 14 |
+
"bos_token_id": null,
|
| 15 |
+
"chunk_size_feed_forward": 0,
|
| 16 |
+
"cross_attention_hidden_size": null,
|
| 17 |
+
"decoder_start_token_id": null,
|
| 18 |
+
"depths": [
|
| 19 |
+
2,
|
| 20 |
+
2,
|
| 21 |
+
18,
|
| 22 |
+
2
|
| 23 |
+
],
|
| 24 |
+
"diversity_penalty": 0.0,
|
| 25 |
+
"do_sample": false,
|
| 26 |
+
"drop_path_rate": 0.3,
|
| 27 |
+
"early_stopping": false,
|
| 28 |
+
"embed_dim": 128,
|
| 29 |
+
"encoder_no_repeat_ngram_size": 0,
|
| 30 |
+
"encoder_stride": 32,
|
| 31 |
+
"eos_token_id": null,
|
| 32 |
+
"exponential_decay_length_penalty": null,
|
| 33 |
+
"finetuning_task": null,
|
| 34 |
+
"forced_bos_token_id": null,
|
| 35 |
+
"forced_eos_token_id": null,
|
| 36 |
+
"hidden_act": "gelu",
|
| 37 |
+
"hidden_dropout_prob": 0.0,
|
| 38 |
+
"hidden_size": 1024,
|
| 39 |
+
"id2label": {
|
| 40 |
+
"0": "LABEL_0",
|
| 41 |
+
"1": "LABEL_1"
|
| 42 |
+
},
|
| 43 |
+
"image_size": 224,
|
| 44 |
+
"initializer_range": 0.02,
|
| 45 |
+
"is_decoder": false,
|
| 46 |
+
"is_encoder_decoder": false,
|
| 47 |
+
"label2id": {
|
| 48 |
+
"LABEL_0": 0,
|
| 49 |
+
"LABEL_1": 1
|
| 50 |
+
},
|
| 51 |
+
"layer_norm_eps": 1e-05,
|
| 52 |
+
"length_penalty": 1.0,
|
| 53 |
+
"max_length": 20,
|
| 54 |
+
"min_length": 0,
|
| 55 |
+
"mlp_ratio": 4.0,
|
| 56 |
+
"model_type": "swin",
|
| 57 |
+
"no_repeat_ngram_size": 0,
|
| 58 |
+
"num_beam_groups": 1,
|
| 59 |
+
"num_beams": 1,
|
| 60 |
+
"num_channels": 3,
|
| 61 |
+
"num_heads": [
|
| 62 |
+
4,
|
| 63 |
+
8,
|
| 64 |
+
16,
|
| 65 |
+
32
|
| 66 |
+
],
|
| 67 |
+
"num_layers": 4,
|
| 68 |
+
"num_return_sequences": 1,
|
| 69 |
+
"out_features": [
|
| 70 |
+
"stage1",
|
| 71 |
+
"stage2",
|
| 72 |
+
"stage3",
|
| 73 |
+
"stage4"
|
| 74 |
+
],
|
| 75 |
+
"output_attentions": false,
|
| 76 |
+
"output_hidden_states": false,
|
| 77 |
+
"output_scores": false,
|
| 78 |
+
"pad_token_id": null,
|
| 79 |
+
"patch_size": 4,
|
| 80 |
+
"path_norm": true,
|
| 81 |
+
"prefix": null,
|
| 82 |
+
"problem_type": null,
|
| 83 |
+
"pruned_heads": {},
|
| 84 |
+
"qkv_bias": true,
|
| 85 |
+
"remove_invalid_values": false,
|
| 86 |
+
"repetition_penalty": 1.0,
|
| 87 |
+
"return_dict": true,
|
| 88 |
+
"return_dict_in_generate": false,
|
| 89 |
+
"sep_token_id": null,
|
| 90 |
+
"stage_names": [
|
| 91 |
+
"stem",
|
| 92 |
+
"stage1",
|
| 93 |
+
"stage2",
|
| 94 |
+
"stage3",
|
| 95 |
+
"stage4"
|
| 96 |
+
],
|
| 97 |
+
"suppress_tokens": null,
|
| 98 |
+
"task_specific_params": null,
|
| 99 |
+
"temperature": 1.0,
|
| 100 |
+
"tf_legacy_loss": false,
|
| 101 |
+
"tie_encoder_decoder": false,
|
| 102 |
+
"tie_word_embeddings": true,
|
| 103 |
+
"tokenizer_class": null,
|
| 104 |
+
"top_k": 50,
|
| 105 |
+
"top_p": 1.0,
|
| 106 |
+
"torch_dtype": null,
|
| 107 |
+
"torchscript": false,
|
| 108 |
+
"transformers_version": "4.26.0.dev0",
|
| 109 |
+
"typical_p": 1.0,
|
| 110 |
+
"use_absolute_embeddings": false,
|
| 111 |
+
"use_bfloat16": false,
|
| 112 |
+
"window_size": 12
|
| 113 |
+
},
|
| 114 |
+
"class_weight": 2.0,
|
| 115 |
+
"common_stride": 4,
|
| 116 |
+
"decoder_layers": 10,
|
| 117 |
+
"dice_weight": 5.0,
|
| 118 |
+
"dim_feedforward": 2048,
|
| 119 |
+
"dropout": 0.0,
|
| 120 |
+
"encoder_feedforward_dim": 1024,
|
| 121 |
+
"encoder_layers": 6,
|
| 122 |
+
"enforce_input_proj": false,
|
| 123 |
+
"enforce_input_projection": false,
|
| 124 |
+
"feature_size": 256,
|
| 125 |
+
"feature_strides": [
|
| 126 |
+
4,
|
| 127 |
+
8,
|
| 128 |
+
16,
|
| 129 |
+
32
|
| 130 |
+
],
|
| 131 |
+
"hidden_dim": 256,
|
| 132 |
+
"id2label": {
|
| 133 |
+
"0": "wall",
|
| 134 |
+
"1": "building",
|
| 135 |
+
"2": "sky",
|
| 136 |
+
"3": "floor",
|
| 137 |
+
"4": "tree",
|
| 138 |
+
"5": "ceiling",
|
| 139 |
+
"6": "road",
|
| 140 |
+
"7": "bed ",
|
| 141 |
+
"8": "windowpane",
|
| 142 |
+
"9": "grass",
|
| 143 |
+
"10": "cabinet",
|
| 144 |
+
"11": "sidewalk",
|
| 145 |
+
"12": "person",
|
| 146 |
+
"13": "earth",
|
| 147 |
+
"14": "door",
|
| 148 |
+
"15": "table",
|
| 149 |
+
"16": "mountain",
|
| 150 |
+
"17": "plant",
|
| 151 |
+
"18": "curtain",
|
| 152 |
+
"19": "chair",
|
| 153 |
+
"20": "car",
|
| 154 |
+
"21": "water",
|
| 155 |
+
"22": "painting",
|
| 156 |
+
"23": "sofa",
|
| 157 |
+
"24": "shelf",
|
| 158 |
+
"25": "house",
|
| 159 |
+
"26": "sea",
|
| 160 |
+
"27": "mirror",
|
| 161 |
+
"28": "rug",
|
| 162 |
+
"29": "field",
|
| 163 |
+
"30": "armchair",
|
| 164 |
+
"31": "seat",
|
| 165 |
+
"32": "fence",
|
| 166 |
+
"33": "desk",
|
| 167 |
+
"34": "rock",
|
| 168 |
+
"35": "wardrobe",
|
| 169 |
+
"36": "lamp",
|
| 170 |
+
"37": "bathtub",
|
| 171 |
+
"38": "railing",
|
| 172 |
+
"39": "cushion",
|
| 173 |
+
"40": "base",
|
| 174 |
+
"41": "box",
|
| 175 |
+
"42": "column",
|
| 176 |
+
"43": "signboard",
|
| 177 |
+
"44": "chest of drawers",
|
| 178 |
+
"45": "counter",
|
| 179 |
+
"46": "sand",
|
| 180 |
+
"47": "sink",
|
| 181 |
+
"48": "skyscraper",
|
| 182 |
+
"49": "fireplace",
|
| 183 |
+
"50": "refrigerator",
|
| 184 |
+
"51": "grandstand",
|
| 185 |
+
"52": "path",
|
| 186 |
+
"53": "stairs",
|
| 187 |
+
"54": "runway",
|
| 188 |
+
"55": "case",
|
| 189 |
+
"56": "pool table",
|
| 190 |
+
"57": "pillow",
|
| 191 |
+
"58": "screen door",
|
| 192 |
+
"59": "stairway",
|
| 193 |
+
"60": "river",
|
| 194 |
+
"61": "bridge",
|
| 195 |
+
"62": "bookcase",
|
| 196 |
+
"63": "blind",
|
| 197 |
+
"64": "coffee table",
|
| 198 |
+
"65": "toilet",
|
| 199 |
+
"66": "flower",
|
| 200 |
+
"67": "book",
|
| 201 |
+
"68": "hill",
|
| 202 |
+
"69": "bench",
|
| 203 |
+
"70": "countertop",
|
| 204 |
+
"71": "stove",
|
| 205 |
+
"72": "palm",
|
| 206 |
+
"73": "kitchen island",
|
| 207 |
+
"74": "computer",
|
| 208 |
+
"75": "swivel chair",
|
| 209 |
+
"76": "boat",
|
| 210 |
+
"77": "bar",
|
| 211 |
+
"78": "arcade machine",
|
| 212 |
+
"79": "hovel",
|
| 213 |
+
"80": "bus",
|
| 214 |
+
"81": "towel",
|
| 215 |
+
"82": "light",
|
| 216 |
+
"83": "truck",
|
| 217 |
+
"84": "tower",
|
| 218 |
+
"85": "chandelier",
|
| 219 |
+
"86": "awning",
|
| 220 |
+
"87": "streetlight",
|
| 221 |
+
"88": "booth",
|
| 222 |
+
"89": "television receiver",
|
| 223 |
+
"90": "airplane",
|
| 224 |
+
"91": "dirt track",
|
| 225 |
+
"92": "apparel",
|
| 226 |
+
"93": "pole",
|
| 227 |
+
"94": "land",
|
| 228 |
+
"95": "bannister",
|
| 229 |
+
"96": "escalator",
|
| 230 |
+
"97": "ottoman",
|
| 231 |
+
"98": "bottle",
|
| 232 |
+
"99": "buffet",
|
| 233 |
+
"100": "poster",
|
| 234 |
+
"101": "stage",
|
| 235 |
+
"102": "van",
|
| 236 |
+
"103": "ship",
|
| 237 |
+
"104": "fountain",
|
| 238 |
+
"105": "conveyer belt",
|
| 239 |
+
"106": "canopy",
|
| 240 |
+
"107": "washer",
|
| 241 |
+
"108": "plaything",
|
| 242 |
+
"109": "swimming pool",
|
| 243 |
+
"110": "stool",
|
| 244 |
+
"111": "barrel",
|
| 245 |
+
"112": "basket",
|
| 246 |
+
"113": "waterfall",
|
| 247 |
+
"114": "tent",
|
| 248 |
+
"115": "bag",
|
| 249 |
+
"116": "minibike",
|
| 250 |
+
"117": "cradle",
|
| 251 |
+
"118": "oven",
|
| 252 |
+
"119": "ball",
|
| 253 |
+
"120": "food",
|
| 254 |
+
"121": "step",
|
| 255 |
+
"122": "tank",
|
| 256 |
+
"123": "trade name",
|
| 257 |
+
"124": "microwave",
|
| 258 |
+
"125": "pot",
|
| 259 |
+
"126": "animal",
|
| 260 |
+
"127": "bicycle",
|
| 261 |
+
"128": "lake",
|
| 262 |
+
"129": "dishwasher",
|
| 263 |
+
"130": "screen",
|
| 264 |
+
"131": "blanket",
|
| 265 |
+
"132": "sculpture",
|
| 266 |
+
"133": "hood",
|
| 267 |
+
"134": "sconce",
|
| 268 |
+
"135": "vase",
|
| 269 |
+
"136": "traffic light",
|
| 270 |
+
"137": "tray",
|
| 271 |
+
"138": "ashcan",
|
| 272 |
+
"139": "fan",
|
| 273 |
+
"140": "pier",
|
| 274 |
+
"141": "crt screen",
|
| 275 |
+
"142": "plate",
|
| 276 |
+
"143": "monitor",
|
| 277 |
+
"144": "bulletin board",
|
| 278 |
+
"145": "shower",
|
| 279 |
+
"146": "radiator",
|
| 280 |
+
"147": "glass",
|
| 281 |
+
"148": "clock",
|
| 282 |
+
"149": "flag"
|
| 283 |
+
},
|
| 284 |
+
"ignore_value": 255,
|
| 285 |
+
"importance_sample_ratio": 0.75,
|
| 286 |
+
"init_std": 0.02,
|
| 287 |
+
"init_xavier_std": 1.0,
|
| 288 |
+
"label2id": {
|
| 289 |
+
"airplane": 90,
|
| 290 |
+
"animal": 126,
|
| 291 |
+
"apparel": 92,
|
| 292 |
+
"arcade machine": 78,
|
| 293 |
+
"armchair": 30,
|
| 294 |
+
"ashcan": 138,
|
| 295 |
+
"awning": 86,
|
| 296 |
+
"bag": 115,
|
| 297 |
+
"ball": 119,
|
| 298 |
+
"bannister": 95,
|
| 299 |
+
"bar": 77,
|
| 300 |
+
"barrel": 111,
|
| 301 |
+
"base": 40,
|
| 302 |
+
"basket": 112,
|
| 303 |
+
"bathtub": 37,
|
| 304 |
+
"bed ": 7,
|
| 305 |
+
"bench": 69,
|
| 306 |
+
"bicycle": 127,
|
| 307 |
+
"blanket": 131,
|
| 308 |
+
"blind": 63,
|
| 309 |
+
"boat": 76,
|
| 310 |
+
"book": 67,
|
| 311 |
+
"bookcase": 62,
|
| 312 |
+
"booth": 88,
|
| 313 |
+
"bottle": 98,
|
| 314 |
+
"box": 41,
|
| 315 |
+
"bridge": 61,
|
| 316 |
+
"buffet": 99,
|
| 317 |
+
"building": 1,
|
| 318 |
+
"bulletin board": 144,
|
| 319 |
+
"bus": 80,
|
| 320 |
+
"cabinet": 10,
|
| 321 |
+
"canopy": 106,
|
| 322 |
+
"car": 20,
|
| 323 |
+
"case": 55,
|
| 324 |
+
"ceiling": 5,
|
| 325 |
+
"chair": 19,
|
| 326 |
+
"chandelier": 85,
|
| 327 |
+
"chest of drawers": 44,
|
| 328 |
+
"clock": 148,
|
| 329 |
+
"coffee table": 64,
|
| 330 |
+
"column": 42,
|
| 331 |
+
"computer": 74,
|
| 332 |
+
"conveyer belt": 105,
|
| 333 |
+
"counter": 45,
|
| 334 |
+
"countertop": 70,
|
| 335 |
+
"cradle": 117,
|
| 336 |
+
"crt screen": 141,
|
| 337 |
+
"curtain": 18,
|
| 338 |
+
"cushion": 39,
|
| 339 |
+
"desk": 33,
|
| 340 |
+
"dirt track": 91,
|
| 341 |
+
"dishwasher": 129,
|
| 342 |
+
"door": 14,
|
| 343 |
+
"earth": 13,
|
| 344 |
+
"escalator": 96,
|
| 345 |
+
"fan": 139,
|
| 346 |
+
"fence": 32,
|
| 347 |
+
"field": 29,
|
| 348 |
+
"fireplace": 49,
|
| 349 |
+
"flag": 149,
|
| 350 |
+
"floor": 3,
|
| 351 |
+
"flower": 66,
|
| 352 |
+
"food": 120,
|
| 353 |
+
"fountain": 104,
|
| 354 |
+
"glass": 147,
|
| 355 |
+
"grandstand": 51,
|
| 356 |
+
"grass": 9,
|
| 357 |
+
"hill": 68,
|
| 358 |
+
"hood": 133,
|
| 359 |
+
"house": 25,
|
| 360 |
+
"hovel": 79,
|
| 361 |
+
"kitchen island": 73,
|
| 362 |
+
"lake": 128,
|
| 363 |
+
"lamp": 36,
|
| 364 |
+
"land": 94,
|
| 365 |
+
"light": 82,
|
| 366 |
+
"microwave": 124,
|
| 367 |
+
"minibike": 116,
|
| 368 |
+
"mirror": 27,
|
| 369 |
+
"monitor": 143,
|
| 370 |
+
"mountain": 16,
|
| 371 |
+
"ottoman": 97,
|
| 372 |
+
"oven": 118,
|
| 373 |
+
"painting": 22,
|
| 374 |
+
"palm": 72,
|
| 375 |
+
"path": 52,
|
| 376 |
+
"person": 12,
|
| 377 |
+
"pier": 140,
|
| 378 |
+
"pillow": 57,
|
| 379 |
+
"plant": 17,
|
| 380 |
+
"plate": 142,
|
| 381 |
+
"plaything": 108,
|
| 382 |
+
"pole": 93,
|
| 383 |
+
"pool table": 56,
|
| 384 |
+
"poster": 100,
|
| 385 |
+
"pot": 125,
|
| 386 |
+
"radiator": 146,
|
| 387 |
+
"railing": 38,
|
| 388 |
+
"refrigerator": 50,
|
| 389 |
+
"river": 60,
|
| 390 |
+
"road": 6,
|
| 391 |
+
"rock": 34,
|
| 392 |
+
"rug": 28,
|
| 393 |
+
"runway": 54,
|
| 394 |
+
"sand": 46,
|
| 395 |
+
"sconce": 134,
|
| 396 |
+
"screen": 130,
|
| 397 |
+
"screen door": 58,
|
| 398 |
+
"sculpture": 132,
|
| 399 |
+
"sea": 26,
|
| 400 |
+
"seat": 31,
|
| 401 |
+
"shelf": 24,
|
| 402 |
+
"ship": 103,
|
| 403 |
+
"shower": 145,
|
| 404 |
+
"sidewalk": 11,
|
| 405 |
+
"signboard": 43,
|
| 406 |
+
"sink": 47,
|
| 407 |
+
"sky": 2,
|
| 408 |
+
"skyscraper": 48,
|
| 409 |
+
"sofa": 23,
|
| 410 |
+
"stage": 101,
|
| 411 |
+
"stairs": 53,
|
| 412 |
+
"stairway": 59,
|
| 413 |
+
"step": 121,
|
| 414 |
+
"stool": 110,
|
| 415 |
+
"stove": 71,
|
| 416 |
+
"streetlight": 87,
|
| 417 |
+
"swimming pool": 109,
|
| 418 |
+
"swivel chair": 75,
|
| 419 |
+
"table": 15,
|
| 420 |
+
"tank": 122,
|
| 421 |
+
"television receiver": 89,
|
| 422 |
+
"tent": 114,
|
| 423 |
+
"toilet": 65,
|
| 424 |
+
"towel": 81,
|
| 425 |
+
"tower": 84,
|
| 426 |
+
"trade name": 123,
|
| 427 |
+
"traffic light": 136,
|
| 428 |
+
"tray": 137,
|
| 429 |
+
"tree": 4,
|
| 430 |
+
"truck": 83,
|
| 431 |
+
"van": 102,
|
| 432 |
+
"vase": 135,
|
| 433 |
+
"wall": 0,
|
| 434 |
+
"wardrobe": 35,
|
| 435 |
+
"washer": 107,
|
| 436 |
+
"water": 21,
|
| 437 |
+
"waterfall": 113,
|
| 438 |
+
"windowpane": 8
|
| 439 |
+
},
|
| 440 |
+
"mask_feature_size": 256,
|
| 441 |
+
"mask_weight": 5.0,
|
| 442 |
+
"model_type": "mask2former",
|
| 443 |
+
"no_object_weight": 0.1,
|
| 444 |
+
"num_attention_heads": 8,
|
| 445 |
+
"num_hidden_layers": 10,
|
| 446 |
+
"num_queries": 100,
|
| 447 |
+
"output_auxiliary_logits": null,
|
| 448 |
+
"oversample_ratio": 3.0,
|
| 449 |
+
"pre_norm": false,
|
| 450 |
+
"torch_dtype": "float32",
|
| 451 |
+
"train_num_points": 12544,
|
| 452 |
+
"transformers_version": null,
|
| 453 |
+
"use_auxiliary_loss": true
|
| 454 |
+
}
|
coral_seg/pretrained/mask2former-swin-base-ade-semantic/model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:09e2ba3efa9f18fa6a313c88ef7d862fc15da10ddb4bbc034df54160089e130e
|
| 3 |
+
size 431785608
|
coral_seg/pretrained/mask2former-swin-base-ade-semantic/preprocessor_config.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_max_size": 2560,
|
| 3 |
+
"do_normalize": true,
|
| 4 |
+
"do_rescale": true,
|
| 5 |
+
"do_resize": true,
|
| 6 |
+
"ignore_index": 255,
|
| 7 |
+
"image_mean": [
|
| 8 |
+
0.48500001430511475,
|
| 9 |
+
0.4560000002384186,
|
| 10 |
+
0.4059999883174896
|
| 11 |
+
],
|
| 12 |
+
"image_processor_type": "Mask2FormerImageProcessor",
|
| 13 |
+
"image_std": [
|
| 14 |
+
0.2290000021457672,
|
| 15 |
+
0.2239999920129776,
|
| 16 |
+
0.22499999403953552
|
| 17 |
+
],
|
| 18 |
+
"num_labels": 150,
|
| 19 |
+
"reduce_labels": false,
|
| 20 |
+
"resample": 2,
|
| 21 |
+
"rescale_factor": 0.00392156862745098,
|
| 22 |
+
"size": {
|
| 23 |
+
"height": 384,
|
| 24 |
+
"width": 384
|
| 25 |
+
},
|
| 26 |
+
"size_divisor": 32
|
| 27 |
+
}
|
coral_seg/pretrained/mask2former-swin-base-ade-semantic/pytorch_model.bin
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:197bab4870fea7287635f62fe52538a4cf053767ddd0f2c9cb7611deca618f1d
|
| 3 |
+
size 431950789
|
coral_seg/requirements.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch==2.3.0
|
| 2 |
+
torchvision==0.18.0
|
| 3 |
+
transformers==4.46.3
|
| 4 |
+
timm==1.0.27
|
| 5 |
+
albumentations==2.0.8
|
| 6 |
+
opencv-python-headless==4.13.0.92
|
| 7 |
+
safetensors==0.8.0
|
| 8 |
+
accelerate==1.14.0
|
| 9 |
+
numpy>=1.26
|
| 10 |
+
Pillow>=10.0
|
| 11 |
+
PyYAML>=6.0
|
coral_seg/splits/train.txt
ADDED
|
@@ -0,0 +1,2550 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0000
|
| 2 |
+
0001
|
| 3 |
+
0002
|
| 4 |
+
0004
|
| 5 |
+
0005
|
| 6 |
+
0006
|
| 7 |
+
0007
|
| 8 |
+
0009
|
| 9 |
+
0011
|
| 10 |
+
0012
|
| 11 |
+
0013
|
| 12 |
+
0015
|
| 13 |
+
0016
|
| 14 |
+
0017
|
| 15 |
+
0018
|
| 16 |
+
0020
|
| 17 |
+
0021
|
| 18 |
+
0022
|
| 19 |
+
0023
|
| 20 |
+
0025
|
| 21 |
+
0026
|
| 22 |
+
0027
|
| 23 |
+
0028
|
| 24 |
+
0030
|
| 25 |
+
0031
|
| 26 |
+
0032
|
| 27 |
+
0033
|
| 28 |
+
0036
|
| 29 |
+
0037
|
| 30 |
+
0038
|
| 31 |
+
0039
|
| 32 |
+
0040
|
| 33 |
+
0041
|
| 34 |
+
0042
|
| 35 |
+
0043
|
| 36 |
+
0044
|
| 37 |
+
0046
|
| 38 |
+
0047
|
| 39 |
+
0049
|
| 40 |
+
0050
|
| 41 |
+
0051
|
| 42 |
+
0052
|
| 43 |
+
0054
|
| 44 |
+
0055
|
| 45 |
+
0056
|
| 46 |
+
0058
|
| 47 |
+
0059
|
| 48 |
+
0060
|
| 49 |
+
0064
|
| 50 |
+
0065
|
| 51 |
+
0067
|
| 52 |
+
0068
|
| 53 |
+
0069
|
| 54 |
+
0070
|
| 55 |
+
0071
|
| 56 |
+
0072
|
| 57 |
+
0073
|
| 58 |
+
0074
|
| 59 |
+
0075
|
| 60 |
+
0076
|
| 61 |
+
0077
|
| 62 |
+
0078
|
| 63 |
+
0080
|
| 64 |
+
0081
|
| 65 |
+
0082
|
| 66 |
+
0083
|
| 67 |
+
0085
|
| 68 |
+
0086
|
| 69 |
+
0087
|
| 70 |
+
0088
|
| 71 |
+
0089
|
| 72 |
+
0090
|
| 73 |
+
0091
|
| 74 |
+
0092
|
| 75 |
+
0093
|
| 76 |
+
0094
|
| 77 |
+
0095
|
| 78 |
+
0096
|
| 79 |
+
0097
|
| 80 |
+
0098
|
| 81 |
+
0100
|
| 82 |
+
0101
|
| 83 |
+
0102
|
| 84 |
+
0103
|
| 85 |
+
0105
|
| 86 |
+
0107
|
| 87 |
+
0108
|
| 88 |
+
0110
|
| 89 |
+
0111
|
| 90 |
+
0113
|
| 91 |
+
0114
|
| 92 |
+
0115
|
| 93 |
+
0116
|
| 94 |
+
0117
|
| 95 |
+
0118
|
| 96 |
+
0119
|
| 97 |
+
0120
|
| 98 |
+
0121
|
| 99 |
+
0122
|
| 100 |
+
0123
|
| 101 |
+
0124
|
| 102 |
+
0125
|
| 103 |
+
0126
|
| 104 |
+
0127
|
| 105 |
+
0128
|
| 106 |
+
0129
|
| 107 |
+
0131
|
| 108 |
+
0132
|
| 109 |
+
0133
|
| 110 |
+
0134
|
| 111 |
+
0137
|
| 112 |
+
0138
|
| 113 |
+
0139
|
| 114 |
+
0140
|
| 115 |
+
0141
|
| 116 |
+
0142
|
| 117 |
+
0143
|
| 118 |
+
0144
|
| 119 |
+
0145
|
| 120 |
+
0146
|
| 121 |
+
0148
|
| 122 |
+
0149
|
| 123 |
+
0150
|
| 124 |
+
0151
|
| 125 |
+
0152
|
| 126 |
+
0153
|
| 127 |
+
0154
|
| 128 |
+
0155
|
| 129 |
+
0156
|
| 130 |
+
0157
|
| 131 |
+
0158
|
| 132 |
+
0159
|
| 133 |
+
0160
|
| 134 |
+
0162
|
| 135 |
+
0163
|
| 136 |
+
0164
|
| 137 |
+
0165
|
| 138 |
+
0166
|
| 139 |
+
0168
|
| 140 |
+
0169
|
| 141 |
+
0170
|
| 142 |
+
0171
|
| 143 |
+
0172
|
| 144 |
+
0174
|
| 145 |
+
0175
|
| 146 |
+
0176
|
| 147 |
+
0178
|
| 148 |
+
0179
|
| 149 |
+
0180
|
| 150 |
+
0181
|
| 151 |
+
0182
|
| 152 |
+
0183
|
| 153 |
+
0184
|
| 154 |
+
0185
|
| 155 |
+
0186
|
| 156 |
+
0187
|
| 157 |
+
0188
|
| 158 |
+
0189
|
| 159 |
+
0190
|
| 160 |
+
0191
|
| 161 |
+
0192
|
| 162 |
+
0193
|
| 163 |
+
0194
|
| 164 |
+
0195
|
| 165 |
+
0197
|
| 166 |
+
0198
|
| 167 |
+
0199
|
| 168 |
+
0200
|
| 169 |
+
0201
|
| 170 |
+
0202
|
| 171 |
+
0203
|
| 172 |
+
0204
|
| 173 |
+
0205
|
| 174 |
+
0206
|
| 175 |
+
0208
|
| 176 |
+
0209
|
| 177 |
+
0210
|
| 178 |
+
0211
|
| 179 |
+
0212
|
| 180 |
+
0213
|
| 181 |
+
0214
|
| 182 |
+
0215
|
| 183 |
+
0216
|
| 184 |
+
0217
|
| 185 |
+
0218
|
| 186 |
+
0219
|
| 187 |
+
0220
|
| 188 |
+
0221
|
| 189 |
+
0222
|
| 190 |
+
0224
|
| 191 |
+
0225
|
| 192 |
+
0227
|
| 193 |
+
0228
|
| 194 |
+
0229
|
| 195 |
+
0230
|
| 196 |
+
0231
|
| 197 |
+
0232
|
| 198 |
+
0233
|
| 199 |
+
0234
|
| 200 |
+
0235
|
| 201 |
+
0236
|
| 202 |
+
0237
|
| 203 |
+
0238
|
| 204 |
+
0239
|
| 205 |
+
0240
|
| 206 |
+
0241
|
| 207 |
+
0242
|
| 208 |
+
0243
|
| 209 |
+
0244
|
| 210 |
+
0245
|
| 211 |
+
0246
|
| 212 |
+
0247
|
| 213 |
+
0248
|
| 214 |
+
0249
|
| 215 |
+
0250
|
| 216 |
+
0251
|
| 217 |
+
0252
|
| 218 |
+
0253
|
| 219 |
+
0254
|
| 220 |
+
0255
|
| 221 |
+
0256
|
| 222 |
+
0257
|
| 223 |
+
0258
|
| 224 |
+
0259
|
| 225 |
+
0260
|
| 226 |
+
0261
|
| 227 |
+
0262
|
| 228 |
+
0263
|
| 229 |
+
0264
|
| 230 |
+
0265
|
| 231 |
+
0266
|
| 232 |
+
0267
|
| 233 |
+
0268
|
| 234 |
+
0269
|
| 235 |
+
0270
|
| 236 |
+
0273
|
| 237 |
+
0274
|
| 238 |
+
0275
|
| 239 |
+
0277
|
| 240 |
+
0278
|
| 241 |
+
0279
|
| 242 |
+
0281
|
| 243 |
+
0282
|
| 244 |
+
0283
|
| 245 |
+
0284
|
| 246 |
+
0285
|
| 247 |
+
0286
|
| 248 |
+
0287
|
| 249 |
+
0288
|
| 250 |
+
0289
|
| 251 |
+
0290
|
| 252 |
+
0292
|
| 253 |
+
0293
|
| 254 |
+
0294
|
| 255 |
+
0295
|
| 256 |
+
0296
|
| 257 |
+
0297
|
| 258 |
+
0298
|
| 259 |
+
0299
|
| 260 |
+
0300
|
| 261 |
+
0302
|
| 262 |
+
0303
|
| 263 |
+
0304
|
| 264 |
+
0305
|
| 265 |
+
0306
|
| 266 |
+
0307
|
| 267 |
+
0308
|
| 268 |
+
0309
|
| 269 |
+
0310
|
| 270 |
+
0311
|
| 271 |
+
0312
|
| 272 |
+
0313
|
| 273 |
+
0314
|
| 274 |
+
0315
|
| 275 |
+
0316
|
| 276 |
+
0317
|
| 277 |
+
0318
|
| 278 |
+
0319
|
| 279 |
+
0320
|
| 280 |
+
0321
|
| 281 |
+
0322
|
| 282 |
+
0323
|
| 283 |
+
0325
|
| 284 |
+
0326
|
| 285 |
+
0327
|
| 286 |
+
0328
|
| 287 |
+
0329
|
| 288 |
+
0330
|
| 289 |
+
0331
|
| 290 |
+
0332
|
| 291 |
+
0334
|
| 292 |
+
0336
|
| 293 |
+
0337
|
| 294 |
+
0338
|
| 295 |
+
0339
|
| 296 |
+
0340
|
| 297 |
+
0341
|
| 298 |
+
0342
|
| 299 |
+
0344
|
| 300 |
+
0345
|
| 301 |
+
0346
|
| 302 |
+
0349
|
| 303 |
+
0351
|
| 304 |
+
0352
|
| 305 |
+
0355
|
| 306 |
+
0356
|
| 307 |
+
0357
|
| 308 |
+
0358
|
| 309 |
+
0359
|
| 310 |
+
0361
|
| 311 |
+
0362
|
| 312 |
+
0364
|
| 313 |
+
0365
|
| 314 |
+
0366
|
| 315 |
+
0367
|
| 316 |
+
0368
|
| 317 |
+
0371
|
| 318 |
+
0372
|
| 319 |
+
0373
|
| 320 |
+
0374
|
| 321 |
+
0375
|
| 322 |
+
0376
|
| 323 |
+
0377
|
| 324 |
+
0379
|
| 325 |
+
0381
|
| 326 |
+
0382
|
| 327 |
+
0383
|
| 328 |
+
0384
|
| 329 |
+
0385
|
| 330 |
+
0386
|
| 331 |
+
0387
|
| 332 |
+
0388
|
| 333 |
+
0389
|
| 334 |
+
0390
|
| 335 |
+
0391
|
| 336 |
+
0393
|
| 337 |
+
0394
|
| 338 |
+
0395
|
| 339 |
+
0396
|
| 340 |
+
0397
|
| 341 |
+
0398
|
| 342 |
+
0400
|
| 343 |
+
0401
|
| 344 |
+
0402
|
| 345 |
+
0403
|
| 346 |
+
0404
|
| 347 |
+
0405
|
| 348 |
+
0406
|
| 349 |
+
0407
|
| 350 |
+
0408
|
| 351 |
+
0409
|
| 352 |
+
0410
|
| 353 |
+
0411
|
| 354 |
+
0413
|
| 355 |
+
0414
|
| 356 |
+
0415
|
| 357 |
+
0416
|
| 358 |
+
0417
|
| 359 |
+
0418
|
| 360 |
+
0419
|
| 361 |
+
0420
|
| 362 |
+
0421
|
| 363 |
+
0422
|
| 364 |
+
0423
|
| 365 |
+
0424
|
| 366 |
+
0425
|
| 367 |
+
0426
|
| 368 |
+
0427
|
| 369 |
+
0429
|
| 370 |
+
0430
|
| 371 |
+
0431
|
| 372 |
+
0432
|
| 373 |
+
0434
|
| 374 |
+
0436
|
| 375 |
+
0437
|
| 376 |
+
0438
|
| 377 |
+
0439
|
| 378 |
+
0440
|
| 379 |
+
0441
|
| 380 |
+
0442
|
| 381 |
+
0443
|
| 382 |
+
0445
|
| 383 |
+
0446
|
| 384 |
+
0447
|
| 385 |
+
0448
|
| 386 |
+
0449
|
| 387 |
+
0451
|
| 388 |
+
0452
|
| 389 |
+
0453
|
| 390 |
+
0454
|
| 391 |
+
0455
|
| 392 |
+
0456
|
| 393 |
+
0457
|
| 394 |
+
0458
|
| 395 |
+
0459
|
| 396 |
+
0460
|
| 397 |
+
0461
|
| 398 |
+
0463
|
| 399 |
+
0464
|
| 400 |
+
0465
|
| 401 |
+
0466
|
| 402 |
+
0467
|
| 403 |
+
0468
|
| 404 |
+
0469
|
| 405 |
+
0471
|
| 406 |
+
0472
|
| 407 |
+
0473
|
| 408 |
+
0474
|
| 409 |
+
0475
|
| 410 |
+
0476
|
| 411 |
+
0477
|
| 412 |
+
0478
|
| 413 |
+
0479
|
| 414 |
+
0480
|
| 415 |
+
0481
|
| 416 |
+
0482
|
| 417 |
+
0483
|
| 418 |
+
0484
|
| 419 |
+
0486
|
| 420 |
+
0487
|
| 421 |
+
0488
|
| 422 |
+
0490
|
| 423 |
+
0491
|
| 424 |
+
0492
|
| 425 |
+
0493
|
| 426 |
+
0495
|
| 427 |
+
0496
|
| 428 |
+
0498
|
| 429 |
+
0500
|
| 430 |
+
0501
|
| 431 |
+
0502
|
| 432 |
+
0503
|
| 433 |
+
0504
|
| 434 |
+
0505
|
| 435 |
+
0506
|
| 436 |
+
0508
|
| 437 |
+
0509
|
| 438 |
+
0510
|
| 439 |
+
0511
|
| 440 |
+
0512
|
| 441 |
+
0513
|
| 442 |
+
0515
|
| 443 |
+
0516
|
| 444 |
+
0517
|
| 445 |
+
0518
|
| 446 |
+
0519
|
| 447 |
+
0520
|
| 448 |
+
0521
|
| 449 |
+
0522
|
| 450 |
+
0523
|
| 451 |
+
0524
|
| 452 |
+
0525
|
| 453 |
+
0526
|
| 454 |
+
0528
|
| 455 |
+
0529
|
| 456 |
+
0531
|
| 457 |
+
0532
|
| 458 |
+
0534
|
| 459 |
+
0535
|
| 460 |
+
0536
|
| 461 |
+
0537
|
| 462 |
+
0538
|
| 463 |
+
0539
|
| 464 |
+
0540
|
| 465 |
+
0542
|
| 466 |
+
0543
|
| 467 |
+
0545
|
| 468 |
+
0546
|
| 469 |
+
0548
|
| 470 |
+
0549
|
| 471 |
+
0550
|
| 472 |
+
0551
|
| 473 |
+
0554
|
| 474 |
+
0556
|
| 475 |
+
0557
|
| 476 |
+
0558
|
| 477 |
+
0559
|
| 478 |
+
0560
|
| 479 |
+
0561
|
| 480 |
+
0562
|
| 481 |
+
0563
|
| 482 |
+
0564
|
| 483 |
+
0565
|
| 484 |
+
0566
|
| 485 |
+
0567
|
| 486 |
+
0568
|
| 487 |
+
0569
|
| 488 |
+
0571
|
| 489 |
+
0572
|
| 490 |
+
0573
|
| 491 |
+
0574
|
| 492 |
+
0575
|
| 493 |
+
0576
|
| 494 |
+
0577
|
| 495 |
+
0578
|
| 496 |
+
0579
|
| 497 |
+
0580
|
| 498 |
+
0581
|
| 499 |
+
0582
|
| 500 |
+
0583
|
| 501 |
+
0584
|
| 502 |
+
0585
|
| 503 |
+
0586
|
| 504 |
+
0588
|
| 505 |
+
0589
|
| 506 |
+
0590
|
| 507 |
+
0591
|
| 508 |
+
0592
|
| 509 |
+
0594
|
| 510 |
+
0595
|
| 511 |
+
0596
|
| 512 |
+
0597
|
| 513 |
+
0598
|
| 514 |
+
0599
|
| 515 |
+
0600
|
| 516 |
+
0601
|
| 517 |
+
0602
|
| 518 |
+
0603
|
| 519 |
+
0604
|
| 520 |
+
0605
|
| 521 |
+
0606
|
| 522 |
+
0607
|
| 523 |
+
0608
|
| 524 |
+
0609
|
| 525 |
+
0610
|
| 526 |
+
0611
|
| 527 |
+
0613
|
| 528 |
+
0614
|
| 529 |
+
0615
|
| 530 |
+
0616
|
| 531 |
+
0617
|
| 532 |
+
0618
|
| 533 |
+
0619
|
| 534 |
+
0620
|
| 535 |
+
0621
|
| 536 |
+
0622
|
| 537 |
+
0623
|
| 538 |
+
0624
|
| 539 |
+
0625
|
| 540 |
+
0626
|
| 541 |
+
0627
|
| 542 |
+
0628
|
| 543 |
+
0629
|
| 544 |
+
0630
|
| 545 |
+
0631
|
| 546 |
+
0632
|
| 547 |
+
0633
|
| 548 |
+
0634
|
| 549 |
+
0635
|
| 550 |
+
0636
|
| 551 |
+
0637
|
| 552 |
+
0638
|
| 553 |
+
0639
|
| 554 |
+
0640
|
| 555 |
+
0642
|
| 556 |
+
0643
|
| 557 |
+
0644
|
| 558 |
+
0645
|
| 559 |
+
0646
|
| 560 |
+
0647
|
| 561 |
+
0648
|
| 562 |
+
0649
|
| 563 |
+
0650
|
| 564 |
+
0651
|
| 565 |
+
0652
|
| 566 |
+
0653
|
| 567 |
+
0654
|
| 568 |
+
0655
|
| 569 |
+
0656
|
| 570 |
+
0657
|
| 571 |
+
0658
|
| 572 |
+
0660
|
| 573 |
+
0661
|
| 574 |
+
0662
|
| 575 |
+
0663
|
| 576 |
+
0664
|
| 577 |
+
0665
|
| 578 |
+
0666
|
| 579 |
+
0667
|
| 580 |
+
0668
|
| 581 |
+
0669
|
| 582 |
+
0671
|
| 583 |
+
0672
|
| 584 |
+
0673
|
| 585 |
+
0674
|
| 586 |
+
0675
|
| 587 |
+
0676
|
| 588 |
+
0677
|
| 589 |
+
0678
|
| 590 |
+
0679
|
| 591 |
+
0680
|
| 592 |
+
0681
|
| 593 |
+
0682
|
| 594 |
+
0683
|
| 595 |
+
0684
|
| 596 |
+
0685
|
| 597 |
+
0686
|
| 598 |
+
0688
|
| 599 |
+
0689
|
| 600 |
+
0690
|
| 601 |
+
0691
|
| 602 |
+
0692
|
| 603 |
+
0693
|
| 604 |
+
0696
|
| 605 |
+
0697
|
| 606 |
+
0698
|
| 607 |
+
0699
|
| 608 |
+
0700
|
| 609 |
+
0701
|
| 610 |
+
0702
|
| 611 |
+
0704
|
| 612 |
+
0705
|
| 613 |
+
0706
|
| 614 |
+
0707
|
| 615 |
+
0708
|
| 616 |
+
0709
|
| 617 |
+
0710
|
| 618 |
+
0711
|
| 619 |
+
0712
|
| 620 |
+
0713
|
| 621 |
+
0714
|
| 622 |
+
0715
|
| 623 |
+
0716
|
| 624 |
+
0718
|
| 625 |
+
0719
|
| 626 |
+
0721
|
| 627 |
+
0722
|
| 628 |
+
0723
|
| 629 |
+
0725
|
| 630 |
+
0726
|
| 631 |
+
0727
|
| 632 |
+
0728
|
| 633 |
+
0729
|
| 634 |
+
0731
|
| 635 |
+
0732
|
| 636 |
+
0733
|
| 637 |
+
0734
|
| 638 |
+
0735
|
| 639 |
+
0736
|
| 640 |
+
0737
|
| 641 |
+
0740
|
| 642 |
+
0741
|
| 643 |
+
0742
|
| 644 |
+
0743
|
| 645 |
+
0744
|
| 646 |
+
0745
|
| 647 |
+
0746
|
| 648 |
+
0747
|
| 649 |
+
0748
|
| 650 |
+
0749
|
| 651 |
+
0750
|
| 652 |
+
0751
|
| 653 |
+
0752
|
| 654 |
+
0754
|
| 655 |
+
0755
|
| 656 |
+
0756
|
| 657 |
+
0759
|
| 658 |
+
0760
|
| 659 |
+
0761
|
| 660 |
+
0762
|
| 661 |
+
0763
|
| 662 |
+
0764
|
| 663 |
+
0765
|
| 664 |
+
0768
|
| 665 |
+
0769
|
| 666 |
+
0770
|
| 667 |
+
0771
|
| 668 |
+
0772
|
| 669 |
+
0773
|
| 670 |
+
0774
|
| 671 |
+
0775
|
| 672 |
+
0776
|
| 673 |
+
0777
|
| 674 |
+
0778
|
| 675 |
+
0780
|
| 676 |
+
0781
|
| 677 |
+
0782
|
| 678 |
+
0783
|
| 679 |
+
0784
|
| 680 |
+
0786
|
| 681 |
+
0787
|
| 682 |
+
0789
|
| 683 |
+
0790
|
| 684 |
+
0791
|
| 685 |
+
0792
|
| 686 |
+
0794
|
| 687 |
+
0795
|
| 688 |
+
0796
|
| 689 |
+
0797
|
| 690 |
+
0799
|
| 691 |
+
0800
|
| 692 |
+
0801
|
| 693 |
+
0802
|
| 694 |
+
0803
|
| 695 |
+
0804
|
| 696 |
+
0805
|
| 697 |
+
0806
|
| 698 |
+
0807
|
| 699 |
+
0809
|
| 700 |
+
0810
|
| 701 |
+
0811
|
| 702 |
+
0812
|
| 703 |
+
0816
|
| 704 |
+
0817
|
| 705 |
+
0818
|
| 706 |
+
0819
|
| 707 |
+
0820
|
| 708 |
+
0821
|
| 709 |
+
0823
|
| 710 |
+
0824
|
| 711 |
+
0826
|
| 712 |
+
0827
|
| 713 |
+
0828
|
| 714 |
+
0829
|
| 715 |
+
0831
|
| 716 |
+
0832
|
| 717 |
+
0833
|
| 718 |
+
0835
|
| 719 |
+
0836
|
| 720 |
+
0837
|
| 721 |
+
0838
|
| 722 |
+
0839
|
| 723 |
+
0840
|
| 724 |
+
0841
|
| 725 |
+
0842
|
| 726 |
+
0843
|
| 727 |
+
0844
|
| 728 |
+
0845
|
| 729 |
+
0846
|
| 730 |
+
0847
|
| 731 |
+
0848
|
| 732 |
+
0849
|
| 733 |
+
0850
|
| 734 |
+
0852
|
| 735 |
+
0854
|
| 736 |
+
0855
|
| 737 |
+
0856
|
| 738 |
+
0857
|
| 739 |
+
0858
|
| 740 |
+
0859
|
| 741 |
+
0860
|
| 742 |
+
0861
|
| 743 |
+
0862
|
| 744 |
+
0863
|
| 745 |
+
0864
|
| 746 |
+
0865
|
| 747 |
+
0866
|
| 748 |
+
0867
|
| 749 |
+
0869
|
| 750 |
+
0870
|
| 751 |
+
0871
|
| 752 |
+
0873
|
| 753 |
+
0874
|
| 754 |
+
0875
|
| 755 |
+
0876
|
| 756 |
+
0877
|
| 757 |
+
0878
|
| 758 |
+
0879
|
| 759 |
+
0880
|
| 760 |
+
0881
|
| 761 |
+
0883
|
| 762 |
+
0884
|
| 763 |
+
0885
|
| 764 |
+
0886
|
| 765 |
+
0888
|
| 766 |
+
0890
|
| 767 |
+
0891
|
| 768 |
+
0892
|
| 769 |
+
0893
|
| 770 |
+
0895
|
| 771 |
+
0896
|
| 772 |
+
0898
|
| 773 |
+
0899
|
| 774 |
+
0900
|
| 775 |
+
0902
|
| 776 |
+
0903
|
| 777 |
+
0904
|
| 778 |
+
0905
|
| 779 |
+
0907
|
| 780 |
+
0908
|
| 781 |
+
0910
|
| 782 |
+
0911
|
| 783 |
+
0913
|
| 784 |
+
0914
|
| 785 |
+
0917
|
| 786 |
+
0918
|
| 787 |
+
0919
|
| 788 |
+
0920
|
| 789 |
+
0921
|
| 790 |
+
0922
|
| 791 |
+
0923
|
| 792 |
+
0924
|
| 793 |
+
0927
|
| 794 |
+
0928
|
| 795 |
+
0929
|
| 796 |
+
0931
|
| 797 |
+
0932
|
| 798 |
+
0933
|
| 799 |
+
0934
|
| 800 |
+
0935
|
| 801 |
+
0936
|
| 802 |
+
0937
|
| 803 |
+
0938
|
| 804 |
+
0939
|
| 805 |
+
0940
|
| 806 |
+
0941
|
| 807 |
+
0942
|
| 808 |
+
0943
|
| 809 |
+
0944
|
| 810 |
+
0945
|
| 811 |
+
0946
|
| 812 |
+
0947
|
| 813 |
+
0948
|
| 814 |
+
0949
|
| 815 |
+
0950
|
| 816 |
+
0951
|
| 817 |
+
0954
|
| 818 |
+
0955
|
| 819 |
+
0957
|
| 820 |
+
0958
|
| 821 |
+
0959
|
| 822 |
+
0960
|
| 823 |
+
0962
|
| 824 |
+
0963
|
| 825 |
+
0964
|
| 826 |
+
0966
|
| 827 |
+
0967
|
| 828 |
+
0968
|
| 829 |
+
0969
|
| 830 |
+
0972
|
| 831 |
+
0973
|
| 832 |
+
0974
|
| 833 |
+
0975
|
| 834 |
+
0976
|
| 835 |
+
0979
|
| 836 |
+
0980
|
| 837 |
+
0981
|
| 838 |
+
0982
|
| 839 |
+
0983
|
| 840 |
+
0984
|
| 841 |
+
0985
|
| 842 |
+
0986
|
| 843 |
+
0987
|
| 844 |
+
0988
|
| 845 |
+
0990
|
| 846 |
+
0991
|
| 847 |
+
0992
|
| 848 |
+
0993
|
| 849 |
+
0994
|
| 850 |
+
0995
|
| 851 |
+
0996
|
| 852 |
+
0997
|
| 853 |
+
0998
|
| 854 |
+
0999
|
| 855 |
+
1000
|
| 856 |
+
1001
|
| 857 |
+
1002
|
| 858 |
+
1003
|
| 859 |
+
1004
|
| 860 |
+
1005
|
| 861 |
+
1006
|
| 862 |
+
1007
|
| 863 |
+
1008
|
| 864 |
+
1009
|
| 865 |
+
1010
|
| 866 |
+
1011
|
| 867 |
+
1012
|
| 868 |
+
1013
|
| 869 |
+
1014
|
| 870 |
+
1015
|
| 871 |
+
1016
|
| 872 |
+
1017
|
| 873 |
+
1018
|
| 874 |
+
1019
|
| 875 |
+
1022
|
| 876 |
+
1024
|
| 877 |
+
1025
|
| 878 |
+
1026
|
| 879 |
+
1027
|
| 880 |
+
1028
|
| 881 |
+
1029
|
| 882 |
+
1030
|
| 883 |
+
1031
|
| 884 |
+
1032
|
| 885 |
+
1033
|
| 886 |
+
1034
|
| 887 |
+
1035
|
| 888 |
+
1036
|
| 889 |
+
1037
|
| 890 |
+
1038
|
| 891 |
+
1039
|
| 892 |
+
1040
|
| 893 |
+
1041
|
| 894 |
+
1042
|
| 895 |
+
1043
|
| 896 |
+
1044
|
| 897 |
+
1046
|
| 898 |
+
1047
|
| 899 |
+
1048
|
| 900 |
+
1050
|
| 901 |
+
1053
|
| 902 |
+
1054
|
| 903 |
+
1056
|
| 904 |
+
1057
|
| 905 |
+
1058
|
| 906 |
+
1059
|
| 907 |
+
1061
|
| 908 |
+
1062
|
| 909 |
+
1063
|
| 910 |
+
1065
|
| 911 |
+
1066
|
| 912 |
+
1068
|
| 913 |
+
1070
|
| 914 |
+
1071
|
| 915 |
+
1072
|
| 916 |
+
1073
|
| 917 |
+
1074
|
| 918 |
+
1075
|
| 919 |
+
1076
|
| 920 |
+
1077
|
| 921 |
+
1078
|
| 922 |
+
1080
|
| 923 |
+
1081
|
| 924 |
+
1082
|
| 925 |
+
1083
|
| 926 |
+
1084
|
| 927 |
+
1085
|
| 928 |
+
1086
|
| 929 |
+
1087
|
| 930 |
+
1088
|
| 931 |
+
1089
|
| 932 |
+
1090
|
| 933 |
+
1092
|
| 934 |
+
1093
|
| 935 |
+
1094
|
| 936 |
+
1095
|
| 937 |
+
1096
|
| 938 |
+
1097
|
| 939 |
+
1098
|
| 940 |
+
1100
|
| 941 |
+
1101
|
| 942 |
+
1103
|
| 943 |
+
1104
|
| 944 |
+
1105
|
| 945 |
+
1107
|
| 946 |
+
1109
|
| 947 |
+
1112
|
| 948 |
+
1114
|
| 949 |
+
1115
|
| 950 |
+
1116
|
| 951 |
+
1117
|
| 952 |
+
1119
|
| 953 |
+
1120
|
| 954 |
+
1122
|
| 955 |
+
1125
|
| 956 |
+
1126
|
| 957 |
+
1127
|
| 958 |
+
1128
|
| 959 |
+
1129
|
| 960 |
+
1130
|
| 961 |
+
1131
|
| 962 |
+
1132
|
| 963 |
+
1133
|
| 964 |
+
1134
|
| 965 |
+
1135
|
| 966 |
+
1136
|
| 967 |
+
1138
|
| 968 |
+
1139
|
| 969 |
+
1142
|
| 970 |
+
1143
|
| 971 |
+
1144
|
| 972 |
+
1145
|
| 973 |
+
1146
|
| 974 |
+
1147
|
| 975 |
+
1148
|
| 976 |
+
1149
|
| 977 |
+
1150
|
| 978 |
+
1151
|
| 979 |
+
1152
|
| 980 |
+
1153
|
| 981 |
+
1154
|
| 982 |
+
1155
|
| 983 |
+
1156
|
| 984 |
+
1157
|
| 985 |
+
1158
|
| 986 |
+
1159
|
| 987 |
+
1160
|
| 988 |
+
1161
|
| 989 |
+
1163
|
| 990 |
+
1164
|
| 991 |
+
1165
|
| 992 |
+
1166
|
| 993 |
+
1167
|
| 994 |
+
1168
|
| 995 |
+
1171
|
| 996 |
+
1172
|
| 997 |
+
1173
|
| 998 |
+
1174
|
| 999 |
+
1175
|
| 1000 |
+
1177
|
| 1001 |
+
1179
|
| 1002 |
+
1181
|
| 1003 |
+
1182
|
| 1004 |
+
1183
|
| 1005 |
+
1184
|
| 1006 |
+
1186
|
| 1007 |
+
1187
|
| 1008 |
+
1188
|
| 1009 |
+
1189
|
| 1010 |
+
1190
|
| 1011 |
+
1191
|
| 1012 |
+
1192
|
| 1013 |
+
1193
|
| 1014 |
+
1194
|
| 1015 |
+
1195
|
| 1016 |
+
1196
|
| 1017 |
+
1198
|
| 1018 |
+
1200
|
| 1019 |
+
1201
|
| 1020 |
+
1203
|
| 1021 |
+
1205
|
| 1022 |
+
1207
|
| 1023 |
+
1208
|
| 1024 |
+
1209
|
| 1025 |
+
1210
|
| 1026 |
+
1211
|
| 1027 |
+
1212
|
| 1028 |
+
1213
|
| 1029 |
+
1214
|
| 1030 |
+
1215
|
| 1031 |
+
1216
|
| 1032 |
+
1217
|
| 1033 |
+
1218
|
| 1034 |
+
1219
|
| 1035 |
+
1220
|
| 1036 |
+
1221
|
| 1037 |
+
1222
|
| 1038 |
+
1223
|
| 1039 |
+
1224
|
| 1040 |
+
1225
|
| 1041 |
+
1226
|
| 1042 |
+
1227
|
| 1043 |
+
1228
|
| 1044 |
+
1229
|
| 1045 |
+
1230
|
| 1046 |
+
1231
|
| 1047 |
+
1232
|
| 1048 |
+
1233
|
| 1049 |
+
1234
|
| 1050 |
+
1236
|
| 1051 |
+
1237
|
| 1052 |
+
1238
|
| 1053 |
+
1239
|
| 1054 |
+
1240
|
| 1055 |
+
1241
|
| 1056 |
+
1243
|
| 1057 |
+
1244
|
| 1058 |
+
1245
|
| 1059 |
+
1246
|
| 1060 |
+
1247
|
| 1061 |
+
1248
|
| 1062 |
+
1249
|
| 1063 |
+
1250
|
| 1064 |
+
1252
|
| 1065 |
+
1253
|
| 1066 |
+
1254
|
| 1067 |
+
1255
|
| 1068 |
+
1256
|
| 1069 |
+
1257
|
| 1070 |
+
1258
|
| 1071 |
+
1259
|
| 1072 |
+
1260
|
| 1073 |
+
1261
|
| 1074 |
+
1262
|
| 1075 |
+
1264
|
| 1076 |
+
1265
|
| 1077 |
+
1266
|
| 1078 |
+
1268
|
| 1079 |
+
1269
|
| 1080 |
+
1270
|
| 1081 |
+
1271
|
| 1082 |
+
1272
|
| 1083 |
+
1273
|
| 1084 |
+
1274
|
| 1085 |
+
1275
|
| 1086 |
+
1276
|
| 1087 |
+
1277
|
| 1088 |
+
1278
|
| 1089 |
+
1279
|
| 1090 |
+
1280
|
| 1091 |
+
1281
|
| 1092 |
+
1282
|
| 1093 |
+
1283
|
| 1094 |
+
1285
|
| 1095 |
+
1286
|
| 1096 |
+
1287
|
| 1097 |
+
1288
|
| 1098 |
+
1289
|
| 1099 |
+
1290
|
| 1100 |
+
1291
|
| 1101 |
+
1292
|
| 1102 |
+
1293
|
| 1103 |
+
1294
|
| 1104 |
+
1295
|
| 1105 |
+
1296
|
| 1106 |
+
1298
|
| 1107 |
+
1299
|
| 1108 |
+
1300
|
| 1109 |
+
1301
|
| 1110 |
+
1302
|
| 1111 |
+
1303
|
| 1112 |
+
1305
|
| 1113 |
+
1306
|
| 1114 |
+
1307
|
| 1115 |
+
1308
|
| 1116 |
+
1309
|
| 1117 |
+
1310
|
| 1118 |
+
1311
|
| 1119 |
+
1312
|
| 1120 |
+
1313
|
| 1121 |
+
1314
|
| 1122 |
+
1315
|
| 1123 |
+
1316
|
| 1124 |
+
1317
|
| 1125 |
+
1318
|
| 1126 |
+
1319
|
| 1127 |
+
1320
|
| 1128 |
+
1321
|
| 1129 |
+
1322
|
| 1130 |
+
1323
|
| 1131 |
+
1324
|
| 1132 |
+
1325
|
| 1133 |
+
1326
|
| 1134 |
+
1327
|
| 1135 |
+
1328
|
| 1136 |
+
1329
|
| 1137 |
+
1330
|
| 1138 |
+
1332
|
| 1139 |
+
1333
|
| 1140 |
+
1334
|
| 1141 |
+
1335
|
| 1142 |
+
1336
|
| 1143 |
+
1337
|
| 1144 |
+
1338
|
| 1145 |
+
1339
|
| 1146 |
+
1340
|
| 1147 |
+
1341
|
| 1148 |
+
1343
|
| 1149 |
+
1344
|
| 1150 |
+
1345
|
| 1151 |
+
1347
|
| 1152 |
+
1348
|
| 1153 |
+
1349
|
| 1154 |
+
1350
|
| 1155 |
+
1351
|
| 1156 |
+
1353
|
| 1157 |
+
1354
|
| 1158 |
+
1355
|
| 1159 |
+
1356
|
| 1160 |
+
1358
|
| 1161 |
+
1359
|
| 1162 |
+
1360
|
| 1163 |
+
1361
|
| 1164 |
+
1362
|
| 1165 |
+
1363
|
| 1166 |
+
1364
|
| 1167 |
+
1365
|
| 1168 |
+
1366
|
| 1169 |
+
1367
|
| 1170 |
+
1368
|
| 1171 |
+
1370
|
| 1172 |
+
1371
|
| 1173 |
+
1372
|
| 1174 |
+
1373
|
| 1175 |
+
1374
|
| 1176 |
+
1377
|
| 1177 |
+
1378
|
| 1178 |
+
1379
|
| 1179 |
+
1380
|
| 1180 |
+
1381
|
| 1181 |
+
1384
|
| 1182 |
+
1386
|
| 1183 |
+
1388
|
| 1184 |
+
1390
|
| 1185 |
+
1391
|
| 1186 |
+
1392
|
| 1187 |
+
1393
|
| 1188 |
+
1394
|
| 1189 |
+
1395
|
| 1190 |
+
1396
|
| 1191 |
+
1398
|
| 1192 |
+
1400
|
| 1193 |
+
1401
|
| 1194 |
+
1402
|
| 1195 |
+
1403
|
| 1196 |
+
1404
|
| 1197 |
+
1405
|
| 1198 |
+
1406
|
| 1199 |
+
1407
|
| 1200 |
+
1408
|
| 1201 |
+
1409
|
| 1202 |
+
1410
|
| 1203 |
+
1411
|
| 1204 |
+
1413
|
| 1205 |
+
1414
|
| 1206 |
+
1416
|
| 1207 |
+
1417
|
| 1208 |
+
1418
|
| 1209 |
+
1419
|
| 1210 |
+
1420
|
| 1211 |
+
1422
|
| 1212 |
+
1424
|
| 1213 |
+
1425
|
| 1214 |
+
1427
|
| 1215 |
+
1428
|
| 1216 |
+
1429
|
| 1217 |
+
1430
|
| 1218 |
+
1431
|
| 1219 |
+
1432
|
| 1220 |
+
1433
|
| 1221 |
+
1434
|
| 1222 |
+
1437
|
| 1223 |
+
1438
|
| 1224 |
+
1439
|
| 1225 |
+
1440
|
| 1226 |
+
1441
|
| 1227 |
+
1442
|
| 1228 |
+
1443
|
| 1229 |
+
1444
|
| 1230 |
+
1445
|
| 1231 |
+
1447
|
| 1232 |
+
1448
|
| 1233 |
+
1449
|
| 1234 |
+
1451
|
| 1235 |
+
1452
|
| 1236 |
+
1453
|
| 1237 |
+
1454
|
| 1238 |
+
1455
|
| 1239 |
+
1456
|
| 1240 |
+
1457
|
| 1241 |
+
1458
|
| 1242 |
+
1459
|
| 1243 |
+
1460
|
| 1244 |
+
1461
|
| 1245 |
+
1462
|
| 1246 |
+
1463
|
| 1247 |
+
1464
|
| 1248 |
+
1465
|
| 1249 |
+
1466
|
| 1250 |
+
1467
|
| 1251 |
+
1468
|
| 1252 |
+
1469
|
| 1253 |
+
1470
|
| 1254 |
+
1471
|
| 1255 |
+
1472
|
| 1256 |
+
1473
|
| 1257 |
+
1474
|
| 1258 |
+
1475
|
| 1259 |
+
1476
|
| 1260 |
+
1477
|
| 1261 |
+
1478
|
| 1262 |
+
1479
|
| 1263 |
+
1480
|
| 1264 |
+
1481
|
| 1265 |
+
1482
|
| 1266 |
+
1483
|
| 1267 |
+
1484
|
| 1268 |
+
1485
|
| 1269 |
+
1487
|
| 1270 |
+
1488
|
| 1271 |
+
1489
|
| 1272 |
+
1491
|
| 1273 |
+
1493
|
| 1274 |
+
1494
|
| 1275 |
+
1496
|
| 1276 |
+
1498
|
| 1277 |
+
1499
|
| 1278 |
+
1500
|
| 1279 |
+
1501
|
| 1280 |
+
1503
|
| 1281 |
+
1504
|
| 1282 |
+
1505
|
| 1283 |
+
1506
|
| 1284 |
+
1507
|
| 1285 |
+
1508
|
| 1286 |
+
1510
|
| 1287 |
+
1512
|
| 1288 |
+
1513
|
| 1289 |
+
1514
|
| 1290 |
+
1515
|
| 1291 |
+
1516
|
| 1292 |
+
1517
|
| 1293 |
+
1518
|
| 1294 |
+
1519
|
| 1295 |
+
1520
|
| 1296 |
+
1521
|
| 1297 |
+
1524
|
| 1298 |
+
1526
|
| 1299 |
+
1527
|
| 1300 |
+
1528
|
| 1301 |
+
1529
|
| 1302 |
+
1530
|
| 1303 |
+
1531
|
| 1304 |
+
1533
|
| 1305 |
+
1534
|
| 1306 |
+
1535
|
| 1307 |
+
1537
|
| 1308 |
+
1539
|
| 1309 |
+
1542
|
| 1310 |
+
1543
|
| 1311 |
+
1544
|
| 1312 |
+
1545
|
| 1313 |
+
1546
|
| 1314 |
+
1547
|
| 1315 |
+
1548
|
| 1316 |
+
1550
|
| 1317 |
+
1551
|
| 1318 |
+
1552
|
| 1319 |
+
1553
|
| 1320 |
+
1554
|
| 1321 |
+
1555
|
| 1322 |
+
1556
|
| 1323 |
+
1557
|
| 1324 |
+
1558
|
| 1325 |
+
1559
|
| 1326 |
+
1560
|
| 1327 |
+
1561
|
| 1328 |
+
1562
|
| 1329 |
+
1563
|
| 1330 |
+
1564
|
| 1331 |
+
1565
|
| 1332 |
+
1566
|
| 1333 |
+
1567
|
| 1334 |
+
1569
|
| 1335 |
+
1570
|
| 1336 |
+
1572
|
| 1337 |
+
1573
|
| 1338 |
+
1574
|
| 1339 |
+
1575
|
| 1340 |
+
1577
|
| 1341 |
+
1578
|
| 1342 |
+
1579
|
| 1343 |
+
1580
|
| 1344 |
+
1582
|
| 1345 |
+
1583
|
| 1346 |
+
1585
|
| 1347 |
+
1586
|
| 1348 |
+
1588
|
| 1349 |
+
1589
|
| 1350 |
+
1590
|
| 1351 |
+
1591
|
| 1352 |
+
1593
|
| 1353 |
+
1594
|
| 1354 |
+
1595
|
| 1355 |
+
1596
|
| 1356 |
+
1597
|
| 1357 |
+
1598
|
| 1358 |
+
1599
|
| 1359 |
+
1600
|
| 1360 |
+
1601
|
| 1361 |
+
1602
|
| 1362 |
+
1603
|
| 1363 |
+
1606
|
| 1364 |
+
1607
|
| 1365 |
+
1608
|
| 1366 |
+
1610
|
| 1367 |
+
1611
|
| 1368 |
+
1612
|
| 1369 |
+
1613
|
| 1370 |
+
1614
|
| 1371 |
+
1616
|
| 1372 |
+
1617
|
| 1373 |
+
1618
|
| 1374 |
+
1619
|
| 1375 |
+
1620
|
| 1376 |
+
1621
|
| 1377 |
+
1622
|
| 1378 |
+
1623
|
| 1379 |
+
1625
|
| 1380 |
+
1626
|
| 1381 |
+
1627
|
| 1382 |
+
1628
|
| 1383 |
+
1629
|
| 1384 |
+
1630
|
| 1385 |
+
1631
|
| 1386 |
+
1632
|
| 1387 |
+
1633
|
| 1388 |
+
1634
|
| 1389 |
+
1635
|
| 1390 |
+
1636
|
| 1391 |
+
1638
|
| 1392 |
+
1640
|
| 1393 |
+
1641
|
| 1394 |
+
1642
|
| 1395 |
+
1643
|
| 1396 |
+
1644
|
| 1397 |
+
1645
|
| 1398 |
+
1646
|
| 1399 |
+
1647
|
| 1400 |
+
1649
|
| 1401 |
+
1650
|
| 1402 |
+
1651
|
| 1403 |
+
1652
|
| 1404 |
+
1653
|
| 1405 |
+
1655
|
| 1406 |
+
1656
|
| 1407 |
+
1657
|
| 1408 |
+
1658
|
| 1409 |
+
1659
|
| 1410 |
+
1660
|
| 1411 |
+
1661
|
| 1412 |
+
1662
|
| 1413 |
+
1663
|
| 1414 |
+
1664
|
| 1415 |
+
1665
|
| 1416 |
+
1666
|
| 1417 |
+
1668
|
| 1418 |
+
1669
|
| 1419 |
+
1671
|
| 1420 |
+
1672
|
| 1421 |
+
1673
|
| 1422 |
+
1674
|
| 1423 |
+
1675
|
| 1424 |
+
1677
|
| 1425 |
+
1678
|
| 1426 |
+
1679
|
| 1427 |
+
1681
|
| 1428 |
+
1683
|
| 1429 |
+
1684
|
| 1430 |
+
1685
|
| 1431 |
+
1686
|
| 1432 |
+
1687
|
| 1433 |
+
1688
|
| 1434 |
+
1690
|
| 1435 |
+
1691
|
| 1436 |
+
1692
|
| 1437 |
+
1693
|
| 1438 |
+
1694
|
| 1439 |
+
1695
|
| 1440 |
+
1696
|
| 1441 |
+
1697
|
| 1442 |
+
1698
|
| 1443 |
+
1699
|
| 1444 |
+
1700
|
| 1445 |
+
1703
|
| 1446 |
+
1704
|
| 1447 |
+
1705
|
| 1448 |
+
1706
|
| 1449 |
+
1708
|
| 1450 |
+
1709
|
| 1451 |
+
1712
|
| 1452 |
+
1714
|
| 1453 |
+
1715
|
| 1454 |
+
1716
|
| 1455 |
+
1718
|
| 1456 |
+
1720
|
| 1457 |
+
1722
|
| 1458 |
+
1723
|
| 1459 |
+
1725
|
| 1460 |
+
1726
|
| 1461 |
+
1727
|
| 1462 |
+
1728
|
| 1463 |
+
1729
|
| 1464 |
+
1730
|
| 1465 |
+
1731
|
| 1466 |
+
1732
|
| 1467 |
+
1733
|
| 1468 |
+
1734
|
| 1469 |
+
1735
|
| 1470 |
+
1736
|
| 1471 |
+
1737
|
| 1472 |
+
1738
|
| 1473 |
+
1739
|
| 1474 |
+
1740
|
| 1475 |
+
1741
|
| 1476 |
+
1742
|
| 1477 |
+
1743
|
| 1478 |
+
1744
|
| 1479 |
+
1745
|
| 1480 |
+
1746
|
| 1481 |
+
1747
|
| 1482 |
+
1749
|
| 1483 |
+
1750
|
| 1484 |
+
1751
|
| 1485 |
+
1752
|
| 1486 |
+
1754
|
| 1487 |
+
1756
|
| 1488 |
+
1757
|
| 1489 |
+
1758
|
| 1490 |
+
1759
|
| 1491 |
+
1760
|
| 1492 |
+
1761
|
| 1493 |
+
1763
|
| 1494 |
+
1764
|
| 1495 |
+
1765
|
| 1496 |
+
1766
|
| 1497 |
+
1767
|
| 1498 |
+
1768
|
| 1499 |
+
1770
|
| 1500 |
+
1771
|
| 1501 |
+
1772
|
| 1502 |
+
1775
|
| 1503 |
+
1776
|
| 1504 |
+
1777
|
| 1505 |
+
1778
|
| 1506 |
+
1781
|
| 1507 |
+
1783
|
| 1508 |
+
1785
|
| 1509 |
+
1786
|
| 1510 |
+
1787
|
| 1511 |
+
1788
|
| 1512 |
+
1789
|
| 1513 |
+
1790
|
| 1514 |
+
1791
|
| 1515 |
+
1792
|
| 1516 |
+
1794
|
| 1517 |
+
1795
|
| 1518 |
+
1796
|
| 1519 |
+
1797
|
| 1520 |
+
1798
|
| 1521 |
+
1799
|
| 1522 |
+
1800
|
| 1523 |
+
1802
|
| 1524 |
+
1803
|
| 1525 |
+
1804
|
| 1526 |
+
1806
|
| 1527 |
+
1807
|
| 1528 |
+
1809
|
| 1529 |
+
1810
|
| 1530 |
+
1811
|
| 1531 |
+
1812
|
| 1532 |
+
1813
|
| 1533 |
+
1814
|
| 1534 |
+
1816
|
| 1535 |
+
1817
|
| 1536 |
+
1818
|
| 1537 |
+
1820
|
| 1538 |
+
1821
|
| 1539 |
+
1822
|
| 1540 |
+
1823
|
| 1541 |
+
1824
|
| 1542 |
+
1825
|
| 1543 |
+
1826
|
| 1544 |
+
1827
|
| 1545 |
+
1828
|
| 1546 |
+
1829
|
| 1547 |
+
1830
|
| 1548 |
+
1831
|
| 1549 |
+
1832
|
| 1550 |
+
1833
|
| 1551 |
+
1834
|
| 1552 |
+
1835
|
| 1553 |
+
1836
|
| 1554 |
+
1837
|
| 1555 |
+
1838
|
| 1556 |
+
1839
|
| 1557 |
+
1840
|
| 1558 |
+
1842
|
| 1559 |
+
1843
|
| 1560 |
+
1844
|
| 1561 |
+
1845
|
| 1562 |
+
1846
|
| 1563 |
+
1847
|
| 1564 |
+
1848
|
| 1565 |
+
1849
|
| 1566 |
+
1852
|
| 1567 |
+
1855
|
| 1568 |
+
1856
|
| 1569 |
+
1857
|
| 1570 |
+
1858
|
| 1571 |
+
1859
|
| 1572 |
+
1860
|
| 1573 |
+
1861
|
| 1574 |
+
1862
|
| 1575 |
+
1863
|
| 1576 |
+
1866
|
| 1577 |
+
1870
|
| 1578 |
+
1871
|
| 1579 |
+
1872
|
| 1580 |
+
1873
|
| 1581 |
+
1874
|
| 1582 |
+
1875
|
| 1583 |
+
1876
|
| 1584 |
+
1877
|
| 1585 |
+
1879
|
| 1586 |
+
1880
|
| 1587 |
+
1882
|
| 1588 |
+
1883
|
| 1589 |
+
1884
|
| 1590 |
+
1885
|
| 1591 |
+
1886
|
| 1592 |
+
1887
|
| 1593 |
+
1890
|
| 1594 |
+
1891
|
| 1595 |
+
1892
|
| 1596 |
+
1893
|
| 1597 |
+
1895
|
| 1598 |
+
1896
|
| 1599 |
+
1897
|
| 1600 |
+
1898
|
| 1601 |
+
1899
|
| 1602 |
+
1900
|
| 1603 |
+
1901
|
| 1604 |
+
1902
|
| 1605 |
+
1903
|
| 1606 |
+
1904
|
| 1607 |
+
1905
|
| 1608 |
+
1907
|
| 1609 |
+
1908
|
| 1610 |
+
1909
|
| 1611 |
+
1911
|
| 1612 |
+
1912
|
| 1613 |
+
1913
|
| 1614 |
+
1914
|
| 1615 |
+
1915
|
| 1616 |
+
1916
|
| 1617 |
+
1917
|
| 1618 |
+
1918
|
| 1619 |
+
1919
|
| 1620 |
+
1921
|
| 1621 |
+
1922
|
| 1622 |
+
1923
|
| 1623 |
+
1924
|
| 1624 |
+
1925
|
| 1625 |
+
1926
|
| 1626 |
+
1927
|
| 1627 |
+
1928
|
| 1628 |
+
1929
|
| 1629 |
+
1930
|
| 1630 |
+
1931
|
| 1631 |
+
1932
|
| 1632 |
+
1933
|
| 1633 |
+
1934
|
| 1634 |
+
1935
|
| 1635 |
+
1936
|
| 1636 |
+
1937
|
| 1637 |
+
1938
|
| 1638 |
+
1941
|
| 1639 |
+
1942
|
| 1640 |
+
1943
|
| 1641 |
+
1944
|
| 1642 |
+
1946
|
| 1643 |
+
1947
|
| 1644 |
+
1948
|
| 1645 |
+
1950
|
| 1646 |
+
1951
|
| 1647 |
+
1952
|
| 1648 |
+
1953
|
| 1649 |
+
1954
|
| 1650 |
+
1955
|
| 1651 |
+
1956
|
| 1652 |
+
1957
|
| 1653 |
+
1958
|
| 1654 |
+
1959
|
| 1655 |
+
1960
|
| 1656 |
+
1961
|
| 1657 |
+
1962
|
| 1658 |
+
1963
|
| 1659 |
+
1964
|
| 1660 |
+
1965
|
| 1661 |
+
1966
|
| 1662 |
+
1967
|
| 1663 |
+
1968
|
| 1664 |
+
1969
|
| 1665 |
+
1970
|
| 1666 |
+
1971
|
| 1667 |
+
1972
|
| 1668 |
+
1973
|
| 1669 |
+
1974
|
| 1670 |
+
1975
|
| 1671 |
+
1976
|
| 1672 |
+
1977
|
| 1673 |
+
1978
|
| 1674 |
+
1979
|
| 1675 |
+
1980
|
| 1676 |
+
1981
|
| 1677 |
+
1982
|
| 1678 |
+
1984
|
| 1679 |
+
1985
|
| 1680 |
+
1986
|
| 1681 |
+
1988
|
| 1682 |
+
1989
|
| 1683 |
+
1991
|
| 1684 |
+
1992
|
| 1685 |
+
1993
|
| 1686 |
+
1994
|
| 1687 |
+
1995
|
| 1688 |
+
1996
|
| 1689 |
+
1998
|
| 1690 |
+
1999
|
| 1691 |
+
2001
|
| 1692 |
+
2002
|
| 1693 |
+
2003
|
| 1694 |
+
2004
|
| 1695 |
+
2005
|
| 1696 |
+
2006
|
| 1697 |
+
2007
|
| 1698 |
+
2009
|
| 1699 |
+
2010
|
| 1700 |
+
2011
|
| 1701 |
+
2012
|
| 1702 |
+
2013
|
| 1703 |
+
2014
|
| 1704 |
+
2015
|
| 1705 |
+
2016
|
| 1706 |
+
2017
|
| 1707 |
+
2018
|
| 1708 |
+
2019
|
| 1709 |
+
2020
|
| 1710 |
+
2021
|
| 1711 |
+
2022
|
| 1712 |
+
2023
|
| 1713 |
+
2024
|
| 1714 |
+
2025
|
| 1715 |
+
2026
|
| 1716 |
+
2027
|
| 1717 |
+
2028
|
| 1718 |
+
2029
|
| 1719 |
+
2030
|
| 1720 |
+
2032
|
| 1721 |
+
2033
|
| 1722 |
+
2034
|
| 1723 |
+
2035
|
| 1724 |
+
2036
|
| 1725 |
+
2037
|
| 1726 |
+
2038
|
| 1727 |
+
2039
|
| 1728 |
+
2040
|
| 1729 |
+
2041
|
| 1730 |
+
2043
|
| 1731 |
+
2044
|
| 1732 |
+
2045
|
| 1733 |
+
2046
|
| 1734 |
+
2047
|
| 1735 |
+
2048
|
| 1736 |
+
2049
|
| 1737 |
+
2051
|
| 1738 |
+
2052
|
| 1739 |
+
2054
|
| 1740 |
+
2055
|
| 1741 |
+
2057
|
| 1742 |
+
2058
|
| 1743 |
+
2059
|
| 1744 |
+
2060
|
| 1745 |
+
2062
|
| 1746 |
+
2063
|
| 1747 |
+
2064
|
| 1748 |
+
2065
|
| 1749 |
+
2066
|
| 1750 |
+
2067
|
| 1751 |
+
2069
|
| 1752 |
+
2070
|
| 1753 |
+
2071
|
| 1754 |
+
2072
|
| 1755 |
+
2073
|
| 1756 |
+
2074
|
| 1757 |
+
2075
|
| 1758 |
+
2077
|
| 1759 |
+
2078
|
| 1760 |
+
2079
|
| 1761 |
+
2080
|
| 1762 |
+
2081
|
| 1763 |
+
2082
|
| 1764 |
+
2083
|
| 1765 |
+
2084
|
| 1766 |
+
2085
|
| 1767 |
+
2086
|
| 1768 |
+
2087
|
| 1769 |
+
2088
|
| 1770 |
+
2089
|
| 1771 |
+
2090
|
| 1772 |
+
2093
|
| 1773 |
+
2094
|
| 1774 |
+
2095
|
| 1775 |
+
2096
|
| 1776 |
+
2097
|
| 1777 |
+
2098
|
| 1778 |
+
2100
|
| 1779 |
+
2101
|
| 1780 |
+
2102
|
| 1781 |
+
2103
|
| 1782 |
+
2104
|
| 1783 |
+
2105
|
| 1784 |
+
2106
|
| 1785 |
+
2107
|
| 1786 |
+
2108
|
| 1787 |
+
2109
|
| 1788 |
+
2110
|
| 1789 |
+
2111
|
| 1790 |
+
2112
|
| 1791 |
+
2114
|
| 1792 |
+
2115
|
| 1793 |
+
2116
|
| 1794 |
+
2117
|
| 1795 |
+
2118
|
| 1796 |
+
2119
|
| 1797 |
+
2120
|
| 1798 |
+
2121
|
| 1799 |
+
2122
|
| 1800 |
+
2123
|
| 1801 |
+
2124
|
| 1802 |
+
2126
|
| 1803 |
+
2127
|
| 1804 |
+
2129
|
| 1805 |
+
2130
|
| 1806 |
+
2131
|
| 1807 |
+
2132
|
| 1808 |
+
2133
|
| 1809 |
+
2134
|
| 1810 |
+
2135
|
| 1811 |
+
2136
|
| 1812 |
+
2137
|
| 1813 |
+
2138
|
| 1814 |
+
2139
|
| 1815 |
+
2140
|
| 1816 |
+
2141
|
| 1817 |
+
2142
|
| 1818 |
+
2143
|
| 1819 |
+
2144
|
| 1820 |
+
2145
|
| 1821 |
+
2147
|
| 1822 |
+
2149
|
| 1823 |
+
2150
|
| 1824 |
+
2151
|
| 1825 |
+
2152
|
| 1826 |
+
2153
|
| 1827 |
+
2154
|
| 1828 |
+
2155
|
| 1829 |
+
2156
|
| 1830 |
+
2157
|
| 1831 |
+
2158
|
| 1832 |
+
2160
|
| 1833 |
+
2161
|
| 1834 |
+
2162
|
| 1835 |
+
2163
|
| 1836 |
+
2164
|
| 1837 |
+
2165
|
| 1838 |
+
2166
|
| 1839 |
+
2167
|
| 1840 |
+
2168
|
| 1841 |
+
2170
|
| 1842 |
+
2171
|
| 1843 |
+
2172
|
| 1844 |
+
2173
|
| 1845 |
+
2175
|
| 1846 |
+
2176
|
| 1847 |
+
2177
|
| 1848 |
+
2178
|
| 1849 |
+
2179
|
| 1850 |
+
2180
|
| 1851 |
+
2181
|
| 1852 |
+
2182
|
| 1853 |
+
2184
|
| 1854 |
+
2185
|
| 1855 |
+
2186
|
| 1856 |
+
2187
|
| 1857 |
+
2189
|
| 1858 |
+
2190
|
| 1859 |
+
2191
|
| 1860 |
+
2192
|
| 1861 |
+
2193
|
| 1862 |
+
2195
|
| 1863 |
+
2196
|
| 1864 |
+
2197
|
| 1865 |
+
2198
|
| 1866 |
+
2199
|
| 1867 |
+
2200
|
| 1868 |
+
2201
|
| 1869 |
+
2202
|
| 1870 |
+
2203
|
| 1871 |
+
2204
|
| 1872 |
+
2205
|
| 1873 |
+
2206
|
| 1874 |
+
2207
|
| 1875 |
+
2208
|
| 1876 |
+
2210
|
| 1877 |
+
2211
|
| 1878 |
+
2212
|
| 1879 |
+
2213
|
| 1880 |
+
2214
|
| 1881 |
+
2215
|
| 1882 |
+
2216
|
| 1883 |
+
2217
|
| 1884 |
+
2218
|
| 1885 |
+
2219
|
| 1886 |
+
2220
|
| 1887 |
+
2221
|
| 1888 |
+
2222
|
| 1889 |
+
2223
|
| 1890 |
+
2224
|
| 1891 |
+
2225
|
| 1892 |
+
2226
|
| 1893 |
+
2227
|
| 1894 |
+
2228
|
| 1895 |
+
2229
|
| 1896 |
+
2231
|
| 1897 |
+
2232
|
| 1898 |
+
2233
|
| 1899 |
+
2234
|
| 1900 |
+
2236
|
| 1901 |
+
2238
|
| 1902 |
+
2239
|
| 1903 |
+
2240
|
| 1904 |
+
2241
|
| 1905 |
+
2242
|
| 1906 |
+
2244
|
| 1907 |
+
2245
|
| 1908 |
+
2246
|
| 1909 |
+
2247
|
| 1910 |
+
2249
|
| 1911 |
+
2250
|
| 1912 |
+
2251
|
| 1913 |
+
2252
|
| 1914 |
+
2253
|
| 1915 |
+
2254
|
| 1916 |
+
2255
|
| 1917 |
+
2256
|
| 1918 |
+
2257
|
| 1919 |
+
2258
|
| 1920 |
+
2259
|
| 1921 |
+
2260
|
| 1922 |
+
2261
|
| 1923 |
+
2262
|
| 1924 |
+
2263
|
| 1925 |
+
2264
|
| 1926 |
+
2265
|
| 1927 |
+
2266
|
| 1928 |
+
2267
|
| 1929 |
+
2268
|
| 1930 |
+
2270
|
| 1931 |
+
2271
|
| 1932 |
+
2272
|
| 1933 |
+
2273
|
| 1934 |
+
2274
|
| 1935 |
+
2275
|
| 1936 |
+
2276
|
| 1937 |
+
2278
|
| 1938 |
+
2279
|
| 1939 |
+
2280
|
| 1940 |
+
2281
|
| 1941 |
+
2282
|
| 1942 |
+
2283
|
| 1943 |
+
2284
|
| 1944 |
+
2285
|
| 1945 |
+
2287
|
| 1946 |
+
2288
|
| 1947 |
+
2289
|
| 1948 |
+
2290
|
| 1949 |
+
2291
|
| 1950 |
+
2292
|
| 1951 |
+
2293
|
| 1952 |
+
2294
|
| 1953 |
+
2295
|
| 1954 |
+
2296
|
| 1955 |
+
2297
|
| 1956 |
+
2299
|
| 1957 |
+
2301
|
| 1958 |
+
2302
|
| 1959 |
+
2303
|
| 1960 |
+
2304
|
| 1961 |
+
2305
|
| 1962 |
+
2306
|
| 1963 |
+
2307
|
| 1964 |
+
2308
|
| 1965 |
+
2309
|
| 1966 |
+
2310
|
| 1967 |
+
2312
|
| 1968 |
+
2313
|
| 1969 |
+
2315
|
| 1970 |
+
2316
|
| 1971 |
+
2317
|
| 1972 |
+
2318
|
| 1973 |
+
2319
|
| 1974 |
+
2320
|
| 1975 |
+
2321
|
| 1976 |
+
2322
|
| 1977 |
+
2323
|
| 1978 |
+
2324
|
| 1979 |
+
2325
|
| 1980 |
+
2326
|
| 1981 |
+
2327
|
| 1982 |
+
2329
|
| 1983 |
+
2330
|
| 1984 |
+
2331
|
| 1985 |
+
2332
|
| 1986 |
+
2333
|
| 1987 |
+
2335
|
| 1988 |
+
2336
|
| 1989 |
+
2337
|
| 1990 |
+
2338
|
| 1991 |
+
2339
|
| 1992 |
+
2341
|
| 1993 |
+
2342
|
| 1994 |
+
2343
|
| 1995 |
+
2346
|
| 1996 |
+
2347
|
| 1997 |
+
2349
|
| 1998 |
+
2350
|
| 1999 |
+
2352
|
| 2000 |
+
2353
|
| 2001 |
+
2354
|
| 2002 |
+
2355
|
| 2003 |
+
2356
|
| 2004 |
+
2357
|
| 2005 |
+
2359
|
| 2006 |
+
2360
|
| 2007 |
+
2361
|
| 2008 |
+
2363
|
| 2009 |
+
2364
|
| 2010 |
+
2365
|
| 2011 |
+
2366
|
| 2012 |
+
2367
|
| 2013 |
+
2368
|
| 2014 |
+
2369
|
| 2015 |
+
2370
|
| 2016 |
+
2371
|
| 2017 |
+
2373
|
| 2018 |
+
2374
|
| 2019 |
+
2375
|
| 2020 |
+
2376
|
| 2021 |
+
2378
|
| 2022 |
+
2379
|
| 2023 |
+
2380
|
| 2024 |
+
2381
|
| 2025 |
+
2382
|
| 2026 |
+
2383
|
| 2027 |
+
2384
|
| 2028 |
+
2385
|
| 2029 |
+
2386
|
| 2030 |
+
2387
|
| 2031 |
+
2388
|
| 2032 |
+
2389
|
| 2033 |
+
2390
|
| 2034 |
+
2391
|
| 2035 |
+
2392
|
| 2036 |
+
2393
|
| 2037 |
+
2394
|
| 2038 |
+
2396
|
| 2039 |
+
2398
|
| 2040 |
+
2399
|
| 2041 |
+
2400
|
| 2042 |
+
2401
|
| 2043 |
+
2402
|
| 2044 |
+
2403
|
| 2045 |
+
2404
|
| 2046 |
+
2405
|
| 2047 |
+
2407
|
| 2048 |
+
2408
|
| 2049 |
+
2409
|
| 2050 |
+
2410
|
| 2051 |
+
2411
|
| 2052 |
+
2412
|
| 2053 |
+
2413
|
| 2054 |
+
2414
|
| 2055 |
+
2417
|
| 2056 |
+
2418
|
| 2057 |
+
2420
|
| 2058 |
+
2421
|
| 2059 |
+
2422
|
| 2060 |
+
2423
|
| 2061 |
+
2424
|
| 2062 |
+
2425
|
| 2063 |
+
2426
|
| 2064 |
+
2427
|
| 2065 |
+
2429
|
| 2066 |
+
2431
|
| 2067 |
+
2432
|
| 2068 |
+
2434
|
| 2069 |
+
2436
|
| 2070 |
+
2439
|
| 2071 |
+
2440
|
| 2072 |
+
2441
|
| 2073 |
+
2442
|
| 2074 |
+
2443
|
| 2075 |
+
2444
|
| 2076 |
+
2445
|
| 2077 |
+
2446
|
| 2078 |
+
2447
|
| 2079 |
+
2448
|
| 2080 |
+
2449
|
| 2081 |
+
2451
|
| 2082 |
+
2452
|
| 2083 |
+
2454
|
| 2084 |
+
2455
|
| 2085 |
+
2456
|
| 2086 |
+
2457
|
| 2087 |
+
2458
|
| 2088 |
+
2460
|
| 2089 |
+
2461
|
| 2090 |
+
2462
|
| 2091 |
+
2463
|
| 2092 |
+
2464
|
| 2093 |
+
2465
|
| 2094 |
+
2466
|
| 2095 |
+
2467
|
| 2096 |
+
2468
|
| 2097 |
+
2469
|
| 2098 |
+
2470
|
| 2099 |
+
2471
|
| 2100 |
+
2472
|
| 2101 |
+
2473
|
| 2102 |
+
2474
|
| 2103 |
+
2475
|
| 2104 |
+
2476
|
| 2105 |
+
2477
|
| 2106 |
+
2478
|
| 2107 |
+
2479
|
| 2108 |
+
2480
|
| 2109 |
+
2481
|
| 2110 |
+
2482
|
| 2111 |
+
2483
|
| 2112 |
+
2484
|
| 2113 |
+
2486
|
| 2114 |
+
2487
|
| 2115 |
+
2488
|
| 2116 |
+
2489
|
| 2117 |
+
2490
|
| 2118 |
+
2491
|
| 2119 |
+
2494
|
| 2120 |
+
2496
|
| 2121 |
+
2497
|
| 2122 |
+
2498
|
| 2123 |
+
2499
|
| 2124 |
+
2500
|
| 2125 |
+
2501
|
| 2126 |
+
2502
|
| 2127 |
+
2504
|
| 2128 |
+
2505
|
| 2129 |
+
2506
|
| 2130 |
+
2507
|
| 2131 |
+
2508
|
| 2132 |
+
2510
|
| 2133 |
+
2511
|
| 2134 |
+
2512
|
| 2135 |
+
2513
|
| 2136 |
+
2514
|
| 2137 |
+
2515
|
| 2138 |
+
2516
|
| 2139 |
+
2518
|
| 2140 |
+
2519
|
| 2141 |
+
2520
|
| 2142 |
+
2521
|
| 2143 |
+
2522
|
| 2144 |
+
2523
|
| 2145 |
+
2524
|
| 2146 |
+
2525
|
| 2147 |
+
2527
|
| 2148 |
+
2528
|
| 2149 |
+
2529
|
| 2150 |
+
2530
|
| 2151 |
+
2531
|
| 2152 |
+
2532
|
| 2153 |
+
2533
|
| 2154 |
+
2534
|
| 2155 |
+
2536
|
| 2156 |
+
2537
|
| 2157 |
+
2538
|
| 2158 |
+
2539
|
| 2159 |
+
2540
|
| 2160 |
+
2541
|
| 2161 |
+
2543
|
| 2162 |
+
2544
|
| 2163 |
+
2545
|
| 2164 |
+
2546
|
| 2165 |
+
2547
|
| 2166 |
+
2548
|
| 2167 |
+
2549
|
| 2168 |
+
2550
|
| 2169 |
+
2551
|
| 2170 |
+
2552
|
| 2171 |
+
2553
|
| 2172 |
+
2554
|
| 2173 |
+
2555
|
| 2174 |
+
2556
|
| 2175 |
+
2557
|
| 2176 |
+
2558
|
| 2177 |
+
2559
|
| 2178 |
+
2560
|
| 2179 |
+
2561
|
| 2180 |
+
2562
|
| 2181 |
+
2563
|
| 2182 |
+
2564
|
| 2183 |
+
2565
|
| 2184 |
+
2566
|
| 2185 |
+
2567
|
| 2186 |
+
2568
|
| 2187 |
+
2570
|
| 2188 |
+
2571
|
| 2189 |
+
2572
|
| 2190 |
+
2573
|
| 2191 |
+
2574
|
| 2192 |
+
2575
|
| 2193 |
+
2576
|
| 2194 |
+
2577
|
| 2195 |
+
2578
|
| 2196 |
+
2579
|
| 2197 |
+
2580
|
| 2198 |
+
2581
|
| 2199 |
+
2582
|
| 2200 |
+
2583
|
| 2201 |
+
2584
|
| 2202 |
+
2586
|
| 2203 |
+
2587
|
| 2204 |
+
2588
|
| 2205 |
+
2589
|
| 2206 |
+
2590
|
| 2207 |
+
2591
|
| 2208 |
+
2592
|
| 2209 |
+
2594
|
| 2210 |
+
2595
|
| 2211 |
+
2596
|
| 2212 |
+
2598
|
| 2213 |
+
2600
|
| 2214 |
+
2601
|
| 2215 |
+
2602
|
| 2216 |
+
2604
|
| 2217 |
+
2605
|
| 2218 |
+
2606
|
| 2219 |
+
2607
|
| 2220 |
+
2608
|
| 2221 |
+
2612
|
| 2222 |
+
2615
|
| 2223 |
+
2616
|
| 2224 |
+
2617
|
| 2225 |
+
2618
|
| 2226 |
+
2620
|
| 2227 |
+
2621
|
| 2228 |
+
2622
|
| 2229 |
+
2623
|
| 2230 |
+
2624
|
| 2231 |
+
2625
|
| 2232 |
+
2626
|
| 2233 |
+
2628
|
| 2234 |
+
2629
|
| 2235 |
+
2630
|
| 2236 |
+
2631
|
| 2237 |
+
2632
|
| 2238 |
+
2636
|
| 2239 |
+
2637
|
| 2240 |
+
2638
|
| 2241 |
+
2639
|
| 2242 |
+
2640
|
| 2243 |
+
2641
|
| 2244 |
+
2642
|
| 2245 |
+
2643
|
| 2246 |
+
2644
|
| 2247 |
+
2645
|
| 2248 |
+
2646
|
| 2249 |
+
2647
|
| 2250 |
+
2648
|
| 2251 |
+
2649
|
| 2252 |
+
2650
|
| 2253 |
+
2651
|
| 2254 |
+
2652
|
| 2255 |
+
2653
|
| 2256 |
+
2655
|
| 2257 |
+
2656
|
| 2258 |
+
2657
|
| 2259 |
+
2658
|
| 2260 |
+
2659
|
| 2261 |
+
2661
|
| 2262 |
+
2662
|
| 2263 |
+
2663
|
| 2264 |
+
2664
|
| 2265 |
+
2665
|
| 2266 |
+
2666
|
| 2267 |
+
2667
|
| 2268 |
+
2668
|
| 2269 |
+
2669
|
| 2270 |
+
2670
|
| 2271 |
+
2672
|
| 2272 |
+
2673
|
| 2273 |
+
2674
|
| 2274 |
+
2675
|
| 2275 |
+
2676
|
| 2276 |
+
2677
|
| 2277 |
+
2680
|
| 2278 |
+
2682
|
| 2279 |
+
2683
|
| 2280 |
+
2684
|
| 2281 |
+
2686
|
| 2282 |
+
2687
|
| 2283 |
+
2689
|
| 2284 |
+
2690
|
| 2285 |
+
2691
|
| 2286 |
+
2692
|
| 2287 |
+
2693
|
| 2288 |
+
2694
|
| 2289 |
+
2695
|
| 2290 |
+
2696
|
| 2291 |
+
2697
|
| 2292 |
+
2698
|
| 2293 |
+
2699
|
| 2294 |
+
2700
|
| 2295 |
+
2701
|
| 2296 |
+
2702
|
| 2297 |
+
2703
|
| 2298 |
+
2704
|
| 2299 |
+
2705
|
| 2300 |
+
2706
|
| 2301 |
+
2707
|
| 2302 |
+
2709
|
| 2303 |
+
2710
|
| 2304 |
+
2713
|
| 2305 |
+
2714
|
| 2306 |
+
2715
|
| 2307 |
+
2716
|
| 2308 |
+
2717
|
| 2309 |
+
2718
|
| 2310 |
+
2719
|
| 2311 |
+
2720
|
| 2312 |
+
2721
|
| 2313 |
+
2722
|
| 2314 |
+
2723
|
| 2315 |
+
2726
|
| 2316 |
+
2727
|
| 2317 |
+
2728
|
| 2318 |
+
2729
|
| 2319 |
+
2730
|
| 2320 |
+
2732
|
| 2321 |
+
2733
|
| 2322 |
+
2734
|
| 2323 |
+
2735
|
| 2324 |
+
2736
|
| 2325 |
+
2737
|
| 2326 |
+
2738
|
| 2327 |
+
2740
|
| 2328 |
+
2741
|
| 2329 |
+
2743
|
| 2330 |
+
2744
|
| 2331 |
+
2745
|
| 2332 |
+
2746
|
| 2333 |
+
2747
|
| 2334 |
+
2749
|
| 2335 |
+
2750
|
| 2336 |
+
2751
|
| 2337 |
+
2752
|
| 2338 |
+
2753
|
| 2339 |
+
2755
|
| 2340 |
+
2756
|
| 2341 |
+
2758
|
| 2342 |
+
2759
|
| 2343 |
+
2760
|
| 2344 |
+
2761
|
| 2345 |
+
2762
|
| 2346 |
+
2764
|
| 2347 |
+
2765
|
| 2348 |
+
2766
|
| 2349 |
+
2767
|
| 2350 |
+
2768
|
| 2351 |
+
2769
|
| 2352 |
+
2770
|
| 2353 |
+
2771
|
| 2354 |
+
2772
|
| 2355 |
+
2775
|
| 2356 |
+
2776
|
| 2357 |
+
2777
|
| 2358 |
+
2780
|
| 2359 |
+
2781
|
| 2360 |
+
2782
|
| 2361 |
+
2783
|
| 2362 |
+
2784
|
| 2363 |
+
2786
|
| 2364 |
+
2788
|
| 2365 |
+
2789
|
| 2366 |
+
2790
|
| 2367 |
+
2791
|
| 2368 |
+
2792
|
| 2369 |
+
2793
|
| 2370 |
+
2794
|
| 2371 |
+
2795
|
| 2372 |
+
2796
|
| 2373 |
+
2797
|
| 2374 |
+
2798
|
| 2375 |
+
2799
|
| 2376 |
+
2800
|
| 2377 |
+
2802
|
| 2378 |
+
2804
|
| 2379 |
+
2805
|
| 2380 |
+
2806
|
| 2381 |
+
2807
|
| 2382 |
+
2808
|
| 2383 |
+
2809
|
| 2384 |
+
2810
|
| 2385 |
+
2811
|
| 2386 |
+
2812
|
| 2387 |
+
2813
|
| 2388 |
+
2814
|
| 2389 |
+
2815
|
| 2390 |
+
2816
|
| 2391 |
+
2817
|
| 2392 |
+
2818
|
| 2393 |
+
2819
|
| 2394 |
+
2822
|
| 2395 |
+
2823
|
| 2396 |
+
2824
|
| 2397 |
+
2825
|
| 2398 |
+
2826
|
| 2399 |
+
2827
|
| 2400 |
+
2828
|
| 2401 |
+
2829
|
| 2402 |
+
2830
|
| 2403 |
+
2831
|
| 2404 |
+
2832
|
| 2405 |
+
2833
|
| 2406 |
+
2834
|
| 2407 |
+
2835
|
| 2408 |
+
2836
|
| 2409 |
+
2837
|
| 2410 |
+
2838
|
| 2411 |
+
2839
|
| 2412 |
+
2840
|
| 2413 |
+
2842
|
| 2414 |
+
2844
|
| 2415 |
+
2845
|
| 2416 |
+
2846
|
| 2417 |
+
2847
|
| 2418 |
+
2848
|
| 2419 |
+
2850
|
| 2420 |
+
2851
|
| 2421 |
+
2852
|
| 2422 |
+
2853
|
| 2423 |
+
2854
|
| 2424 |
+
2855
|
| 2425 |
+
2856
|
| 2426 |
+
2857
|
| 2427 |
+
2858
|
| 2428 |
+
2859
|
| 2429 |
+
2860
|
| 2430 |
+
2861
|
| 2431 |
+
2862
|
| 2432 |
+
2863
|
| 2433 |
+
2864
|
| 2434 |
+
2865
|
| 2435 |
+
2866
|
| 2436 |
+
2867
|
| 2437 |
+
2868
|
| 2438 |
+
2869
|
| 2439 |
+
2870
|
| 2440 |
+
2871
|
| 2441 |
+
2873
|
| 2442 |
+
2874
|
| 2443 |
+
2875
|
| 2444 |
+
2876
|
| 2445 |
+
2877
|
| 2446 |
+
2878
|
| 2447 |
+
2879
|
| 2448 |
+
2881
|
| 2449 |
+
2882
|
| 2450 |
+
2883
|
| 2451 |
+
2884
|
| 2452 |
+
2885
|
| 2453 |
+
2886
|
| 2454 |
+
2887
|
| 2455 |
+
2888
|
| 2456 |
+
2889
|
| 2457 |
+
2890
|
| 2458 |
+
2891
|
| 2459 |
+
2892
|
| 2460 |
+
2893
|
| 2461 |
+
2896
|
| 2462 |
+
2897
|
| 2463 |
+
2898
|
| 2464 |
+
2899
|
| 2465 |
+
2900
|
| 2466 |
+
2901
|
| 2467 |
+
2902
|
| 2468 |
+
2903
|
| 2469 |
+
2904
|
| 2470 |
+
2905
|
| 2471 |
+
2906
|
| 2472 |
+
2907
|
| 2473 |
+
2908
|
| 2474 |
+
2909
|
| 2475 |
+
2910
|
| 2476 |
+
2911
|
| 2477 |
+
2912
|
| 2478 |
+
2913
|
| 2479 |
+
2914
|
| 2480 |
+
2915
|
| 2481 |
+
2916
|
| 2482 |
+
2917
|
| 2483 |
+
2918
|
| 2484 |
+
2919
|
| 2485 |
+
2920
|
| 2486 |
+
2921
|
| 2487 |
+
2923
|
| 2488 |
+
2925
|
| 2489 |
+
2927
|
| 2490 |
+
2928
|
| 2491 |
+
2929
|
| 2492 |
+
2930
|
| 2493 |
+
2931
|
| 2494 |
+
2932
|
| 2495 |
+
2933
|
| 2496 |
+
2934
|
| 2497 |
+
2935
|
| 2498 |
+
2936
|
| 2499 |
+
2937
|
| 2500 |
+
2938
|
| 2501 |
+
2939
|
| 2502 |
+
2940
|
| 2503 |
+
2941
|
| 2504 |
+
2942
|
| 2505 |
+
2943
|
| 2506 |
+
2944
|
| 2507 |
+
2945
|
| 2508 |
+
2946
|
| 2509 |
+
2947
|
| 2510 |
+
2948
|
| 2511 |
+
2950
|
| 2512 |
+
2951
|
| 2513 |
+
2952
|
| 2514 |
+
2953
|
| 2515 |
+
2954
|
| 2516 |
+
2955
|
| 2517 |
+
2956
|
| 2518 |
+
2957
|
| 2519 |
+
2958
|
| 2520 |
+
2959
|
| 2521 |
+
2960
|
| 2522 |
+
2962
|
| 2523 |
+
2964
|
| 2524 |
+
2965
|
| 2525 |
+
2966
|
| 2526 |
+
2967
|
| 2527 |
+
2968
|
| 2528 |
+
2969
|
| 2529 |
+
2970
|
| 2530 |
+
2971
|
| 2531 |
+
2972
|
| 2532 |
+
2973
|
| 2533 |
+
2974
|
| 2534 |
+
2977
|
| 2535 |
+
2978
|
| 2536 |
+
2979
|
| 2537 |
+
2980
|
| 2538 |
+
2981
|
| 2539 |
+
2982
|
| 2540 |
+
2984
|
| 2541 |
+
2987
|
| 2542 |
+
2988
|
| 2543 |
+
2990
|
| 2544 |
+
2991
|
| 2545 |
+
2992
|
| 2546 |
+
2993
|
| 2547 |
+
2994
|
| 2548 |
+
2995
|
| 2549 |
+
2998
|
| 2550 |
+
2999
|
coral_seg/splits/train_full.txt
ADDED
|
@@ -0,0 +1,3000 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0000
|
| 2 |
+
0001
|
| 3 |
+
0002
|
| 4 |
+
0003
|
| 5 |
+
0004
|
| 6 |
+
0005
|
| 7 |
+
0006
|
| 8 |
+
0007
|
| 9 |
+
0008
|
| 10 |
+
0009
|
| 11 |
+
0010
|
| 12 |
+
0011
|
| 13 |
+
0012
|
| 14 |
+
0013
|
| 15 |
+
0014
|
| 16 |
+
0015
|
| 17 |
+
0016
|
| 18 |
+
0017
|
| 19 |
+
0018
|
| 20 |
+
0019
|
| 21 |
+
0020
|
| 22 |
+
0021
|
| 23 |
+
0022
|
| 24 |
+
0023
|
| 25 |
+
0024
|
| 26 |
+
0025
|
| 27 |
+
0026
|
| 28 |
+
0027
|
| 29 |
+
0028
|
| 30 |
+
0029
|
| 31 |
+
0030
|
| 32 |
+
0031
|
| 33 |
+
0032
|
| 34 |
+
0033
|
| 35 |
+
0034
|
| 36 |
+
0035
|
| 37 |
+
0036
|
| 38 |
+
0037
|
| 39 |
+
0038
|
| 40 |
+
0039
|
| 41 |
+
0040
|
| 42 |
+
0041
|
| 43 |
+
0042
|
| 44 |
+
0043
|
| 45 |
+
0044
|
| 46 |
+
0045
|
| 47 |
+
0046
|
| 48 |
+
0047
|
| 49 |
+
0048
|
| 50 |
+
0049
|
| 51 |
+
0050
|
| 52 |
+
0051
|
| 53 |
+
0052
|
| 54 |
+
0053
|
| 55 |
+
0054
|
| 56 |
+
0055
|
| 57 |
+
0056
|
| 58 |
+
0057
|
| 59 |
+
0058
|
| 60 |
+
0059
|
| 61 |
+
0060
|
| 62 |
+
0061
|
| 63 |
+
0062
|
| 64 |
+
0063
|
| 65 |
+
0064
|
| 66 |
+
0065
|
| 67 |
+
0066
|
| 68 |
+
0067
|
| 69 |
+
0068
|
| 70 |
+
0069
|
| 71 |
+
0070
|
| 72 |
+
0071
|
| 73 |
+
0072
|
| 74 |
+
0073
|
| 75 |
+
0074
|
| 76 |
+
0075
|
| 77 |
+
0076
|
| 78 |
+
0077
|
| 79 |
+
0078
|
| 80 |
+
0079
|
| 81 |
+
0080
|
| 82 |
+
0081
|
| 83 |
+
0082
|
| 84 |
+
0083
|
| 85 |
+
0084
|
| 86 |
+
0085
|
| 87 |
+
0086
|
| 88 |
+
0087
|
| 89 |
+
0088
|
| 90 |
+
0089
|
| 91 |
+
0090
|
| 92 |
+
0091
|
| 93 |
+
0092
|
| 94 |
+
0093
|
| 95 |
+
0094
|
| 96 |
+
0095
|
| 97 |
+
0096
|
| 98 |
+
0097
|
| 99 |
+
0098
|
| 100 |
+
0099
|
| 101 |
+
0100
|
| 102 |
+
0101
|
| 103 |
+
0102
|
| 104 |
+
0103
|
| 105 |
+
0104
|
| 106 |
+
0105
|
| 107 |
+
0106
|
| 108 |
+
0107
|
| 109 |
+
0108
|
| 110 |
+
0109
|
| 111 |
+
0110
|
| 112 |
+
0111
|
| 113 |
+
0112
|
| 114 |
+
0113
|
| 115 |
+
0114
|
| 116 |
+
0115
|
| 117 |
+
0116
|
| 118 |
+
0117
|
| 119 |
+
0118
|
| 120 |
+
0119
|
| 121 |
+
0120
|
| 122 |
+
0121
|
| 123 |
+
0122
|
| 124 |
+
0123
|
| 125 |
+
0124
|
| 126 |
+
0125
|
| 127 |
+
0126
|
| 128 |
+
0127
|
| 129 |
+
0128
|
| 130 |
+
0129
|
| 131 |
+
0130
|
| 132 |
+
0131
|
| 133 |
+
0132
|
| 134 |
+
0133
|
| 135 |
+
0134
|
| 136 |
+
0135
|
| 137 |
+
0136
|
| 138 |
+
0137
|
| 139 |
+
0138
|
| 140 |
+
0139
|
| 141 |
+
0140
|
| 142 |
+
0141
|
| 143 |
+
0142
|
| 144 |
+
0143
|
| 145 |
+
0144
|
| 146 |
+
0145
|
| 147 |
+
0146
|
| 148 |
+
0147
|
| 149 |
+
0148
|
| 150 |
+
0149
|
| 151 |
+
0150
|
| 152 |
+
0151
|
| 153 |
+
0152
|
| 154 |
+
0153
|
| 155 |
+
0154
|
| 156 |
+
0155
|
| 157 |
+
0156
|
| 158 |
+
0157
|
| 159 |
+
0158
|
| 160 |
+
0159
|
| 161 |
+
0160
|
| 162 |
+
0161
|
| 163 |
+
0162
|
| 164 |
+
0163
|
| 165 |
+
0164
|
| 166 |
+
0165
|
| 167 |
+
0166
|
| 168 |
+
0167
|
| 169 |
+
0168
|
| 170 |
+
0169
|
| 171 |
+
0170
|
| 172 |
+
0171
|
| 173 |
+
0172
|
| 174 |
+
0173
|
| 175 |
+
0174
|
| 176 |
+
0175
|
| 177 |
+
0176
|
| 178 |
+
0177
|
| 179 |
+
0178
|
| 180 |
+
0179
|
| 181 |
+
0180
|
| 182 |
+
0181
|
| 183 |
+
0182
|
| 184 |
+
0183
|
| 185 |
+
0184
|
| 186 |
+
0185
|
| 187 |
+
0186
|
| 188 |
+
0187
|
| 189 |
+
0188
|
| 190 |
+
0189
|
| 191 |
+
0190
|
| 192 |
+
0191
|
| 193 |
+
0192
|
| 194 |
+
0193
|
| 195 |
+
0194
|
| 196 |
+
0195
|
| 197 |
+
0196
|
| 198 |
+
0197
|
| 199 |
+
0198
|
| 200 |
+
0199
|
| 201 |
+
0200
|
| 202 |
+
0201
|
| 203 |
+
0202
|
| 204 |
+
0203
|
| 205 |
+
0204
|
| 206 |
+
0205
|
| 207 |
+
0206
|
| 208 |
+
0207
|
| 209 |
+
0208
|
| 210 |
+
0209
|
| 211 |
+
0210
|
| 212 |
+
0211
|
| 213 |
+
0212
|
| 214 |
+
0213
|
| 215 |
+
0214
|
| 216 |
+
0215
|
| 217 |
+
0216
|
| 218 |
+
0217
|
| 219 |
+
0218
|
| 220 |
+
0219
|
| 221 |
+
0220
|
| 222 |
+
0221
|
| 223 |
+
0222
|
| 224 |
+
0223
|
| 225 |
+
0224
|
| 226 |
+
0225
|
| 227 |
+
0226
|
| 228 |
+
0227
|
| 229 |
+
0228
|
| 230 |
+
0229
|
| 231 |
+
0230
|
| 232 |
+
0231
|
| 233 |
+
0232
|
| 234 |
+
0233
|
| 235 |
+
0234
|
| 236 |
+
0235
|
| 237 |
+
0236
|
| 238 |
+
0237
|
| 239 |
+
0238
|
| 240 |
+
0239
|
| 241 |
+
0240
|
| 242 |
+
0241
|
| 243 |
+
0242
|
| 244 |
+
0243
|
| 245 |
+
0244
|
| 246 |
+
0245
|
| 247 |
+
0246
|
| 248 |
+
0247
|
| 249 |
+
0248
|
| 250 |
+
0249
|
| 251 |
+
0250
|
| 252 |
+
0251
|
| 253 |
+
0252
|
| 254 |
+
0253
|
| 255 |
+
0254
|
| 256 |
+
0255
|
| 257 |
+
0256
|
| 258 |
+
0257
|
| 259 |
+
0258
|
| 260 |
+
0259
|
| 261 |
+
0260
|
| 262 |
+
0261
|
| 263 |
+
0262
|
| 264 |
+
0263
|
| 265 |
+
0264
|
| 266 |
+
0265
|
| 267 |
+
0266
|
| 268 |
+
0267
|
| 269 |
+
0268
|
| 270 |
+
0269
|
| 271 |
+
0270
|
| 272 |
+
0271
|
| 273 |
+
0272
|
| 274 |
+
0273
|
| 275 |
+
0274
|
| 276 |
+
0275
|
| 277 |
+
0276
|
| 278 |
+
0277
|
| 279 |
+
0278
|
| 280 |
+
0279
|
| 281 |
+
0280
|
| 282 |
+
0281
|
| 283 |
+
0282
|
| 284 |
+
0283
|
| 285 |
+
0284
|
| 286 |
+
0285
|
| 287 |
+
0286
|
| 288 |
+
0287
|
| 289 |
+
0288
|
| 290 |
+
0289
|
| 291 |
+
0290
|
| 292 |
+
0291
|
| 293 |
+
0292
|
| 294 |
+
0293
|
| 295 |
+
0294
|
| 296 |
+
0295
|
| 297 |
+
0296
|
| 298 |
+
0297
|
| 299 |
+
0298
|
| 300 |
+
0299
|
| 301 |
+
0300
|
| 302 |
+
0301
|
| 303 |
+
0302
|
| 304 |
+
0303
|
| 305 |
+
0304
|
| 306 |
+
0305
|
| 307 |
+
0306
|
| 308 |
+
0307
|
| 309 |
+
0308
|
| 310 |
+
0309
|
| 311 |
+
0310
|
| 312 |
+
0311
|
| 313 |
+
0312
|
| 314 |
+
0313
|
| 315 |
+
0314
|
| 316 |
+
0315
|
| 317 |
+
0316
|
| 318 |
+
0317
|
| 319 |
+
0318
|
| 320 |
+
0319
|
| 321 |
+
0320
|
| 322 |
+
0321
|
| 323 |
+
0322
|
| 324 |
+
0323
|
| 325 |
+
0324
|
| 326 |
+
0325
|
| 327 |
+
0326
|
| 328 |
+
0327
|
| 329 |
+
0328
|
| 330 |
+
0329
|
| 331 |
+
0330
|
| 332 |
+
0331
|
| 333 |
+
0332
|
| 334 |
+
0333
|
| 335 |
+
0334
|
| 336 |
+
0335
|
| 337 |
+
0336
|
| 338 |
+
0337
|
| 339 |
+
0338
|
| 340 |
+
0339
|
| 341 |
+
0340
|
| 342 |
+
0341
|
| 343 |
+
0342
|
| 344 |
+
0343
|
| 345 |
+
0344
|
| 346 |
+
0345
|
| 347 |
+
0346
|
| 348 |
+
0347
|
| 349 |
+
0348
|
| 350 |
+
0349
|
| 351 |
+
0350
|
| 352 |
+
0351
|
| 353 |
+
0352
|
| 354 |
+
0353
|
| 355 |
+
0354
|
| 356 |
+
0355
|
| 357 |
+
0356
|
| 358 |
+
0357
|
| 359 |
+
0358
|
| 360 |
+
0359
|
| 361 |
+
0360
|
| 362 |
+
0361
|
| 363 |
+
0362
|
| 364 |
+
0363
|
| 365 |
+
0364
|
| 366 |
+
0365
|
| 367 |
+
0366
|
| 368 |
+
0367
|
| 369 |
+
0368
|
| 370 |
+
0369
|
| 371 |
+
0370
|
| 372 |
+
0371
|
| 373 |
+
0372
|
| 374 |
+
0373
|
| 375 |
+
0374
|
| 376 |
+
0375
|
| 377 |
+
0376
|
| 378 |
+
0377
|
| 379 |
+
0378
|
| 380 |
+
0379
|
| 381 |
+
0380
|
| 382 |
+
0381
|
| 383 |
+
0382
|
| 384 |
+
0383
|
| 385 |
+
0384
|
| 386 |
+
0385
|
| 387 |
+
0386
|
| 388 |
+
0387
|
| 389 |
+
0388
|
| 390 |
+
0389
|
| 391 |
+
0390
|
| 392 |
+
0391
|
| 393 |
+
0392
|
| 394 |
+
0393
|
| 395 |
+
0394
|
| 396 |
+
0395
|
| 397 |
+
0396
|
| 398 |
+
0397
|
| 399 |
+
0398
|
| 400 |
+
0399
|
| 401 |
+
0400
|
| 402 |
+
0401
|
| 403 |
+
0402
|
| 404 |
+
0403
|
| 405 |
+
0404
|
| 406 |
+
0405
|
| 407 |
+
0406
|
| 408 |
+
0407
|
| 409 |
+
0408
|
| 410 |
+
0409
|
| 411 |
+
0410
|
| 412 |
+
0411
|
| 413 |
+
0412
|
| 414 |
+
0413
|
| 415 |
+
0414
|
| 416 |
+
0415
|
| 417 |
+
0416
|
| 418 |
+
0417
|
| 419 |
+
0418
|
| 420 |
+
0419
|
| 421 |
+
0420
|
| 422 |
+
0421
|
| 423 |
+
0422
|
| 424 |
+
0423
|
| 425 |
+
0424
|
| 426 |
+
0425
|
| 427 |
+
0426
|
| 428 |
+
0427
|
| 429 |
+
0428
|
| 430 |
+
0429
|
| 431 |
+
0430
|
| 432 |
+
0431
|
| 433 |
+
0432
|
| 434 |
+
0433
|
| 435 |
+
0434
|
| 436 |
+
0435
|
| 437 |
+
0436
|
| 438 |
+
0437
|
| 439 |
+
0438
|
| 440 |
+
0439
|
| 441 |
+
0440
|
| 442 |
+
0441
|
| 443 |
+
0442
|
| 444 |
+
0443
|
| 445 |
+
0444
|
| 446 |
+
0445
|
| 447 |
+
0446
|
| 448 |
+
0447
|
| 449 |
+
0448
|
| 450 |
+
0449
|
| 451 |
+
0450
|
| 452 |
+
0451
|
| 453 |
+
0452
|
| 454 |
+
0453
|
| 455 |
+
0454
|
| 456 |
+
0455
|
| 457 |
+
0456
|
| 458 |
+
0457
|
| 459 |
+
0458
|
| 460 |
+
0459
|
| 461 |
+
0460
|
| 462 |
+
0461
|
| 463 |
+
0462
|
| 464 |
+
0463
|
| 465 |
+
0464
|
| 466 |
+
0465
|
| 467 |
+
0466
|
| 468 |
+
0467
|
| 469 |
+
0468
|
| 470 |
+
0469
|
| 471 |
+
0470
|
| 472 |
+
0471
|
| 473 |
+
0472
|
| 474 |
+
0473
|
| 475 |
+
0474
|
| 476 |
+
0475
|
| 477 |
+
0476
|
| 478 |
+
0477
|
| 479 |
+
0478
|
| 480 |
+
0479
|
| 481 |
+
0480
|
| 482 |
+
0481
|
| 483 |
+
0482
|
| 484 |
+
0483
|
| 485 |
+
0484
|
| 486 |
+
0485
|
| 487 |
+
0486
|
| 488 |
+
0487
|
| 489 |
+
0488
|
| 490 |
+
0489
|
| 491 |
+
0490
|
| 492 |
+
0491
|
| 493 |
+
0492
|
| 494 |
+
0493
|
| 495 |
+
0494
|
| 496 |
+
0495
|
| 497 |
+
0496
|
| 498 |
+
0497
|
| 499 |
+
0498
|
| 500 |
+
0499
|
| 501 |
+
0500
|
| 502 |
+
0501
|
| 503 |
+
0502
|
| 504 |
+
0503
|
| 505 |
+
0504
|
| 506 |
+
0505
|
| 507 |
+
0506
|
| 508 |
+
0507
|
| 509 |
+
0508
|
| 510 |
+
0509
|
| 511 |
+
0510
|
| 512 |
+
0511
|
| 513 |
+
0512
|
| 514 |
+
0513
|
| 515 |
+
0514
|
| 516 |
+
0515
|
| 517 |
+
0516
|
| 518 |
+
0517
|
| 519 |
+
0518
|
| 520 |
+
0519
|
| 521 |
+
0520
|
| 522 |
+
0521
|
| 523 |
+
0522
|
| 524 |
+
0523
|
| 525 |
+
0524
|
| 526 |
+
0525
|
| 527 |
+
0526
|
| 528 |
+
0527
|
| 529 |
+
0528
|
| 530 |
+
0529
|
| 531 |
+
0530
|
| 532 |
+
0531
|
| 533 |
+
0532
|
| 534 |
+
0533
|
| 535 |
+
0534
|
| 536 |
+
0535
|
| 537 |
+
0536
|
| 538 |
+
0537
|
| 539 |
+
0538
|
| 540 |
+
0539
|
| 541 |
+
0540
|
| 542 |
+
0541
|
| 543 |
+
0542
|
| 544 |
+
0543
|
| 545 |
+
0544
|
| 546 |
+
0545
|
| 547 |
+
0546
|
| 548 |
+
0547
|
| 549 |
+
0548
|
| 550 |
+
0549
|
| 551 |
+
0550
|
| 552 |
+
0551
|
| 553 |
+
0552
|
| 554 |
+
0553
|
| 555 |
+
0554
|
| 556 |
+
0555
|
| 557 |
+
0556
|
| 558 |
+
0557
|
| 559 |
+
0558
|
| 560 |
+
0559
|
| 561 |
+
0560
|
| 562 |
+
0561
|
| 563 |
+
0562
|
| 564 |
+
0563
|
| 565 |
+
0564
|
| 566 |
+
0565
|
| 567 |
+
0566
|
| 568 |
+
0567
|
| 569 |
+
0568
|
| 570 |
+
0569
|
| 571 |
+
0570
|
| 572 |
+
0571
|
| 573 |
+
0572
|
| 574 |
+
0573
|
| 575 |
+
0574
|
| 576 |
+
0575
|
| 577 |
+
0576
|
| 578 |
+
0577
|
| 579 |
+
0578
|
| 580 |
+
0579
|
| 581 |
+
0580
|
| 582 |
+
0581
|
| 583 |
+
0582
|
| 584 |
+
0583
|
| 585 |
+
0584
|
| 586 |
+
0585
|
| 587 |
+
0586
|
| 588 |
+
0587
|
| 589 |
+
0588
|
| 590 |
+
0589
|
| 591 |
+
0590
|
| 592 |
+
0591
|
| 593 |
+
0592
|
| 594 |
+
0593
|
| 595 |
+
0594
|
| 596 |
+
0595
|
| 597 |
+
0596
|
| 598 |
+
0597
|
| 599 |
+
0598
|
| 600 |
+
0599
|
| 601 |
+
0600
|
| 602 |
+
0601
|
| 603 |
+
0602
|
| 604 |
+
0603
|
| 605 |
+
0604
|
| 606 |
+
0605
|
| 607 |
+
0606
|
| 608 |
+
0607
|
| 609 |
+
0608
|
| 610 |
+
0609
|
| 611 |
+
0610
|
| 612 |
+
0611
|
| 613 |
+
0612
|
| 614 |
+
0613
|
| 615 |
+
0614
|
| 616 |
+
0615
|
| 617 |
+
0616
|
| 618 |
+
0617
|
| 619 |
+
0618
|
| 620 |
+
0619
|
| 621 |
+
0620
|
| 622 |
+
0621
|
| 623 |
+
0622
|
| 624 |
+
0623
|
| 625 |
+
0624
|
| 626 |
+
0625
|
| 627 |
+
0626
|
| 628 |
+
0627
|
| 629 |
+
0628
|
| 630 |
+
0629
|
| 631 |
+
0630
|
| 632 |
+
0631
|
| 633 |
+
0632
|
| 634 |
+
0633
|
| 635 |
+
0634
|
| 636 |
+
0635
|
| 637 |
+
0636
|
| 638 |
+
0637
|
| 639 |
+
0638
|
| 640 |
+
0639
|
| 641 |
+
0640
|
| 642 |
+
0641
|
| 643 |
+
0642
|
| 644 |
+
0643
|
| 645 |
+
0644
|
| 646 |
+
0645
|
| 647 |
+
0646
|
| 648 |
+
0647
|
| 649 |
+
0648
|
| 650 |
+
0649
|
| 651 |
+
0650
|
| 652 |
+
0651
|
| 653 |
+
0652
|
| 654 |
+
0653
|
| 655 |
+
0654
|
| 656 |
+
0655
|
| 657 |
+
0656
|
| 658 |
+
0657
|
| 659 |
+
0658
|
| 660 |
+
0659
|
| 661 |
+
0660
|
| 662 |
+
0661
|
| 663 |
+
0662
|
| 664 |
+
0663
|
| 665 |
+
0664
|
| 666 |
+
0665
|
| 667 |
+
0666
|
| 668 |
+
0667
|
| 669 |
+
0668
|
| 670 |
+
0669
|
| 671 |
+
0670
|
| 672 |
+
0671
|
| 673 |
+
0672
|
| 674 |
+
0673
|
| 675 |
+
0674
|
| 676 |
+
0675
|
| 677 |
+
0676
|
| 678 |
+
0677
|
| 679 |
+
0678
|
| 680 |
+
0679
|
| 681 |
+
0680
|
| 682 |
+
0681
|
| 683 |
+
0682
|
| 684 |
+
0683
|
| 685 |
+
0684
|
| 686 |
+
0685
|
| 687 |
+
0686
|
| 688 |
+
0687
|
| 689 |
+
0688
|
| 690 |
+
0689
|
| 691 |
+
0690
|
| 692 |
+
0691
|
| 693 |
+
0692
|
| 694 |
+
0693
|
| 695 |
+
0694
|
| 696 |
+
0695
|
| 697 |
+
0696
|
| 698 |
+
0697
|
| 699 |
+
0698
|
| 700 |
+
0699
|
| 701 |
+
0700
|
| 702 |
+
0701
|
| 703 |
+
0702
|
| 704 |
+
0703
|
| 705 |
+
0704
|
| 706 |
+
0705
|
| 707 |
+
0706
|
| 708 |
+
0707
|
| 709 |
+
0708
|
| 710 |
+
0709
|
| 711 |
+
0710
|
| 712 |
+
0711
|
| 713 |
+
0712
|
| 714 |
+
0713
|
| 715 |
+
0714
|
| 716 |
+
0715
|
| 717 |
+
0716
|
| 718 |
+
0717
|
| 719 |
+
0718
|
| 720 |
+
0719
|
| 721 |
+
0720
|
| 722 |
+
0721
|
| 723 |
+
0722
|
| 724 |
+
0723
|
| 725 |
+
0724
|
| 726 |
+
0725
|
| 727 |
+
0726
|
| 728 |
+
0727
|
| 729 |
+
0728
|
| 730 |
+
0729
|
| 731 |
+
0730
|
| 732 |
+
0731
|
| 733 |
+
0732
|
| 734 |
+
0733
|
| 735 |
+
0734
|
| 736 |
+
0735
|
| 737 |
+
0736
|
| 738 |
+
0737
|
| 739 |
+
0738
|
| 740 |
+
0739
|
| 741 |
+
0740
|
| 742 |
+
0741
|
| 743 |
+
0742
|
| 744 |
+
0743
|
| 745 |
+
0744
|
| 746 |
+
0745
|
| 747 |
+
0746
|
| 748 |
+
0747
|
| 749 |
+
0748
|
| 750 |
+
0749
|
| 751 |
+
0750
|
| 752 |
+
0751
|
| 753 |
+
0752
|
| 754 |
+
0753
|
| 755 |
+
0754
|
| 756 |
+
0755
|
| 757 |
+
0756
|
| 758 |
+
0757
|
| 759 |
+
0758
|
| 760 |
+
0759
|
| 761 |
+
0760
|
| 762 |
+
0761
|
| 763 |
+
0762
|
| 764 |
+
0763
|
| 765 |
+
0764
|
| 766 |
+
0765
|
| 767 |
+
0766
|
| 768 |
+
0767
|
| 769 |
+
0768
|
| 770 |
+
0769
|
| 771 |
+
0770
|
| 772 |
+
0771
|
| 773 |
+
0772
|
| 774 |
+
0773
|
| 775 |
+
0774
|
| 776 |
+
0775
|
| 777 |
+
0776
|
| 778 |
+
0777
|
| 779 |
+
0778
|
| 780 |
+
0779
|
| 781 |
+
0780
|
| 782 |
+
0781
|
| 783 |
+
0782
|
| 784 |
+
0783
|
| 785 |
+
0784
|
| 786 |
+
0785
|
| 787 |
+
0786
|
| 788 |
+
0787
|
| 789 |
+
0788
|
| 790 |
+
0789
|
| 791 |
+
0790
|
| 792 |
+
0791
|
| 793 |
+
0792
|
| 794 |
+
0793
|
| 795 |
+
0794
|
| 796 |
+
0795
|
| 797 |
+
0796
|
| 798 |
+
0797
|
| 799 |
+
0798
|
| 800 |
+
0799
|
| 801 |
+
0800
|
| 802 |
+
0801
|
| 803 |
+
0802
|
| 804 |
+
0803
|
| 805 |
+
0804
|
| 806 |
+
0805
|
| 807 |
+
0806
|
| 808 |
+
0807
|
| 809 |
+
0808
|
| 810 |
+
0809
|
| 811 |
+
0810
|
| 812 |
+
0811
|
| 813 |
+
0812
|
| 814 |
+
0813
|
| 815 |
+
0814
|
| 816 |
+
0815
|
| 817 |
+
0816
|
| 818 |
+
0817
|
| 819 |
+
0818
|
| 820 |
+
0819
|
| 821 |
+
0820
|
| 822 |
+
0821
|
| 823 |
+
0822
|
| 824 |
+
0823
|
| 825 |
+
0824
|
| 826 |
+
0825
|
| 827 |
+
0826
|
| 828 |
+
0827
|
| 829 |
+
0828
|
| 830 |
+
0829
|
| 831 |
+
0830
|
| 832 |
+
0831
|
| 833 |
+
0832
|
| 834 |
+
0833
|
| 835 |
+
0834
|
| 836 |
+
0835
|
| 837 |
+
0836
|
| 838 |
+
0837
|
| 839 |
+
0838
|
| 840 |
+
0839
|
| 841 |
+
0840
|
| 842 |
+
0841
|
| 843 |
+
0842
|
| 844 |
+
0843
|
| 845 |
+
0844
|
| 846 |
+
0845
|
| 847 |
+
0846
|
| 848 |
+
0847
|
| 849 |
+
0848
|
| 850 |
+
0849
|
| 851 |
+
0850
|
| 852 |
+
0851
|
| 853 |
+
0852
|
| 854 |
+
0853
|
| 855 |
+
0854
|
| 856 |
+
0855
|
| 857 |
+
0856
|
| 858 |
+
0857
|
| 859 |
+
0858
|
| 860 |
+
0859
|
| 861 |
+
0860
|
| 862 |
+
0861
|
| 863 |
+
0862
|
| 864 |
+
0863
|
| 865 |
+
0864
|
| 866 |
+
0865
|
| 867 |
+
0866
|
| 868 |
+
0867
|
| 869 |
+
0868
|
| 870 |
+
0869
|
| 871 |
+
0870
|
| 872 |
+
0871
|
| 873 |
+
0872
|
| 874 |
+
0873
|
| 875 |
+
0874
|
| 876 |
+
0875
|
| 877 |
+
0876
|
| 878 |
+
0877
|
| 879 |
+
0878
|
| 880 |
+
0879
|
| 881 |
+
0880
|
| 882 |
+
0881
|
| 883 |
+
0882
|
| 884 |
+
0883
|
| 885 |
+
0884
|
| 886 |
+
0885
|
| 887 |
+
0886
|
| 888 |
+
0887
|
| 889 |
+
0888
|
| 890 |
+
0889
|
| 891 |
+
0890
|
| 892 |
+
0891
|
| 893 |
+
0892
|
| 894 |
+
0893
|
| 895 |
+
0894
|
| 896 |
+
0895
|
| 897 |
+
0896
|
| 898 |
+
0897
|
| 899 |
+
0898
|
| 900 |
+
0899
|
| 901 |
+
0900
|
| 902 |
+
0901
|
| 903 |
+
0902
|
| 904 |
+
0903
|
| 905 |
+
0904
|
| 906 |
+
0905
|
| 907 |
+
0906
|
| 908 |
+
0907
|
| 909 |
+
0908
|
| 910 |
+
0909
|
| 911 |
+
0910
|
| 912 |
+
0911
|
| 913 |
+
0912
|
| 914 |
+
0913
|
| 915 |
+
0914
|
| 916 |
+
0915
|
| 917 |
+
0916
|
| 918 |
+
0917
|
| 919 |
+
0918
|
| 920 |
+
0919
|
| 921 |
+
0920
|
| 922 |
+
0921
|
| 923 |
+
0922
|
| 924 |
+
0923
|
| 925 |
+
0924
|
| 926 |
+
0925
|
| 927 |
+
0926
|
| 928 |
+
0927
|
| 929 |
+
0928
|
| 930 |
+
0929
|
| 931 |
+
0930
|
| 932 |
+
0931
|
| 933 |
+
0932
|
| 934 |
+
0933
|
| 935 |
+
0934
|
| 936 |
+
0935
|
| 937 |
+
0936
|
| 938 |
+
0937
|
| 939 |
+
0938
|
| 940 |
+
0939
|
| 941 |
+
0940
|
| 942 |
+
0941
|
| 943 |
+
0942
|
| 944 |
+
0943
|
| 945 |
+
0944
|
| 946 |
+
0945
|
| 947 |
+
0946
|
| 948 |
+
0947
|
| 949 |
+
0948
|
| 950 |
+
0949
|
| 951 |
+
0950
|
| 952 |
+
0951
|
| 953 |
+
0952
|
| 954 |
+
0953
|
| 955 |
+
0954
|
| 956 |
+
0955
|
| 957 |
+
0956
|
| 958 |
+
0957
|
| 959 |
+
0958
|
| 960 |
+
0959
|
| 961 |
+
0960
|
| 962 |
+
0961
|
| 963 |
+
0962
|
| 964 |
+
0963
|
| 965 |
+
0964
|
| 966 |
+
0965
|
| 967 |
+
0966
|
| 968 |
+
0967
|
| 969 |
+
0968
|
| 970 |
+
0969
|
| 971 |
+
0970
|
| 972 |
+
0971
|
| 973 |
+
0972
|
| 974 |
+
0973
|
| 975 |
+
0974
|
| 976 |
+
0975
|
| 977 |
+
0976
|
| 978 |
+
0977
|
| 979 |
+
0978
|
| 980 |
+
0979
|
| 981 |
+
0980
|
| 982 |
+
0981
|
| 983 |
+
0982
|
| 984 |
+
0983
|
| 985 |
+
0984
|
| 986 |
+
0985
|
| 987 |
+
0986
|
| 988 |
+
0987
|
| 989 |
+
0988
|
| 990 |
+
0989
|
| 991 |
+
0990
|
| 992 |
+
0991
|
| 993 |
+
0992
|
| 994 |
+
0993
|
| 995 |
+
0994
|
| 996 |
+
0995
|
| 997 |
+
0996
|
| 998 |
+
0997
|
| 999 |
+
0998
|
| 1000 |
+
0999
|
| 1001 |
+
1000
|
| 1002 |
+
1001
|
| 1003 |
+
1002
|
| 1004 |
+
1003
|
| 1005 |
+
1004
|
| 1006 |
+
1005
|
| 1007 |
+
1006
|
| 1008 |
+
1007
|
| 1009 |
+
1008
|
| 1010 |
+
1009
|
| 1011 |
+
1010
|
| 1012 |
+
1011
|
| 1013 |
+
1012
|
| 1014 |
+
1013
|
| 1015 |
+
1014
|
| 1016 |
+
1015
|
| 1017 |
+
1016
|
| 1018 |
+
1017
|
| 1019 |
+
1018
|
| 1020 |
+
1019
|
| 1021 |
+
1020
|
| 1022 |
+
1021
|
| 1023 |
+
1022
|
| 1024 |
+
1023
|
| 1025 |
+
1024
|
| 1026 |
+
1025
|
| 1027 |
+
1026
|
| 1028 |
+
1027
|
| 1029 |
+
1028
|
| 1030 |
+
1029
|
| 1031 |
+
1030
|
| 1032 |
+
1031
|
| 1033 |
+
1032
|
| 1034 |
+
1033
|
| 1035 |
+
1034
|
| 1036 |
+
1035
|
| 1037 |
+
1036
|
| 1038 |
+
1037
|
| 1039 |
+
1038
|
| 1040 |
+
1039
|
| 1041 |
+
1040
|
| 1042 |
+
1041
|
| 1043 |
+
1042
|
| 1044 |
+
1043
|
| 1045 |
+
1044
|
| 1046 |
+
1045
|
| 1047 |
+
1046
|
| 1048 |
+
1047
|
| 1049 |
+
1048
|
| 1050 |
+
1049
|
| 1051 |
+
1050
|
| 1052 |
+
1051
|
| 1053 |
+
1052
|
| 1054 |
+
1053
|
| 1055 |
+
1054
|
| 1056 |
+
1055
|
| 1057 |
+
1056
|
| 1058 |
+
1057
|
| 1059 |
+
1058
|
| 1060 |
+
1059
|
| 1061 |
+
1060
|
| 1062 |
+
1061
|
| 1063 |
+
1062
|
| 1064 |
+
1063
|
| 1065 |
+
1064
|
| 1066 |
+
1065
|
| 1067 |
+
1066
|
| 1068 |
+
1067
|
| 1069 |
+
1068
|
| 1070 |
+
1069
|
| 1071 |
+
1070
|
| 1072 |
+
1071
|
| 1073 |
+
1072
|
| 1074 |
+
1073
|
| 1075 |
+
1074
|
| 1076 |
+
1075
|
| 1077 |
+
1076
|
| 1078 |
+
1077
|
| 1079 |
+
1078
|
| 1080 |
+
1079
|
| 1081 |
+
1080
|
| 1082 |
+
1081
|
| 1083 |
+
1082
|
| 1084 |
+
1083
|
| 1085 |
+
1084
|
| 1086 |
+
1085
|
| 1087 |
+
1086
|
| 1088 |
+
1087
|
| 1089 |
+
1088
|
| 1090 |
+
1089
|
| 1091 |
+
1090
|
| 1092 |
+
1091
|
| 1093 |
+
1092
|
| 1094 |
+
1093
|
| 1095 |
+
1094
|
| 1096 |
+
1095
|
| 1097 |
+
1096
|
| 1098 |
+
1097
|
| 1099 |
+
1098
|
| 1100 |
+
1099
|
| 1101 |
+
1100
|
| 1102 |
+
1101
|
| 1103 |
+
1102
|
| 1104 |
+
1103
|
| 1105 |
+
1104
|
| 1106 |
+
1105
|
| 1107 |
+
1106
|
| 1108 |
+
1107
|
| 1109 |
+
1108
|
| 1110 |
+
1109
|
| 1111 |
+
1110
|
| 1112 |
+
1111
|
| 1113 |
+
1112
|
| 1114 |
+
1113
|
| 1115 |
+
1114
|
| 1116 |
+
1115
|
| 1117 |
+
1116
|
| 1118 |
+
1117
|
| 1119 |
+
1118
|
| 1120 |
+
1119
|
| 1121 |
+
1120
|
| 1122 |
+
1121
|
| 1123 |
+
1122
|
| 1124 |
+
1123
|
| 1125 |
+
1124
|
| 1126 |
+
1125
|
| 1127 |
+
1126
|
| 1128 |
+
1127
|
| 1129 |
+
1128
|
| 1130 |
+
1129
|
| 1131 |
+
1130
|
| 1132 |
+
1131
|
| 1133 |
+
1132
|
| 1134 |
+
1133
|
| 1135 |
+
1134
|
| 1136 |
+
1135
|
| 1137 |
+
1136
|
| 1138 |
+
1137
|
| 1139 |
+
1138
|
| 1140 |
+
1139
|
| 1141 |
+
1140
|
| 1142 |
+
1141
|
| 1143 |
+
1142
|
| 1144 |
+
1143
|
| 1145 |
+
1144
|
| 1146 |
+
1145
|
| 1147 |
+
1146
|
| 1148 |
+
1147
|
| 1149 |
+
1148
|
| 1150 |
+
1149
|
| 1151 |
+
1150
|
| 1152 |
+
1151
|
| 1153 |
+
1152
|
| 1154 |
+
1153
|
| 1155 |
+
1154
|
| 1156 |
+
1155
|
| 1157 |
+
1156
|
| 1158 |
+
1157
|
| 1159 |
+
1158
|
| 1160 |
+
1159
|
| 1161 |
+
1160
|
| 1162 |
+
1161
|
| 1163 |
+
1162
|
| 1164 |
+
1163
|
| 1165 |
+
1164
|
| 1166 |
+
1165
|
| 1167 |
+
1166
|
| 1168 |
+
1167
|
| 1169 |
+
1168
|
| 1170 |
+
1169
|
| 1171 |
+
1170
|
| 1172 |
+
1171
|
| 1173 |
+
1172
|
| 1174 |
+
1173
|
| 1175 |
+
1174
|
| 1176 |
+
1175
|
| 1177 |
+
1176
|
| 1178 |
+
1177
|
| 1179 |
+
1178
|
| 1180 |
+
1179
|
| 1181 |
+
1180
|
| 1182 |
+
1181
|
| 1183 |
+
1182
|
| 1184 |
+
1183
|
| 1185 |
+
1184
|
| 1186 |
+
1185
|
| 1187 |
+
1186
|
| 1188 |
+
1187
|
| 1189 |
+
1188
|
| 1190 |
+
1189
|
| 1191 |
+
1190
|
| 1192 |
+
1191
|
| 1193 |
+
1192
|
| 1194 |
+
1193
|
| 1195 |
+
1194
|
| 1196 |
+
1195
|
| 1197 |
+
1196
|
| 1198 |
+
1197
|
| 1199 |
+
1198
|
| 1200 |
+
1199
|
| 1201 |
+
1200
|
| 1202 |
+
1201
|
| 1203 |
+
1202
|
| 1204 |
+
1203
|
| 1205 |
+
1204
|
| 1206 |
+
1205
|
| 1207 |
+
1206
|
| 1208 |
+
1207
|
| 1209 |
+
1208
|
| 1210 |
+
1209
|
| 1211 |
+
1210
|
| 1212 |
+
1211
|
| 1213 |
+
1212
|
| 1214 |
+
1213
|
| 1215 |
+
1214
|
| 1216 |
+
1215
|
| 1217 |
+
1216
|
| 1218 |
+
1217
|
| 1219 |
+
1218
|
| 1220 |
+
1219
|
| 1221 |
+
1220
|
| 1222 |
+
1221
|
| 1223 |
+
1222
|
| 1224 |
+
1223
|
| 1225 |
+
1224
|
| 1226 |
+
1225
|
| 1227 |
+
1226
|
| 1228 |
+
1227
|
| 1229 |
+
1228
|
| 1230 |
+
1229
|
| 1231 |
+
1230
|
| 1232 |
+
1231
|
| 1233 |
+
1232
|
| 1234 |
+
1233
|
| 1235 |
+
1234
|
| 1236 |
+
1235
|
| 1237 |
+
1236
|
| 1238 |
+
1237
|
| 1239 |
+
1238
|
| 1240 |
+
1239
|
| 1241 |
+
1240
|
| 1242 |
+
1241
|
| 1243 |
+
1242
|
| 1244 |
+
1243
|
| 1245 |
+
1244
|
| 1246 |
+
1245
|
| 1247 |
+
1246
|
| 1248 |
+
1247
|
| 1249 |
+
1248
|
| 1250 |
+
1249
|
| 1251 |
+
1250
|
| 1252 |
+
1251
|
| 1253 |
+
1252
|
| 1254 |
+
1253
|
| 1255 |
+
1254
|
| 1256 |
+
1255
|
| 1257 |
+
1256
|
| 1258 |
+
1257
|
| 1259 |
+
1258
|
| 1260 |
+
1259
|
| 1261 |
+
1260
|
| 1262 |
+
1261
|
| 1263 |
+
1262
|
| 1264 |
+
1263
|
| 1265 |
+
1264
|
| 1266 |
+
1265
|
| 1267 |
+
1266
|
| 1268 |
+
1267
|
| 1269 |
+
1268
|
| 1270 |
+
1269
|
| 1271 |
+
1270
|
| 1272 |
+
1271
|
| 1273 |
+
1272
|
| 1274 |
+
1273
|
| 1275 |
+
1274
|
| 1276 |
+
1275
|
| 1277 |
+
1276
|
| 1278 |
+
1277
|
| 1279 |
+
1278
|
| 1280 |
+
1279
|
| 1281 |
+
1280
|
| 1282 |
+
1281
|
| 1283 |
+
1282
|
| 1284 |
+
1283
|
| 1285 |
+
1284
|
| 1286 |
+
1285
|
| 1287 |
+
1286
|
| 1288 |
+
1287
|
| 1289 |
+
1288
|
| 1290 |
+
1289
|
| 1291 |
+
1290
|
| 1292 |
+
1291
|
| 1293 |
+
1292
|
| 1294 |
+
1293
|
| 1295 |
+
1294
|
| 1296 |
+
1295
|
| 1297 |
+
1296
|
| 1298 |
+
1297
|
| 1299 |
+
1298
|
| 1300 |
+
1299
|
| 1301 |
+
1300
|
| 1302 |
+
1301
|
| 1303 |
+
1302
|
| 1304 |
+
1303
|
| 1305 |
+
1304
|
| 1306 |
+
1305
|
| 1307 |
+
1306
|
| 1308 |
+
1307
|
| 1309 |
+
1308
|
| 1310 |
+
1309
|
| 1311 |
+
1310
|
| 1312 |
+
1311
|
| 1313 |
+
1312
|
| 1314 |
+
1313
|
| 1315 |
+
1314
|
| 1316 |
+
1315
|
| 1317 |
+
1316
|
| 1318 |
+
1317
|
| 1319 |
+
1318
|
| 1320 |
+
1319
|
| 1321 |
+
1320
|
| 1322 |
+
1321
|
| 1323 |
+
1322
|
| 1324 |
+
1323
|
| 1325 |
+
1324
|
| 1326 |
+
1325
|
| 1327 |
+
1326
|
| 1328 |
+
1327
|
| 1329 |
+
1328
|
| 1330 |
+
1329
|
| 1331 |
+
1330
|
| 1332 |
+
1331
|
| 1333 |
+
1332
|
| 1334 |
+
1333
|
| 1335 |
+
1334
|
| 1336 |
+
1335
|
| 1337 |
+
1336
|
| 1338 |
+
1337
|
| 1339 |
+
1338
|
| 1340 |
+
1339
|
| 1341 |
+
1340
|
| 1342 |
+
1341
|
| 1343 |
+
1342
|
| 1344 |
+
1343
|
| 1345 |
+
1344
|
| 1346 |
+
1345
|
| 1347 |
+
1346
|
| 1348 |
+
1347
|
| 1349 |
+
1348
|
| 1350 |
+
1349
|
| 1351 |
+
1350
|
| 1352 |
+
1351
|
| 1353 |
+
1352
|
| 1354 |
+
1353
|
| 1355 |
+
1354
|
| 1356 |
+
1355
|
| 1357 |
+
1356
|
| 1358 |
+
1357
|
| 1359 |
+
1358
|
| 1360 |
+
1359
|
| 1361 |
+
1360
|
| 1362 |
+
1361
|
| 1363 |
+
1362
|
| 1364 |
+
1363
|
| 1365 |
+
1364
|
| 1366 |
+
1365
|
| 1367 |
+
1366
|
| 1368 |
+
1367
|
| 1369 |
+
1368
|
| 1370 |
+
1369
|
| 1371 |
+
1370
|
| 1372 |
+
1371
|
| 1373 |
+
1372
|
| 1374 |
+
1373
|
| 1375 |
+
1374
|
| 1376 |
+
1375
|
| 1377 |
+
1376
|
| 1378 |
+
1377
|
| 1379 |
+
1378
|
| 1380 |
+
1379
|
| 1381 |
+
1380
|
| 1382 |
+
1381
|
| 1383 |
+
1382
|
| 1384 |
+
1383
|
| 1385 |
+
1384
|
| 1386 |
+
1385
|
| 1387 |
+
1386
|
| 1388 |
+
1387
|
| 1389 |
+
1388
|
| 1390 |
+
1389
|
| 1391 |
+
1390
|
| 1392 |
+
1391
|
| 1393 |
+
1392
|
| 1394 |
+
1393
|
| 1395 |
+
1394
|
| 1396 |
+
1395
|
| 1397 |
+
1396
|
| 1398 |
+
1397
|
| 1399 |
+
1398
|
| 1400 |
+
1399
|
| 1401 |
+
1400
|
| 1402 |
+
1401
|
| 1403 |
+
1402
|
| 1404 |
+
1403
|
| 1405 |
+
1404
|
| 1406 |
+
1405
|
| 1407 |
+
1406
|
| 1408 |
+
1407
|
| 1409 |
+
1408
|
| 1410 |
+
1409
|
| 1411 |
+
1410
|
| 1412 |
+
1411
|
| 1413 |
+
1412
|
| 1414 |
+
1413
|
| 1415 |
+
1414
|
| 1416 |
+
1415
|
| 1417 |
+
1416
|
| 1418 |
+
1417
|
| 1419 |
+
1418
|
| 1420 |
+
1419
|
| 1421 |
+
1420
|
| 1422 |
+
1421
|
| 1423 |
+
1422
|
| 1424 |
+
1423
|
| 1425 |
+
1424
|
| 1426 |
+
1425
|
| 1427 |
+
1426
|
| 1428 |
+
1427
|
| 1429 |
+
1428
|
| 1430 |
+
1429
|
| 1431 |
+
1430
|
| 1432 |
+
1431
|
| 1433 |
+
1432
|
| 1434 |
+
1433
|
| 1435 |
+
1434
|
| 1436 |
+
1435
|
| 1437 |
+
1436
|
| 1438 |
+
1437
|
| 1439 |
+
1438
|
| 1440 |
+
1439
|
| 1441 |
+
1440
|
| 1442 |
+
1441
|
| 1443 |
+
1442
|
| 1444 |
+
1443
|
| 1445 |
+
1444
|
| 1446 |
+
1445
|
| 1447 |
+
1446
|
| 1448 |
+
1447
|
| 1449 |
+
1448
|
| 1450 |
+
1449
|
| 1451 |
+
1450
|
| 1452 |
+
1451
|
| 1453 |
+
1452
|
| 1454 |
+
1453
|
| 1455 |
+
1454
|
| 1456 |
+
1455
|
| 1457 |
+
1456
|
| 1458 |
+
1457
|
| 1459 |
+
1458
|
| 1460 |
+
1459
|
| 1461 |
+
1460
|
| 1462 |
+
1461
|
| 1463 |
+
1462
|
| 1464 |
+
1463
|
| 1465 |
+
1464
|
| 1466 |
+
1465
|
| 1467 |
+
1466
|
| 1468 |
+
1467
|
| 1469 |
+
1468
|
| 1470 |
+
1469
|
| 1471 |
+
1470
|
| 1472 |
+
1471
|
| 1473 |
+
1472
|
| 1474 |
+
1473
|
| 1475 |
+
1474
|
| 1476 |
+
1475
|
| 1477 |
+
1476
|
| 1478 |
+
1477
|
| 1479 |
+
1478
|
| 1480 |
+
1479
|
| 1481 |
+
1480
|
| 1482 |
+
1481
|
| 1483 |
+
1482
|
| 1484 |
+
1483
|
| 1485 |
+
1484
|
| 1486 |
+
1485
|
| 1487 |
+
1486
|
| 1488 |
+
1487
|
| 1489 |
+
1488
|
| 1490 |
+
1489
|
| 1491 |
+
1490
|
| 1492 |
+
1491
|
| 1493 |
+
1492
|
| 1494 |
+
1493
|
| 1495 |
+
1494
|
| 1496 |
+
1495
|
| 1497 |
+
1496
|
| 1498 |
+
1497
|
| 1499 |
+
1498
|
| 1500 |
+
1499
|
| 1501 |
+
1500
|
| 1502 |
+
1501
|
| 1503 |
+
1502
|
| 1504 |
+
1503
|
| 1505 |
+
1504
|
| 1506 |
+
1505
|
| 1507 |
+
1506
|
| 1508 |
+
1507
|
| 1509 |
+
1508
|
| 1510 |
+
1509
|
| 1511 |
+
1510
|
| 1512 |
+
1511
|
| 1513 |
+
1512
|
| 1514 |
+
1513
|
| 1515 |
+
1514
|
| 1516 |
+
1515
|
| 1517 |
+
1516
|
| 1518 |
+
1517
|
| 1519 |
+
1518
|
| 1520 |
+
1519
|
| 1521 |
+
1520
|
| 1522 |
+
1521
|
| 1523 |
+
1522
|
| 1524 |
+
1523
|
| 1525 |
+
1524
|
| 1526 |
+
1525
|
| 1527 |
+
1526
|
| 1528 |
+
1527
|
| 1529 |
+
1528
|
| 1530 |
+
1529
|
| 1531 |
+
1530
|
| 1532 |
+
1531
|
| 1533 |
+
1532
|
| 1534 |
+
1533
|
| 1535 |
+
1534
|
| 1536 |
+
1535
|
| 1537 |
+
1536
|
| 1538 |
+
1537
|
| 1539 |
+
1538
|
| 1540 |
+
1539
|
| 1541 |
+
1540
|
| 1542 |
+
1541
|
| 1543 |
+
1542
|
| 1544 |
+
1543
|
| 1545 |
+
1544
|
| 1546 |
+
1545
|
| 1547 |
+
1546
|
| 1548 |
+
1547
|
| 1549 |
+
1548
|
| 1550 |
+
1549
|
| 1551 |
+
1550
|
| 1552 |
+
1551
|
| 1553 |
+
1552
|
| 1554 |
+
1553
|
| 1555 |
+
1554
|
| 1556 |
+
1555
|
| 1557 |
+
1556
|
| 1558 |
+
1557
|
| 1559 |
+
1558
|
| 1560 |
+
1559
|
| 1561 |
+
1560
|
| 1562 |
+
1561
|
| 1563 |
+
1562
|
| 1564 |
+
1563
|
| 1565 |
+
1564
|
| 1566 |
+
1565
|
| 1567 |
+
1566
|
| 1568 |
+
1567
|
| 1569 |
+
1568
|
| 1570 |
+
1569
|
| 1571 |
+
1570
|
| 1572 |
+
1571
|
| 1573 |
+
1572
|
| 1574 |
+
1573
|
| 1575 |
+
1574
|
| 1576 |
+
1575
|
| 1577 |
+
1576
|
| 1578 |
+
1577
|
| 1579 |
+
1578
|
| 1580 |
+
1579
|
| 1581 |
+
1580
|
| 1582 |
+
1581
|
| 1583 |
+
1582
|
| 1584 |
+
1583
|
| 1585 |
+
1584
|
| 1586 |
+
1585
|
| 1587 |
+
1586
|
| 1588 |
+
1587
|
| 1589 |
+
1588
|
| 1590 |
+
1589
|
| 1591 |
+
1590
|
| 1592 |
+
1591
|
| 1593 |
+
1592
|
| 1594 |
+
1593
|
| 1595 |
+
1594
|
| 1596 |
+
1595
|
| 1597 |
+
1596
|
| 1598 |
+
1597
|
| 1599 |
+
1598
|
| 1600 |
+
1599
|
| 1601 |
+
1600
|
| 1602 |
+
1601
|
| 1603 |
+
1602
|
| 1604 |
+
1603
|
| 1605 |
+
1604
|
| 1606 |
+
1605
|
| 1607 |
+
1606
|
| 1608 |
+
1607
|
| 1609 |
+
1608
|
| 1610 |
+
1609
|
| 1611 |
+
1610
|
| 1612 |
+
1611
|
| 1613 |
+
1612
|
| 1614 |
+
1613
|
| 1615 |
+
1614
|
| 1616 |
+
1615
|
| 1617 |
+
1616
|
| 1618 |
+
1617
|
| 1619 |
+
1618
|
| 1620 |
+
1619
|
| 1621 |
+
1620
|
| 1622 |
+
1621
|
| 1623 |
+
1622
|
| 1624 |
+
1623
|
| 1625 |
+
1624
|
| 1626 |
+
1625
|
| 1627 |
+
1626
|
| 1628 |
+
1627
|
| 1629 |
+
1628
|
| 1630 |
+
1629
|
| 1631 |
+
1630
|
| 1632 |
+
1631
|
| 1633 |
+
1632
|
| 1634 |
+
1633
|
| 1635 |
+
1634
|
| 1636 |
+
1635
|
| 1637 |
+
1636
|
| 1638 |
+
1637
|
| 1639 |
+
1638
|
| 1640 |
+
1639
|
| 1641 |
+
1640
|
| 1642 |
+
1641
|
| 1643 |
+
1642
|
| 1644 |
+
1643
|
| 1645 |
+
1644
|
| 1646 |
+
1645
|
| 1647 |
+
1646
|
| 1648 |
+
1647
|
| 1649 |
+
1648
|
| 1650 |
+
1649
|
| 1651 |
+
1650
|
| 1652 |
+
1651
|
| 1653 |
+
1652
|
| 1654 |
+
1653
|
| 1655 |
+
1654
|
| 1656 |
+
1655
|
| 1657 |
+
1656
|
| 1658 |
+
1657
|
| 1659 |
+
1658
|
| 1660 |
+
1659
|
| 1661 |
+
1660
|
| 1662 |
+
1661
|
| 1663 |
+
1662
|
| 1664 |
+
1663
|
| 1665 |
+
1664
|
| 1666 |
+
1665
|
| 1667 |
+
1666
|
| 1668 |
+
1667
|
| 1669 |
+
1668
|
| 1670 |
+
1669
|
| 1671 |
+
1670
|
| 1672 |
+
1671
|
| 1673 |
+
1672
|
| 1674 |
+
1673
|
| 1675 |
+
1674
|
| 1676 |
+
1675
|
| 1677 |
+
1676
|
| 1678 |
+
1677
|
| 1679 |
+
1678
|
| 1680 |
+
1679
|
| 1681 |
+
1680
|
| 1682 |
+
1681
|
| 1683 |
+
1682
|
| 1684 |
+
1683
|
| 1685 |
+
1684
|
| 1686 |
+
1685
|
| 1687 |
+
1686
|
| 1688 |
+
1687
|
| 1689 |
+
1688
|
| 1690 |
+
1689
|
| 1691 |
+
1690
|
| 1692 |
+
1691
|
| 1693 |
+
1692
|
| 1694 |
+
1693
|
| 1695 |
+
1694
|
| 1696 |
+
1695
|
| 1697 |
+
1696
|
| 1698 |
+
1697
|
| 1699 |
+
1698
|
| 1700 |
+
1699
|
| 1701 |
+
1700
|
| 1702 |
+
1701
|
| 1703 |
+
1702
|
| 1704 |
+
1703
|
| 1705 |
+
1704
|
| 1706 |
+
1705
|
| 1707 |
+
1706
|
| 1708 |
+
1707
|
| 1709 |
+
1708
|
| 1710 |
+
1709
|
| 1711 |
+
1710
|
| 1712 |
+
1711
|
| 1713 |
+
1712
|
| 1714 |
+
1713
|
| 1715 |
+
1714
|
| 1716 |
+
1715
|
| 1717 |
+
1716
|
| 1718 |
+
1717
|
| 1719 |
+
1718
|
| 1720 |
+
1719
|
| 1721 |
+
1720
|
| 1722 |
+
1721
|
| 1723 |
+
1722
|
| 1724 |
+
1723
|
| 1725 |
+
1724
|
| 1726 |
+
1725
|
| 1727 |
+
1726
|
| 1728 |
+
1727
|
| 1729 |
+
1728
|
| 1730 |
+
1729
|
| 1731 |
+
1730
|
| 1732 |
+
1731
|
| 1733 |
+
1732
|
| 1734 |
+
1733
|
| 1735 |
+
1734
|
| 1736 |
+
1735
|
| 1737 |
+
1736
|
| 1738 |
+
1737
|
| 1739 |
+
1738
|
| 1740 |
+
1739
|
| 1741 |
+
1740
|
| 1742 |
+
1741
|
| 1743 |
+
1742
|
| 1744 |
+
1743
|
| 1745 |
+
1744
|
| 1746 |
+
1745
|
| 1747 |
+
1746
|
| 1748 |
+
1747
|
| 1749 |
+
1748
|
| 1750 |
+
1749
|
| 1751 |
+
1750
|
| 1752 |
+
1751
|
| 1753 |
+
1752
|
| 1754 |
+
1753
|
| 1755 |
+
1754
|
| 1756 |
+
1755
|
| 1757 |
+
1756
|
| 1758 |
+
1757
|
| 1759 |
+
1758
|
| 1760 |
+
1759
|
| 1761 |
+
1760
|
| 1762 |
+
1761
|
| 1763 |
+
1762
|
| 1764 |
+
1763
|
| 1765 |
+
1764
|
| 1766 |
+
1765
|
| 1767 |
+
1766
|
| 1768 |
+
1767
|
| 1769 |
+
1768
|
| 1770 |
+
1769
|
| 1771 |
+
1770
|
| 1772 |
+
1771
|
| 1773 |
+
1772
|
| 1774 |
+
1773
|
| 1775 |
+
1774
|
| 1776 |
+
1775
|
| 1777 |
+
1776
|
| 1778 |
+
1777
|
| 1779 |
+
1778
|
| 1780 |
+
1779
|
| 1781 |
+
1780
|
| 1782 |
+
1781
|
| 1783 |
+
1782
|
| 1784 |
+
1783
|
| 1785 |
+
1784
|
| 1786 |
+
1785
|
| 1787 |
+
1786
|
| 1788 |
+
1787
|
| 1789 |
+
1788
|
| 1790 |
+
1789
|
| 1791 |
+
1790
|
| 1792 |
+
1791
|
| 1793 |
+
1792
|
| 1794 |
+
1793
|
| 1795 |
+
1794
|
| 1796 |
+
1795
|
| 1797 |
+
1796
|
| 1798 |
+
1797
|
| 1799 |
+
1798
|
| 1800 |
+
1799
|
| 1801 |
+
1800
|
| 1802 |
+
1801
|
| 1803 |
+
1802
|
| 1804 |
+
1803
|
| 1805 |
+
1804
|
| 1806 |
+
1805
|
| 1807 |
+
1806
|
| 1808 |
+
1807
|
| 1809 |
+
1808
|
| 1810 |
+
1809
|
| 1811 |
+
1810
|
| 1812 |
+
1811
|
| 1813 |
+
1812
|
| 1814 |
+
1813
|
| 1815 |
+
1814
|
| 1816 |
+
1815
|
| 1817 |
+
1816
|
| 1818 |
+
1817
|
| 1819 |
+
1818
|
| 1820 |
+
1819
|
| 1821 |
+
1820
|
| 1822 |
+
1821
|
| 1823 |
+
1822
|
| 1824 |
+
1823
|
| 1825 |
+
1824
|
| 1826 |
+
1825
|
| 1827 |
+
1826
|
| 1828 |
+
1827
|
| 1829 |
+
1828
|
| 1830 |
+
1829
|
| 1831 |
+
1830
|
| 1832 |
+
1831
|
| 1833 |
+
1832
|
| 1834 |
+
1833
|
| 1835 |
+
1834
|
| 1836 |
+
1835
|
| 1837 |
+
1836
|
| 1838 |
+
1837
|
| 1839 |
+
1838
|
| 1840 |
+
1839
|
| 1841 |
+
1840
|
| 1842 |
+
1841
|
| 1843 |
+
1842
|
| 1844 |
+
1843
|
| 1845 |
+
1844
|
| 1846 |
+
1845
|
| 1847 |
+
1846
|
| 1848 |
+
1847
|
| 1849 |
+
1848
|
| 1850 |
+
1849
|
| 1851 |
+
1850
|
| 1852 |
+
1851
|
| 1853 |
+
1852
|
| 1854 |
+
1853
|
| 1855 |
+
1854
|
| 1856 |
+
1855
|
| 1857 |
+
1856
|
| 1858 |
+
1857
|
| 1859 |
+
1858
|
| 1860 |
+
1859
|
| 1861 |
+
1860
|
| 1862 |
+
1861
|
| 1863 |
+
1862
|
| 1864 |
+
1863
|
| 1865 |
+
1864
|
| 1866 |
+
1865
|
| 1867 |
+
1866
|
| 1868 |
+
1867
|
| 1869 |
+
1868
|
| 1870 |
+
1869
|
| 1871 |
+
1870
|
| 1872 |
+
1871
|
| 1873 |
+
1872
|
| 1874 |
+
1873
|
| 1875 |
+
1874
|
| 1876 |
+
1875
|
| 1877 |
+
1876
|
| 1878 |
+
1877
|
| 1879 |
+
1878
|
| 1880 |
+
1879
|
| 1881 |
+
1880
|
| 1882 |
+
1881
|
| 1883 |
+
1882
|
| 1884 |
+
1883
|
| 1885 |
+
1884
|
| 1886 |
+
1885
|
| 1887 |
+
1886
|
| 1888 |
+
1887
|
| 1889 |
+
1888
|
| 1890 |
+
1889
|
| 1891 |
+
1890
|
| 1892 |
+
1891
|
| 1893 |
+
1892
|
| 1894 |
+
1893
|
| 1895 |
+
1894
|
| 1896 |
+
1895
|
| 1897 |
+
1896
|
| 1898 |
+
1897
|
| 1899 |
+
1898
|
| 1900 |
+
1899
|
| 1901 |
+
1900
|
| 1902 |
+
1901
|
| 1903 |
+
1902
|
| 1904 |
+
1903
|
| 1905 |
+
1904
|
| 1906 |
+
1905
|
| 1907 |
+
1906
|
| 1908 |
+
1907
|
| 1909 |
+
1908
|
| 1910 |
+
1909
|
| 1911 |
+
1910
|
| 1912 |
+
1911
|
| 1913 |
+
1912
|
| 1914 |
+
1913
|
| 1915 |
+
1914
|
| 1916 |
+
1915
|
| 1917 |
+
1916
|
| 1918 |
+
1917
|
| 1919 |
+
1918
|
| 1920 |
+
1919
|
| 1921 |
+
1920
|
| 1922 |
+
1921
|
| 1923 |
+
1922
|
| 1924 |
+
1923
|
| 1925 |
+
1924
|
| 1926 |
+
1925
|
| 1927 |
+
1926
|
| 1928 |
+
1927
|
| 1929 |
+
1928
|
| 1930 |
+
1929
|
| 1931 |
+
1930
|
| 1932 |
+
1931
|
| 1933 |
+
1932
|
| 1934 |
+
1933
|
| 1935 |
+
1934
|
| 1936 |
+
1935
|
| 1937 |
+
1936
|
| 1938 |
+
1937
|
| 1939 |
+
1938
|
| 1940 |
+
1939
|
| 1941 |
+
1940
|
| 1942 |
+
1941
|
| 1943 |
+
1942
|
| 1944 |
+
1943
|
| 1945 |
+
1944
|
| 1946 |
+
1945
|
| 1947 |
+
1946
|
| 1948 |
+
1947
|
| 1949 |
+
1948
|
| 1950 |
+
1949
|
| 1951 |
+
1950
|
| 1952 |
+
1951
|
| 1953 |
+
1952
|
| 1954 |
+
1953
|
| 1955 |
+
1954
|
| 1956 |
+
1955
|
| 1957 |
+
1956
|
| 1958 |
+
1957
|
| 1959 |
+
1958
|
| 1960 |
+
1959
|
| 1961 |
+
1960
|
| 1962 |
+
1961
|
| 1963 |
+
1962
|
| 1964 |
+
1963
|
| 1965 |
+
1964
|
| 1966 |
+
1965
|
| 1967 |
+
1966
|
| 1968 |
+
1967
|
| 1969 |
+
1968
|
| 1970 |
+
1969
|
| 1971 |
+
1970
|
| 1972 |
+
1971
|
| 1973 |
+
1972
|
| 1974 |
+
1973
|
| 1975 |
+
1974
|
| 1976 |
+
1975
|
| 1977 |
+
1976
|
| 1978 |
+
1977
|
| 1979 |
+
1978
|
| 1980 |
+
1979
|
| 1981 |
+
1980
|
| 1982 |
+
1981
|
| 1983 |
+
1982
|
| 1984 |
+
1983
|
| 1985 |
+
1984
|
| 1986 |
+
1985
|
| 1987 |
+
1986
|
| 1988 |
+
1987
|
| 1989 |
+
1988
|
| 1990 |
+
1989
|
| 1991 |
+
1990
|
| 1992 |
+
1991
|
| 1993 |
+
1992
|
| 1994 |
+
1993
|
| 1995 |
+
1994
|
| 1996 |
+
1995
|
| 1997 |
+
1996
|
| 1998 |
+
1997
|
| 1999 |
+
1998
|
| 2000 |
+
1999
|
| 2001 |
+
2000
|
| 2002 |
+
2001
|
| 2003 |
+
2002
|
| 2004 |
+
2003
|
| 2005 |
+
2004
|
| 2006 |
+
2005
|
| 2007 |
+
2006
|
| 2008 |
+
2007
|
| 2009 |
+
2008
|
| 2010 |
+
2009
|
| 2011 |
+
2010
|
| 2012 |
+
2011
|
| 2013 |
+
2012
|
| 2014 |
+
2013
|
| 2015 |
+
2014
|
| 2016 |
+
2015
|
| 2017 |
+
2016
|
| 2018 |
+
2017
|
| 2019 |
+
2018
|
| 2020 |
+
2019
|
| 2021 |
+
2020
|
| 2022 |
+
2021
|
| 2023 |
+
2022
|
| 2024 |
+
2023
|
| 2025 |
+
2024
|
| 2026 |
+
2025
|
| 2027 |
+
2026
|
| 2028 |
+
2027
|
| 2029 |
+
2028
|
| 2030 |
+
2029
|
| 2031 |
+
2030
|
| 2032 |
+
2031
|
| 2033 |
+
2032
|
| 2034 |
+
2033
|
| 2035 |
+
2034
|
| 2036 |
+
2035
|
| 2037 |
+
2036
|
| 2038 |
+
2037
|
| 2039 |
+
2038
|
| 2040 |
+
2039
|
| 2041 |
+
2040
|
| 2042 |
+
2041
|
| 2043 |
+
2042
|
| 2044 |
+
2043
|
| 2045 |
+
2044
|
| 2046 |
+
2045
|
| 2047 |
+
2046
|
| 2048 |
+
2047
|
| 2049 |
+
2048
|
| 2050 |
+
2049
|
| 2051 |
+
2050
|
| 2052 |
+
2051
|
| 2053 |
+
2052
|
| 2054 |
+
2053
|
| 2055 |
+
2054
|
| 2056 |
+
2055
|
| 2057 |
+
2056
|
| 2058 |
+
2057
|
| 2059 |
+
2058
|
| 2060 |
+
2059
|
| 2061 |
+
2060
|
| 2062 |
+
2061
|
| 2063 |
+
2062
|
| 2064 |
+
2063
|
| 2065 |
+
2064
|
| 2066 |
+
2065
|
| 2067 |
+
2066
|
| 2068 |
+
2067
|
| 2069 |
+
2068
|
| 2070 |
+
2069
|
| 2071 |
+
2070
|
| 2072 |
+
2071
|
| 2073 |
+
2072
|
| 2074 |
+
2073
|
| 2075 |
+
2074
|
| 2076 |
+
2075
|
| 2077 |
+
2076
|
| 2078 |
+
2077
|
| 2079 |
+
2078
|
| 2080 |
+
2079
|
| 2081 |
+
2080
|
| 2082 |
+
2081
|
| 2083 |
+
2082
|
| 2084 |
+
2083
|
| 2085 |
+
2084
|
| 2086 |
+
2085
|
| 2087 |
+
2086
|
| 2088 |
+
2087
|
| 2089 |
+
2088
|
| 2090 |
+
2089
|
| 2091 |
+
2090
|
| 2092 |
+
2091
|
| 2093 |
+
2092
|
| 2094 |
+
2093
|
| 2095 |
+
2094
|
| 2096 |
+
2095
|
| 2097 |
+
2096
|
| 2098 |
+
2097
|
| 2099 |
+
2098
|
| 2100 |
+
2099
|
| 2101 |
+
2100
|
| 2102 |
+
2101
|
| 2103 |
+
2102
|
| 2104 |
+
2103
|
| 2105 |
+
2104
|
| 2106 |
+
2105
|
| 2107 |
+
2106
|
| 2108 |
+
2107
|
| 2109 |
+
2108
|
| 2110 |
+
2109
|
| 2111 |
+
2110
|
| 2112 |
+
2111
|
| 2113 |
+
2112
|
| 2114 |
+
2113
|
| 2115 |
+
2114
|
| 2116 |
+
2115
|
| 2117 |
+
2116
|
| 2118 |
+
2117
|
| 2119 |
+
2118
|
| 2120 |
+
2119
|
| 2121 |
+
2120
|
| 2122 |
+
2121
|
| 2123 |
+
2122
|
| 2124 |
+
2123
|
| 2125 |
+
2124
|
| 2126 |
+
2125
|
| 2127 |
+
2126
|
| 2128 |
+
2127
|
| 2129 |
+
2128
|
| 2130 |
+
2129
|
| 2131 |
+
2130
|
| 2132 |
+
2131
|
| 2133 |
+
2132
|
| 2134 |
+
2133
|
| 2135 |
+
2134
|
| 2136 |
+
2135
|
| 2137 |
+
2136
|
| 2138 |
+
2137
|
| 2139 |
+
2138
|
| 2140 |
+
2139
|
| 2141 |
+
2140
|
| 2142 |
+
2141
|
| 2143 |
+
2142
|
| 2144 |
+
2143
|
| 2145 |
+
2144
|
| 2146 |
+
2145
|
| 2147 |
+
2146
|
| 2148 |
+
2147
|
| 2149 |
+
2148
|
| 2150 |
+
2149
|
| 2151 |
+
2150
|
| 2152 |
+
2151
|
| 2153 |
+
2152
|
| 2154 |
+
2153
|
| 2155 |
+
2154
|
| 2156 |
+
2155
|
| 2157 |
+
2156
|
| 2158 |
+
2157
|
| 2159 |
+
2158
|
| 2160 |
+
2159
|
| 2161 |
+
2160
|
| 2162 |
+
2161
|
| 2163 |
+
2162
|
| 2164 |
+
2163
|
| 2165 |
+
2164
|
| 2166 |
+
2165
|
| 2167 |
+
2166
|
| 2168 |
+
2167
|
| 2169 |
+
2168
|
| 2170 |
+
2169
|
| 2171 |
+
2170
|
| 2172 |
+
2171
|
| 2173 |
+
2172
|
| 2174 |
+
2173
|
| 2175 |
+
2174
|
| 2176 |
+
2175
|
| 2177 |
+
2176
|
| 2178 |
+
2177
|
| 2179 |
+
2178
|
| 2180 |
+
2179
|
| 2181 |
+
2180
|
| 2182 |
+
2181
|
| 2183 |
+
2182
|
| 2184 |
+
2183
|
| 2185 |
+
2184
|
| 2186 |
+
2185
|
| 2187 |
+
2186
|
| 2188 |
+
2187
|
| 2189 |
+
2188
|
| 2190 |
+
2189
|
| 2191 |
+
2190
|
| 2192 |
+
2191
|
| 2193 |
+
2192
|
| 2194 |
+
2193
|
| 2195 |
+
2194
|
| 2196 |
+
2195
|
| 2197 |
+
2196
|
| 2198 |
+
2197
|
| 2199 |
+
2198
|
| 2200 |
+
2199
|
| 2201 |
+
2200
|
| 2202 |
+
2201
|
| 2203 |
+
2202
|
| 2204 |
+
2203
|
| 2205 |
+
2204
|
| 2206 |
+
2205
|
| 2207 |
+
2206
|
| 2208 |
+
2207
|
| 2209 |
+
2208
|
| 2210 |
+
2209
|
| 2211 |
+
2210
|
| 2212 |
+
2211
|
| 2213 |
+
2212
|
| 2214 |
+
2213
|
| 2215 |
+
2214
|
| 2216 |
+
2215
|
| 2217 |
+
2216
|
| 2218 |
+
2217
|
| 2219 |
+
2218
|
| 2220 |
+
2219
|
| 2221 |
+
2220
|
| 2222 |
+
2221
|
| 2223 |
+
2222
|
| 2224 |
+
2223
|
| 2225 |
+
2224
|
| 2226 |
+
2225
|
| 2227 |
+
2226
|
| 2228 |
+
2227
|
| 2229 |
+
2228
|
| 2230 |
+
2229
|
| 2231 |
+
2230
|
| 2232 |
+
2231
|
| 2233 |
+
2232
|
| 2234 |
+
2233
|
| 2235 |
+
2234
|
| 2236 |
+
2235
|
| 2237 |
+
2236
|
| 2238 |
+
2237
|
| 2239 |
+
2238
|
| 2240 |
+
2239
|
| 2241 |
+
2240
|
| 2242 |
+
2241
|
| 2243 |
+
2242
|
| 2244 |
+
2243
|
| 2245 |
+
2244
|
| 2246 |
+
2245
|
| 2247 |
+
2246
|
| 2248 |
+
2247
|
| 2249 |
+
2248
|
| 2250 |
+
2249
|
| 2251 |
+
2250
|
| 2252 |
+
2251
|
| 2253 |
+
2252
|
| 2254 |
+
2253
|
| 2255 |
+
2254
|
| 2256 |
+
2255
|
| 2257 |
+
2256
|
| 2258 |
+
2257
|
| 2259 |
+
2258
|
| 2260 |
+
2259
|
| 2261 |
+
2260
|
| 2262 |
+
2261
|
| 2263 |
+
2262
|
| 2264 |
+
2263
|
| 2265 |
+
2264
|
| 2266 |
+
2265
|
| 2267 |
+
2266
|
| 2268 |
+
2267
|
| 2269 |
+
2268
|
| 2270 |
+
2269
|
| 2271 |
+
2270
|
| 2272 |
+
2271
|
| 2273 |
+
2272
|
| 2274 |
+
2273
|
| 2275 |
+
2274
|
| 2276 |
+
2275
|
| 2277 |
+
2276
|
| 2278 |
+
2277
|
| 2279 |
+
2278
|
| 2280 |
+
2279
|
| 2281 |
+
2280
|
| 2282 |
+
2281
|
| 2283 |
+
2282
|
| 2284 |
+
2283
|
| 2285 |
+
2284
|
| 2286 |
+
2285
|
| 2287 |
+
2286
|
| 2288 |
+
2287
|
| 2289 |
+
2288
|
| 2290 |
+
2289
|
| 2291 |
+
2290
|
| 2292 |
+
2291
|
| 2293 |
+
2292
|
| 2294 |
+
2293
|
| 2295 |
+
2294
|
| 2296 |
+
2295
|
| 2297 |
+
2296
|
| 2298 |
+
2297
|
| 2299 |
+
2298
|
| 2300 |
+
2299
|
| 2301 |
+
2300
|
| 2302 |
+
2301
|
| 2303 |
+
2302
|
| 2304 |
+
2303
|
| 2305 |
+
2304
|
| 2306 |
+
2305
|
| 2307 |
+
2306
|
| 2308 |
+
2307
|
| 2309 |
+
2308
|
| 2310 |
+
2309
|
| 2311 |
+
2310
|
| 2312 |
+
2311
|
| 2313 |
+
2312
|
| 2314 |
+
2313
|
| 2315 |
+
2314
|
| 2316 |
+
2315
|
| 2317 |
+
2316
|
| 2318 |
+
2317
|
| 2319 |
+
2318
|
| 2320 |
+
2319
|
| 2321 |
+
2320
|
| 2322 |
+
2321
|
| 2323 |
+
2322
|
| 2324 |
+
2323
|
| 2325 |
+
2324
|
| 2326 |
+
2325
|
| 2327 |
+
2326
|
| 2328 |
+
2327
|
| 2329 |
+
2328
|
| 2330 |
+
2329
|
| 2331 |
+
2330
|
| 2332 |
+
2331
|
| 2333 |
+
2332
|
| 2334 |
+
2333
|
| 2335 |
+
2334
|
| 2336 |
+
2335
|
| 2337 |
+
2336
|
| 2338 |
+
2337
|
| 2339 |
+
2338
|
| 2340 |
+
2339
|
| 2341 |
+
2340
|
| 2342 |
+
2341
|
| 2343 |
+
2342
|
| 2344 |
+
2343
|
| 2345 |
+
2344
|
| 2346 |
+
2345
|
| 2347 |
+
2346
|
| 2348 |
+
2347
|
| 2349 |
+
2348
|
| 2350 |
+
2349
|
| 2351 |
+
2350
|
| 2352 |
+
2351
|
| 2353 |
+
2352
|
| 2354 |
+
2353
|
| 2355 |
+
2354
|
| 2356 |
+
2355
|
| 2357 |
+
2356
|
| 2358 |
+
2357
|
| 2359 |
+
2358
|
| 2360 |
+
2359
|
| 2361 |
+
2360
|
| 2362 |
+
2361
|
| 2363 |
+
2362
|
| 2364 |
+
2363
|
| 2365 |
+
2364
|
| 2366 |
+
2365
|
| 2367 |
+
2366
|
| 2368 |
+
2367
|
| 2369 |
+
2368
|
| 2370 |
+
2369
|
| 2371 |
+
2370
|
| 2372 |
+
2371
|
| 2373 |
+
2372
|
| 2374 |
+
2373
|
| 2375 |
+
2374
|
| 2376 |
+
2375
|
| 2377 |
+
2376
|
| 2378 |
+
2377
|
| 2379 |
+
2378
|
| 2380 |
+
2379
|
| 2381 |
+
2380
|
| 2382 |
+
2381
|
| 2383 |
+
2382
|
| 2384 |
+
2383
|
| 2385 |
+
2384
|
| 2386 |
+
2385
|
| 2387 |
+
2386
|
| 2388 |
+
2387
|
| 2389 |
+
2388
|
| 2390 |
+
2389
|
| 2391 |
+
2390
|
| 2392 |
+
2391
|
| 2393 |
+
2392
|
| 2394 |
+
2393
|
| 2395 |
+
2394
|
| 2396 |
+
2395
|
| 2397 |
+
2396
|
| 2398 |
+
2397
|
| 2399 |
+
2398
|
| 2400 |
+
2399
|
| 2401 |
+
2400
|
| 2402 |
+
2401
|
| 2403 |
+
2402
|
| 2404 |
+
2403
|
| 2405 |
+
2404
|
| 2406 |
+
2405
|
| 2407 |
+
2406
|
| 2408 |
+
2407
|
| 2409 |
+
2408
|
| 2410 |
+
2409
|
| 2411 |
+
2410
|
| 2412 |
+
2411
|
| 2413 |
+
2412
|
| 2414 |
+
2413
|
| 2415 |
+
2414
|
| 2416 |
+
2415
|
| 2417 |
+
2416
|
| 2418 |
+
2417
|
| 2419 |
+
2418
|
| 2420 |
+
2419
|
| 2421 |
+
2420
|
| 2422 |
+
2421
|
| 2423 |
+
2422
|
| 2424 |
+
2423
|
| 2425 |
+
2424
|
| 2426 |
+
2425
|
| 2427 |
+
2426
|
| 2428 |
+
2427
|
| 2429 |
+
2428
|
| 2430 |
+
2429
|
| 2431 |
+
2430
|
| 2432 |
+
2431
|
| 2433 |
+
2432
|
| 2434 |
+
2433
|
| 2435 |
+
2434
|
| 2436 |
+
2435
|
| 2437 |
+
2436
|
| 2438 |
+
2437
|
| 2439 |
+
2438
|
| 2440 |
+
2439
|
| 2441 |
+
2440
|
| 2442 |
+
2441
|
| 2443 |
+
2442
|
| 2444 |
+
2443
|
| 2445 |
+
2444
|
| 2446 |
+
2445
|
| 2447 |
+
2446
|
| 2448 |
+
2447
|
| 2449 |
+
2448
|
| 2450 |
+
2449
|
| 2451 |
+
2450
|
| 2452 |
+
2451
|
| 2453 |
+
2452
|
| 2454 |
+
2453
|
| 2455 |
+
2454
|
| 2456 |
+
2455
|
| 2457 |
+
2456
|
| 2458 |
+
2457
|
| 2459 |
+
2458
|
| 2460 |
+
2459
|
| 2461 |
+
2460
|
| 2462 |
+
2461
|
| 2463 |
+
2462
|
| 2464 |
+
2463
|
| 2465 |
+
2464
|
| 2466 |
+
2465
|
| 2467 |
+
2466
|
| 2468 |
+
2467
|
| 2469 |
+
2468
|
| 2470 |
+
2469
|
| 2471 |
+
2470
|
| 2472 |
+
2471
|
| 2473 |
+
2472
|
| 2474 |
+
2473
|
| 2475 |
+
2474
|
| 2476 |
+
2475
|
| 2477 |
+
2476
|
| 2478 |
+
2477
|
| 2479 |
+
2478
|
| 2480 |
+
2479
|
| 2481 |
+
2480
|
| 2482 |
+
2481
|
| 2483 |
+
2482
|
| 2484 |
+
2483
|
| 2485 |
+
2484
|
| 2486 |
+
2485
|
| 2487 |
+
2486
|
| 2488 |
+
2487
|
| 2489 |
+
2488
|
| 2490 |
+
2489
|
| 2491 |
+
2490
|
| 2492 |
+
2491
|
| 2493 |
+
2492
|
| 2494 |
+
2493
|
| 2495 |
+
2494
|
| 2496 |
+
2495
|
| 2497 |
+
2496
|
| 2498 |
+
2497
|
| 2499 |
+
2498
|
| 2500 |
+
2499
|
| 2501 |
+
2500
|
| 2502 |
+
2501
|
| 2503 |
+
2502
|
| 2504 |
+
2503
|
| 2505 |
+
2504
|
| 2506 |
+
2505
|
| 2507 |
+
2506
|
| 2508 |
+
2507
|
| 2509 |
+
2508
|
| 2510 |
+
2509
|
| 2511 |
+
2510
|
| 2512 |
+
2511
|
| 2513 |
+
2512
|
| 2514 |
+
2513
|
| 2515 |
+
2514
|
| 2516 |
+
2515
|
| 2517 |
+
2516
|
| 2518 |
+
2517
|
| 2519 |
+
2518
|
| 2520 |
+
2519
|
| 2521 |
+
2520
|
| 2522 |
+
2521
|
| 2523 |
+
2522
|
| 2524 |
+
2523
|
| 2525 |
+
2524
|
| 2526 |
+
2525
|
| 2527 |
+
2526
|
| 2528 |
+
2527
|
| 2529 |
+
2528
|
| 2530 |
+
2529
|
| 2531 |
+
2530
|
| 2532 |
+
2531
|
| 2533 |
+
2532
|
| 2534 |
+
2533
|
| 2535 |
+
2534
|
| 2536 |
+
2535
|
| 2537 |
+
2536
|
| 2538 |
+
2537
|
| 2539 |
+
2538
|
| 2540 |
+
2539
|
| 2541 |
+
2540
|
| 2542 |
+
2541
|
| 2543 |
+
2542
|
| 2544 |
+
2543
|
| 2545 |
+
2544
|
| 2546 |
+
2545
|
| 2547 |
+
2546
|
| 2548 |
+
2547
|
| 2549 |
+
2548
|
| 2550 |
+
2549
|
| 2551 |
+
2550
|
| 2552 |
+
2551
|
| 2553 |
+
2552
|
| 2554 |
+
2553
|
| 2555 |
+
2554
|
| 2556 |
+
2555
|
| 2557 |
+
2556
|
| 2558 |
+
2557
|
| 2559 |
+
2558
|
| 2560 |
+
2559
|
| 2561 |
+
2560
|
| 2562 |
+
2561
|
| 2563 |
+
2562
|
| 2564 |
+
2563
|
| 2565 |
+
2564
|
| 2566 |
+
2565
|
| 2567 |
+
2566
|
| 2568 |
+
2567
|
| 2569 |
+
2568
|
| 2570 |
+
2569
|
| 2571 |
+
2570
|
| 2572 |
+
2571
|
| 2573 |
+
2572
|
| 2574 |
+
2573
|
| 2575 |
+
2574
|
| 2576 |
+
2575
|
| 2577 |
+
2576
|
| 2578 |
+
2577
|
| 2579 |
+
2578
|
| 2580 |
+
2579
|
| 2581 |
+
2580
|
| 2582 |
+
2581
|
| 2583 |
+
2582
|
| 2584 |
+
2583
|
| 2585 |
+
2584
|
| 2586 |
+
2585
|
| 2587 |
+
2586
|
| 2588 |
+
2587
|
| 2589 |
+
2588
|
| 2590 |
+
2589
|
| 2591 |
+
2590
|
| 2592 |
+
2591
|
| 2593 |
+
2592
|
| 2594 |
+
2593
|
| 2595 |
+
2594
|
| 2596 |
+
2595
|
| 2597 |
+
2596
|
| 2598 |
+
2597
|
| 2599 |
+
2598
|
| 2600 |
+
2599
|
| 2601 |
+
2600
|
| 2602 |
+
2601
|
| 2603 |
+
2602
|
| 2604 |
+
2603
|
| 2605 |
+
2604
|
| 2606 |
+
2605
|
| 2607 |
+
2606
|
| 2608 |
+
2607
|
| 2609 |
+
2608
|
| 2610 |
+
2609
|
| 2611 |
+
2610
|
| 2612 |
+
2611
|
| 2613 |
+
2612
|
| 2614 |
+
2613
|
| 2615 |
+
2614
|
| 2616 |
+
2615
|
| 2617 |
+
2616
|
| 2618 |
+
2617
|
| 2619 |
+
2618
|
| 2620 |
+
2619
|
| 2621 |
+
2620
|
| 2622 |
+
2621
|
| 2623 |
+
2622
|
| 2624 |
+
2623
|
| 2625 |
+
2624
|
| 2626 |
+
2625
|
| 2627 |
+
2626
|
| 2628 |
+
2627
|
| 2629 |
+
2628
|
| 2630 |
+
2629
|
| 2631 |
+
2630
|
| 2632 |
+
2631
|
| 2633 |
+
2632
|
| 2634 |
+
2633
|
| 2635 |
+
2634
|
| 2636 |
+
2635
|
| 2637 |
+
2636
|
| 2638 |
+
2637
|
| 2639 |
+
2638
|
| 2640 |
+
2639
|
| 2641 |
+
2640
|
| 2642 |
+
2641
|
| 2643 |
+
2642
|
| 2644 |
+
2643
|
| 2645 |
+
2644
|
| 2646 |
+
2645
|
| 2647 |
+
2646
|
| 2648 |
+
2647
|
| 2649 |
+
2648
|
| 2650 |
+
2649
|
| 2651 |
+
2650
|
| 2652 |
+
2651
|
| 2653 |
+
2652
|
| 2654 |
+
2653
|
| 2655 |
+
2654
|
| 2656 |
+
2655
|
| 2657 |
+
2656
|
| 2658 |
+
2657
|
| 2659 |
+
2658
|
| 2660 |
+
2659
|
| 2661 |
+
2660
|
| 2662 |
+
2661
|
| 2663 |
+
2662
|
| 2664 |
+
2663
|
| 2665 |
+
2664
|
| 2666 |
+
2665
|
| 2667 |
+
2666
|
| 2668 |
+
2667
|
| 2669 |
+
2668
|
| 2670 |
+
2669
|
| 2671 |
+
2670
|
| 2672 |
+
2671
|
| 2673 |
+
2672
|
| 2674 |
+
2673
|
| 2675 |
+
2674
|
| 2676 |
+
2675
|
| 2677 |
+
2676
|
| 2678 |
+
2677
|
| 2679 |
+
2678
|
| 2680 |
+
2679
|
| 2681 |
+
2680
|
| 2682 |
+
2681
|
| 2683 |
+
2682
|
| 2684 |
+
2683
|
| 2685 |
+
2684
|
| 2686 |
+
2685
|
| 2687 |
+
2686
|
| 2688 |
+
2687
|
| 2689 |
+
2688
|
| 2690 |
+
2689
|
| 2691 |
+
2690
|
| 2692 |
+
2691
|
| 2693 |
+
2692
|
| 2694 |
+
2693
|
| 2695 |
+
2694
|
| 2696 |
+
2695
|
| 2697 |
+
2696
|
| 2698 |
+
2697
|
| 2699 |
+
2698
|
| 2700 |
+
2699
|
| 2701 |
+
2700
|
| 2702 |
+
2701
|
| 2703 |
+
2702
|
| 2704 |
+
2703
|
| 2705 |
+
2704
|
| 2706 |
+
2705
|
| 2707 |
+
2706
|
| 2708 |
+
2707
|
| 2709 |
+
2708
|
| 2710 |
+
2709
|
| 2711 |
+
2710
|
| 2712 |
+
2711
|
| 2713 |
+
2712
|
| 2714 |
+
2713
|
| 2715 |
+
2714
|
| 2716 |
+
2715
|
| 2717 |
+
2716
|
| 2718 |
+
2717
|
| 2719 |
+
2718
|
| 2720 |
+
2719
|
| 2721 |
+
2720
|
| 2722 |
+
2721
|
| 2723 |
+
2722
|
| 2724 |
+
2723
|
| 2725 |
+
2724
|
| 2726 |
+
2725
|
| 2727 |
+
2726
|
| 2728 |
+
2727
|
| 2729 |
+
2728
|
| 2730 |
+
2729
|
| 2731 |
+
2730
|
| 2732 |
+
2731
|
| 2733 |
+
2732
|
| 2734 |
+
2733
|
| 2735 |
+
2734
|
| 2736 |
+
2735
|
| 2737 |
+
2736
|
| 2738 |
+
2737
|
| 2739 |
+
2738
|
| 2740 |
+
2739
|
| 2741 |
+
2740
|
| 2742 |
+
2741
|
| 2743 |
+
2742
|
| 2744 |
+
2743
|
| 2745 |
+
2744
|
| 2746 |
+
2745
|
| 2747 |
+
2746
|
| 2748 |
+
2747
|
| 2749 |
+
2748
|
| 2750 |
+
2749
|
| 2751 |
+
2750
|
| 2752 |
+
2751
|
| 2753 |
+
2752
|
| 2754 |
+
2753
|
| 2755 |
+
2754
|
| 2756 |
+
2755
|
| 2757 |
+
2756
|
| 2758 |
+
2757
|
| 2759 |
+
2758
|
| 2760 |
+
2759
|
| 2761 |
+
2760
|
| 2762 |
+
2761
|
| 2763 |
+
2762
|
| 2764 |
+
2763
|
| 2765 |
+
2764
|
| 2766 |
+
2765
|
| 2767 |
+
2766
|
| 2768 |
+
2767
|
| 2769 |
+
2768
|
| 2770 |
+
2769
|
| 2771 |
+
2770
|
| 2772 |
+
2771
|
| 2773 |
+
2772
|
| 2774 |
+
2773
|
| 2775 |
+
2774
|
| 2776 |
+
2775
|
| 2777 |
+
2776
|
| 2778 |
+
2777
|
| 2779 |
+
2778
|
| 2780 |
+
2779
|
| 2781 |
+
2780
|
| 2782 |
+
2781
|
| 2783 |
+
2782
|
| 2784 |
+
2783
|
| 2785 |
+
2784
|
| 2786 |
+
2785
|
| 2787 |
+
2786
|
| 2788 |
+
2787
|
| 2789 |
+
2788
|
| 2790 |
+
2789
|
| 2791 |
+
2790
|
| 2792 |
+
2791
|
| 2793 |
+
2792
|
| 2794 |
+
2793
|
| 2795 |
+
2794
|
| 2796 |
+
2795
|
| 2797 |
+
2796
|
| 2798 |
+
2797
|
| 2799 |
+
2798
|
| 2800 |
+
2799
|
| 2801 |
+
2800
|
| 2802 |
+
2801
|
| 2803 |
+
2802
|
| 2804 |
+
2803
|
| 2805 |
+
2804
|
| 2806 |
+
2805
|
| 2807 |
+
2806
|
| 2808 |
+
2807
|
| 2809 |
+
2808
|
| 2810 |
+
2809
|
| 2811 |
+
2810
|
| 2812 |
+
2811
|
| 2813 |
+
2812
|
| 2814 |
+
2813
|
| 2815 |
+
2814
|
| 2816 |
+
2815
|
| 2817 |
+
2816
|
| 2818 |
+
2817
|
| 2819 |
+
2818
|
| 2820 |
+
2819
|
| 2821 |
+
2820
|
| 2822 |
+
2821
|
| 2823 |
+
2822
|
| 2824 |
+
2823
|
| 2825 |
+
2824
|
| 2826 |
+
2825
|
| 2827 |
+
2826
|
| 2828 |
+
2827
|
| 2829 |
+
2828
|
| 2830 |
+
2829
|
| 2831 |
+
2830
|
| 2832 |
+
2831
|
| 2833 |
+
2832
|
| 2834 |
+
2833
|
| 2835 |
+
2834
|
| 2836 |
+
2835
|
| 2837 |
+
2836
|
| 2838 |
+
2837
|
| 2839 |
+
2838
|
| 2840 |
+
2839
|
| 2841 |
+
2840
|
| 2842 |
+
2841
|
| 2843 |
+
2842
|
| 2844 |
+
2843
|
| 2845 |
+
2844
|
| 2846 |
+
2845
|
| 2847 |
+
2846
|
| 2848 |
+
2847
|
| 2849 |
+
2848
|
| 2850 |
+
2849
|
| 2851 |
+
2850
|
| 2852 |
+
2851
|
| 2853 |
+
2852
|
| 2854 |
+
2853
|
| 2855 |
+
2854
|
| 2856 |
+
2855
|
| 2857 |
+
2856
|
| 2858 |
+
2857
|
| 2859 |
+
2858
|
| 2860 |
+
2859
|
| 2861 |
+
2860
|
| 2862 |
+
2861
|
| 2863 |
+
2862
|
| 2864 |
+
2863
|
| 2865 |
+
2864
|
| 2866 |
+
2865
|
| 2867 |
+
2866
|
| 2868 |
+
2867
|
| 2869 |
+
2868
|
| 2870 |
+
2869
|
| 2871 |
+
2870
|
| 2872 |
+
2871
|
| 2873 |
+
2872
|
| 2874 |
+
2873
|
| 2875 |
+
2874
|
| 2876 |
+
2875
|
| 2877 |
+
2876
|
| 2878 |
+
2877
|
| 2879 |
+
2878
|
| 2880 |
+
2879
|
| 2881 |
+
2880
|
| 2882 |
+
2881
|
| 2883 |
+
2882
|
| 2884 |
+
2883
|
| 2885 |
+
2884
|
| 2886 |
+
2885
|
| 2887 |
+
2886
|
| 2888 |
+
2887
|
| 2889 |
+
2888
|
| 2890 |
+
2889
|
| 2891 |
+
2890
|
| 2892 |
+
2891
|
| 2893 |
+
2892
|
| 2894 |
+
2893
|
| 2895 |
+
2894
|
| 2896 |
+
2895
|
| 2897 |
+
2896
|
| 2898 |
+
2897
|
| 2899 |
+
2898
|
| 2900 |
+
2899
|
| 2901 |
+
2900
|
| 2902 |
+
2901
|
| 2903 |
+
2902
|
| 2904 |
+
2903
|
| 2905 |
+
2904
|
| 2906 |
+
2905
|
| 2907 |
+
2906
|
| 2908 |
+
2907
|
| 2909 |
+
2908
|
| 2910 |
+
2909
|
| 2911 |
+
2910
|
| 2912 |
+
2911
|
| 2913 |
+
2912
|
| 2914 |
+
2913
|
| 2915 |
+
2914
|
| 2916 |
+
2915
|
| 2917 |
+
2916
|
| 2918 |
+
2917
|
| 2919 |
+
2918
|
| 2920 |
+
2919
|
| 2921 |
+
2920
|
| 2922 |
+
2921
|
| 2923 |
+
2922
|
| 2924 |
+
2923
|
| 2925 |
+
2924
|
| 2926 |
+
2925
|
| 2927 |
+
2926
|
| 2928 |
+
2927
|
| 2929 |
+
2928
|
| 2930 |
+
2929
|
| 2931 |
+
2930
|
| 2932 |
+
2931
|
| 2933 |
+
2932
|
| 2934 |
+
2933
|
| 2935 |
+
2934
|
| 2936 |
+
2935
|
| 2937 |
+
2936
|
| 2938 |
+
2937
|
| 2939 |
+
2938
|
| 2940 |
+
2939
|
| 2941 |
+
2940
|
| 2942 |
+
2941
|
| 2943 |
+
2942
|
| 2944 |
+
2943
|
| 2945 |
+
2944
|
| 2946 |
+
2945
|
| 2947 |
+
2946
|
| 2948 |
+
2947
|
| 2949 |
+
2948
|
| 2950 |
+
2949
|
| 2951 |
+
2950
|
| 2952 |
+
2951
|
| 2953 |
+
2952
|
| 2954 |
+
2953
|
| 2955 |
+
2954
|
| 2956 |
+
2955
|
| 2957 |
+
2956
|
| 2958 |
+
2957
|
| 2959 |
+
2958
|
| 2960 |
+
2959
|
| 2961 |
+
2960
|
| 2962 |
+
2961
|
| 2963 |
+
2962
|
| 2964 |
+
2963
|
| 2965 |
+
2964
|
| 2966 |
+
2965
|
| 2967 |
+
2966
|
| 2968 |
+
2967
|
| 2969 |
+
2968
|
| 2970 |
+
2969
|
| 2971 |
+
2970
|
| 2972 |
+
2971
|
| 2973 |
+
2972
|
| 2974 |
+
2973
|
| 2975 |
+
2974
|
| 2976 |
+
2975
|
| 2977 |
+
2976
|
| 2978 |
+
2977
|
| 2979 |
+
2978
|
| 2980 |
+
2979
|
| 2981 |
+
2980
|
| 2982 |
+
2981
|
| 2983 |
+
2982
|
| 2984 |
+
2983
|
| 2985 |
+
2984
|
| 2986 |
+
2985
|
| 2987 |
+
2986
|
| 2988 |
+
2987
|
| 2989 |
+
2988
|
| 2990 |
+
2989
|
| 2991 |
+
2990
|
| 2992 |
+
2991
|
| 2993 |
+
2992
|
| 2994 |
+
2993
|
| 2995 |
+
2994
|
| 2996 |
+
2995
|
| 2997 |
+
2996
|
| 2998 |
+
2997
|
| 2999 |
+
2998
|
| 3000 |
+
2999
|
coral_seg/splits/val.txt
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0003
|
| 2 |
+
0008
|
| 3 |
+
0010
|
| 4 |
+
0014
|
| 5 |
+
0019
|
| 6 |
+
0024
|
| 7 |
+
0029
|
| 8 |
+
0034
|
| 9 |
+
0035
|
| 10 |
+
0045
|
| 11 |
+
0048
|
| 12 |
+
0053
|
| 13 |
+
0057
|
| 14 |
+
0061
|
| 15 |
+
0062
|
| 16 |
+
0063
|
| 17 |
+
0066
|
| 18 |
+
0079
|
| 19 |
+
0084
|
| 20 |
+
0099
|
| 21 |
+
0104
|
| 22 |
+
0106
|
| 23 |
+
0109
|
| 24 |
+
0112
|
| 25 |
+
0130
|
| 26 |
+
0135
|
| 27 |
+
0136
|
| 28 |
+
0147
|
| 29 |
+
0161
|
| 30 |
+
0167
|
| 31 |
+
0173
|
| 32 |
+
0177
|
| 33 |
+
0196
|
| 34 |
+
0207
|
| 35 |
+
0223
|
| 36 |
+
0226
|
| 37 |
+
0271
|
| 38 |
+
0272
|
| 39 |
+
0276
|
| 40 |
+
0280
|
| 41 |
+
0291
|
| 42 |
+
0301
|
| 43 |
+
0324
|
| 44 |
+
0333
|
| 45 |
+
0335
|
| 46 |
+
0343
|
| 47 |
+
0347
|
| 48 |
+
0348
|
| 49 |
+
0350
|
| 50 |
+
0353
|
| 51 |
+
0354
|
| 52 |
+
0360
|
| 53 |
+
0363
|
| 54 |
+
0369
|
| 55 |
+
0370
|
| 56 |
+
0378
|
| 57 |
+
0380
|
| 58 |
+
0392
|
| 59 |
+
0399
|
| 60 |
+
0412
|
| 61 |
+
0428
|
| 62 |
+
0433
|
| 63 |
+
0435
|
| 64 |
+
0444
|
| 65 |
+
0450
|
| 66 |
+
0462
|
| 67 |
+
0470
|
| 68 |
+
0485
|
| 69 |
+
0489
|
| 70 |
+
0494
|
| 71 |
+
0497
|
| 72 |
+
0499
|
| 73 |
+
0507
|
| 74 |
+
0514
|
| 75 |
+
0527
|
| 76 |
+
0530
|
| 77 |
+
0533
|
| 78 |
+
0541
|
| 79 |
+
0544
|
| 80 |
+
0547
|
| 81 |
+
0552
|
| 82 |
+
0553
|
| 83 |
+
0555
|
| 84 |
+
0570
|
| 85 |
+
0587
|
| 86 |
+
0593
|
| 87 |
+
0612
|
| 88 |
+
0641
|
| 89 |
+
0659
|
| 90 |
+
0670
|
| 91 |
+
0687
|
| 92 |
+
0694
|
| 93 |
+
0695
|
| 94 |
+
0703
|
| 95 |
+
0717
|
| 96 |
+
0720
|
| 97 |
+
0724
|
| 98 |
+
0730
|
| 99 |
+
0738
|
| 100 |
+
0739
|
| 101 |
+
0753
|
| 102 |
+
0757
|
| 103 |
+
0758
|
| 104 |
+
0766
|
| 105 |
+
0767
|
| 106 |
+
0779
|
| 107 |
+
0785
|
| 108 |
+
0788
|
| 109 |
+
0793
|
| 110 |
+
0798
|
| 111 |
+
0808
|
| 112 |
+
0813
|
| 113 |
+
0814
|
| 114 |
+
0815
|
| 115 |
+
0822
|
| 116 |
+
0825
|
| 117 |
+
0830
|
| 118 |
+
0834
|
| 119 |
+
0851
|
| 120 |
+
0853
|
| 121 |
+
0868
|
| 122 |
+
0872
|
| 123 |
+
0882
|
| 124 |
+
0887
|
| 125 |
+
0889
|
| 126 |
+
0894
|
| 127 |
+
0897
|
| 128 |
+
0901
|
| 129 |
+
0906
|
| 130 |
+
0909
|
| 131 |
+
0912
|
| 132 |
+
0915
|
| 133 |
+
0916
|
| 134 |
+
0925
|
| 135 |
+
0926
|
| 136 |
+
0930
|
| 137 |
+
0952
|
| 138 |
+
0953
|
| 139 |
+
0956
|
| 140 |
+
0961
|
| 141 |
+
0965
|
| 142 |
+
0970
|
| 143 |
+
0971
|
| 144 |
+
0977
|
| 145 |
+
0978
|
| 146 |
+
0989
|
| 147 |
+
1020
|
| 148 |
+
1021
|
| 149 |
+
1023
|
| 150 |
+
1045
|
| 151 |
+
1049
|
| 152 |
+
1051
|
| 153 |
+
1052
|
| 154 |
+
1055
|
| 155 |
+
1060
|
| 156 |
+
1064
|
| 157 |
+
1067
|
| 158 |
+
1069
|
| 159 |
+
1079
|
| 160 |
+
1091
|
| 161 |
+
1099
|
| 162 |
+
1102
|
| 163 |
+
1106
|
| 164 |
+
1108
|
| 165 |
+
1110
|
| 166 |
+
1111
|
| 167 |
+
1113
|
| 168 |
+
1118
|
| 169 |
+
1121
|
| 170 |
+
1123
|
| 171 |
+
1124
|
| 172 |
+
1137
|
| 173 |
+
1140
|
| 174 |
+
1141
|
| 175 |
+
1162
|
| 176 |
+
1169
|
| 177 |
+
1170
|
| 178 |
+
1176
|
| 179 |
+
1178
|
| 180 |
+
1180
|
| 181 |
+
1185
|
| 182 |
+
1197
|
| 183 |
+
1199
|
| 184 |
+
1202
|
| 185 |
+
1204
|
| 186 |
+
1206
|
| 187 |
+
1235
|
| 188 |
+
1242
|
| 189 |
+
1251
|
| 190 |
+
1263
|
| 191 |
+
1267
|
| 192 |
+
1284
|
| 193 |
+
1297
|
| 194 |
+
1304
|
| 195 |
+
1331
|
| 196 |
+
1342
|
| 197 |
+
1346
|
| 198 |
+
1352
|
| 199 |
+
1357
|
| 200 |
+
1369
|
| 201 |
+
1375
|
| 202 |
+
1376
|
| 203 |
+
1382
|
| 204 |
+
1383
|
| 205 |
+
1385
|
| 206 |
+
1387
|
| 207 |
+
1389
|
| 208 |
+
1397
|
| 209 |
+
1399
|
| 210 |
+
1412
|
| 211 |
+
1415
|
| 212 |
+
1421
|
| 213 |
+
1423
|
| 214 |
+
1426
|
| 215 |
+
1435
|
| 216 |
+
1436
|
| 217 |
+
1446
|
| 218 |
+
1450
|
| 219 |
+
1486
|
| 220 |
+
1490
|
| 221 |
+
1492
|
| 222 |
+
1495
|
| 223 |
+
1497
|
| 224 |
+
1502
|
| 225 |
+
1509
|
| 226 |
+
1511
|
| 227 |
+
1522
|
| 228 |
+
1523
|
| 229 |
+
1525
|
| 230 |
+
1532
|
| 231 |
+
1536
|
| 232 |
+
1538
|
| 233 |
+
1540
|
| 234 |
+
1541
|
| 235 |
+
1549
|
| 236 |
+
1568
|
| 237 |
+
1571
|
| 238 |
+
1576
|
| 239 |
+
1581
|
| 240 |
+
1584
|
| 241 |
+
1587
|
| 242 |
+
1592
|
| 243 |
+
1604
|
| 244 |
+
1605
|
| 245 |
+
1609
|
| 246 |
+
1615
|
| 247 |
+
1624
|
| 248 |
+
1637
|
| 249 |
+
1639
|
| 250 |
+
1648
|
| 251 |
+
1654
|
| 252 |
+
1667
|
| 253 |
+
1670
|
| 254 |
+
1676
|
| 255 |
+
1680
|
| 256 |
+
1682
|
| 257 |
+
1689
|
| 258 |
+
1701
|
| 259 |
+
1702
|
| 260 |
+
1707
|
| 261 |
+
1710
|
| 262 |
+
1711
|
| 263 |
+
1713
|
| 264 |
+
1717
|
| 265 |
+
1719
|
| 266 |
+
1721
|
| 267 |
+
1724
|
| 268 |
+
1748
|
| 269 |
+
1753
|
| 270 |
+
1755
|
| 271 |
+
1762
|
| 272 |
+
1769
|
| 273 |
+
1773
|
| 274 |
+
1774
|
| 275 |
+
1779
|
| 276 |
+
1780
|
| 277 |
+
1782
|
| 278 |
+
1784
|
| 279 |
+
1793
|
| 280 |
+
1801
|
| 281 |
+
1805
|
| 282 |
+
1808
|
| 283 |
+
1815
|
| 284 |
+
1819
|
| 285 |
+
1841
|
| 286 |
+
1850
|
| 287 |
+
1851
|
| 288 |
+
1853
|
| 289 |
+
1854
|
| 290 |
+
1864
|
| 291 |
+
1865
|
| 292 |
+
1867
|
| 293 |
+
1868
|
| 294 |
+
1869
|
| 295 |
+
1878
|
| 296 |
+
1881
|
| 297 |
+
1888
|
| 298 |
+
1889
|
| 299 |
+
1894
|
| 300 |
+
1906
|
| 301 |
+
1910
|
| 302 |
+
1920
|
| 303 |
+
1939
|
| 304 |
+
1940
|
| 305 |
+
1945
|
| 306 |
+
1949
|
| 307 |
+
1983
|
| 308 |
+
1987
|
| 309 |
+
1990
|
| 310 |
+
1997
|
| 311 |
+
2000
|
| 312 |
+
2008
|
| 313 |
+
2031
|
| 314 |
+
2042
|
| 315 |
+
2050
|
| 316 |
+
2053
|
| 317 |
+
2056
|
| 318 |
+
2061
|
| 319 |
+
2068
|
| 320 |
+
2076
|
| 321 |
+
2091
|
| 322 |
+
2092
|
| 323 |
+
2099
|
| 324 |
+
2113
|
| 325 |
+
2125
|
| 326 |
+
2128
|
| 327 |
+
2146
|
| 328 |
+
2148
|
| 329 |
+
2159
|
| 330 |
+
2169
|
| 331 |
+
2174
|
| 332 |
+
2183
|
| 333 |
+
2188
|
| 334 |
+
2194
|
| 335 |
+
2209
|
| 336 |
+
2230
|
| 337 |
+
2235
|
| 338 |
+
2237
|
| 339 |
+
2243
|
| 340 |
+
2248
|
| 341 |
+
2269
|
| 342 |
+
2277
|
| 343 |
+
2286
|
| 344 |
+
2298
|
| 345 |
+
2300
|
| 346 |
+
2311
|
| 347 |
+
2314
|
| 348 |
+
2328
|
| 349 |
+
2334
|
| 350 |
+
2340
|
| 351 |
+
2344
|
| 352 |
+
2345
|
| 353 |
+
2348
|
| 354 |
+
2351
|
| 355 |
+
2358
|
| 356 |
+
2362
|
| 357 |
+
2372
|
| 358 |
+
2377
|
| 359 |
+
2395
|
| 360 |
+
2397
|
| 361 |
+
2406
|
| 362 |
+
2415
|
| 363 |
+
2416
|
| 364 |
+
2419
|
| 365 |
+
2428
|
| 366 |
+
2430
|
| 367 |
+
2433
|
| 368 |
+
2435
|
| 369 |
+
2437
|
| 370 |
+
2438
|
| 371 |
+
2450
|
| 372 |
+
2453
|
| 373 |
+
2459
|
| 374 |
+
2485
|
| 375 |
+
2492
|
| 376 |
+
2493
|
| 377 |
+
2495
|
| 378 |
+
2503
|
| 379 |
+
2509
|
| 380 |
+
2517
|
| 381 |
+
2526
|
| 382 |
+
2535
|
| 383 |
+
2542
|
| 384 |
+
2569
|
| 385 |
+
2585
|
| 386 |
+
2593
|
| 387 |
+
2597
|
| 388 |
+
2599
|
| 389 |
+
2603
|
| 390 |
+
2609
|
| 391 |
+
2610
|
| 392 |
+
2611
|
| 393 |
+
2613
|
| 394 |
+
2614
|
| 395 |
+
2619
|
| 396 |
+
2627
|
| 397 |
+
2633
|
| 398 |
+
2634
|
| 399 |
+
2635
|
| 400 |
+
2654
|
| 401 |
+
2660
|
| 402 |
+
2671
|
| 403 |
+
2678
|
| 404 |
+
2679
|
| 405 |
+
2681
|
| 406 |
+
2685
|
| 407 |
+
2688
|
| 408 |
+
2708
|
| 409 |
+
2711
|
| 410 |
+
2712
|
| 411 |
+
2724
|
| 412 |
+
2725
|
| 413 |
+
2731
|
| 414 |
+
2739
|
| 415 |
+
2742
|
| 416 |
+
2748
|
| 417 |
+
2754
|
| 418 |
+
2757
|
| 419 |
+
2763
|
| 420 |
+
2773
|
| 421 |
+
2774
|
| 422 |
+
2778
|
| 423 |
+
2779
|
| 424 |
+
2785
|
| 425 |
+
2787
|
| 426 |
+
2801
|
| 427 |
+
2803
|
| 428 |
+
2820
|
| 429 |
+
2821
|
| 430 |
+
2841
|
| 431 |
+
2843
|
| 432 |
+
2849
|
| 433 |
+
2872
|
| 434 |
+
2880
|
| 435 |
+
2894
|
| 436 |
+
2895
|
| 437 |
+
2922
|
| 438 |
+
2924
|
| 439 |
+
2926
|
| 440 |
+
2949
|
| 441 |
+
2961
|
| 442 |
+
2963
|
| 443 |
+
2975
|
| 444 |
+
2976
|
| 445 |
+
2983
|
| 446 |
+
2985
|
| 447 |
+
2986
|
| 448 |
+
2989
|
| 449 |
+
2996
|
| 450 |
+
2997
|
coral_seg/submissions/results.zip
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:19326a534acc1de1c4b4a901d94f11e92699cf347d3e13901f8da343a65c9502
|
| 3 |
+
size 950074
|
coral_seg/tools/__pycache__/check_data.cpython-312.pyc
ADDED
|
Binary file (2.24 kB). View file
|
|
|
coral_seg/tools/__pycache__/create_splits.cpython-312.pyc
ADDED
|
Binary file (1.73 kB). View file
|
|
|
coral_seg/tools/__pycache__/download_pretrained.cpython-312.pyc
ADDED
|
Binary file (2.03 kB). View file
|
|
|
coral_seg/tools/__pycache__/eval_ensemble_val.cpython-312.pyc
ADDED
|
Binary file (5.45 kB). View file
|
|
|
coral_seg/tools/__pycache__/eval_predictions.cpython-312.pyc
ADDED
|
Binary file (7.2 kB). View file
|
|
|
coral_seg/tools/__pycache__/infer_ensemble.cpython-312.pyc
ADDED
|
Binary file (10.4 kB). View file
|
|
|
coral_seg/tools/__pycache__/train_convnext.cpython-312.pyc
ADDED
|
Binary file (11.2 kB). View file
|
|
|
coral_seg/tools/__pycache__/train_mask2former.cpython-312.pyc
ADDED
|
Binary file (13.7 kB). View file
|
|
|
coral_seg/tools/__pycache__/visualize_results.cpython-312.pyc
ADDED
|
Binary file (6.51 kB). View file
|
|
|
coral_seg/tools/check_data.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import sys
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
from PIL import Image
|
| 7 |
+
|
| 8 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 9 |
+
sys.path.insert(0, str(ROOT))
|
| 10 |
+
|
| 11 |
+
from coral_seg.utils import list_pngs, load_config
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def main() -> None:
|
| 15 |
+
parser = argparse.ArgumentParser()
|
| 16 |
+
parser.add_argument("--config", default=str(ROOT / "configs/final_dual.yaml"))
|
| 17 |
+
args = parser.parse_args()
|
| 18 |
+
cfg = load_config(args.config)
|
| 19 |
+
for key in ("train_images", "train_masks", "test_images"):
|
| 20 |
+
paths = list_pngs(cfg["data"][key])
|
| 21 |
+
print(key, len(paths), paths[0].name if paths else None, paths[-1].name if paths else None)
|
| 22 |
+
values = set()
|
| 23 |
+
bad = []
|
| 24 |
+
for path in list_pngs(cfg["data"]["train_masks"]):
|
| 25 |
+
arr = np.array(Image.open(path))
|
| 26 |
+
unique = set(np.unique(arr).tolist())
|
| 27 |
+
values |= unique
|
| 28 |
+
if not unique <= {0, 1, 2, 3}:
|
| 29 |
+
bad.append((path.name, sorted(unique)))
|
| 30 |
+
print("mask values:", sorted(values))
|
| 31 |
+
print("bad masks:", len(bad), bad[:5])
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
if __name__ == "__main__":
|
| 35 |
+
main()
|
coral_seg/tools/create_splits.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import sys
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 6 |
+
sys.path.insert(0, str(ROOT))
|
| 7 |
+
|
| 8 |
+
from coral_seg.splits import create_split_files
|
| 9 |
+
from coral_seg.utils import load_config
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def main() -> None:
|
| 13 |
+
parser = argparse.ArgumentParser()
|
| 14 |
+
parser.add_argument("--config", default=str(ROOT / "configs/final_dual.yaml"))
|
| 15 |
+
args = parser.parse_args()
|
| 16 |
+
|
| 17 |
+
cfg = load_config(args.config)
|
| 18 |
+
train_file, val_file, full_file = create_split_files(
|
| 19 |
+
cfg["data"]["train_images"],
|
| 20 |
+
cfg["data"]["train_masks"],
|
| 21 |
+
cfg["data"]["split_dir"],
|
| 22 |
+
val_ratio=float(cfg["data"].get("val_ratio", 0.15)),
|
| 23 |
+
seed=int(cfg.get("seed", 2026)),
|
| 24 |
+
)
|
| 25 |
+
print(f"train split: {train_file}")
|
| 26 |
+
print(f"val split: {val_file}")
|
| 27 |
+
print(f"full split: {full_file}")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
if __name__ == "__main__":
|
| 31 |
+
main()
|
coral_seg/tools/download_pretrained.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import shutil
|
| 3 |
+
import sys
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
|
| 8 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 9 |
+
sys.path.insert(0, str(ROOT))
|
| 10 |
+
|
| 11 |
+
from huggingface_hub import snapshot_download
|
| 12 |
+
from torchvision.models import ConvNeXt_Large_Weights, convnext_large
|
| 13 |
+
|
| 14 |
+
from coral_seg.utils import ensure_dir, load_config
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def main() -> None:
|
| 18 |
+
parser = argparse.ArgumentParser()
|
| 19 |
+
parser.add_argument("--config", default=str(ROOT / "configs/final_dual.yaml"))
|
| 20 |
+
args = parser.parse_args()
|
| 21 |
+
|
| 22 |
+
cfg = load_config(args.config)
|
| 23 |
+
mask2former_dir = Path(cfg["mask2former"]["pretrained_dir"])
|
| 24 |
+
ensure_dir(mask2former_dir.parent)
|
| 25 |
+
has_mask2former_weight = (mask2former_dir / "model.safetensors").is_file() or (mask2former_dir / "pytorch_model.bin").is_file()
|
| 26 |
+
has_mask2former_config = (mask2former_dir / "config.json").is_file() and (mask2former_dir / "preprocessor_config.json").is_file()
|
| 27 |
+
if has_mask2former_weight and has_mask2former_config:
|
| 28 |
+
print(f"Mask2Former local files already exist: {mask2former_dir}")
|
| 29 |
+
else:
|
| 30 |
+
print("Downloading Mask2Former-Swin-B from HuggingFace cache/source...")
|
| 31 |
+
snapshot_download(
|
| 32 |
+
repo_id=cfg["mask2former"]["pretrained_name"],
|
| 33 |
+
local_dir=mask2former_dir,
|
| 34 |
+
local_dir_use_symlinks=False,
|
| 35 |
+
)
|
| 36 |
+
print(f"Mask2Former saved to {mask2former_dir}")
|
| 37 |
+
|
| 38 |
+
convnext_path = Path(cfg["convnext"].get("pretrained_path", ROOT / "pretrained/convnext_large-ea097f82.pth"))
|
| 39 |
+
ensure_dir(convnext_path.parent)
|
| 40 |
+
if convnext_path.is_file():
|
| 41 |
+
print(f"ConvNeXt-L local weight already exists: {convnext_path}")
|
| 42 |
+
else:
|
| 43 |
+
print("Downloading torchvision ConvNeXt-L ImageNet-1K weights...")
|
| 44 |
+
_ = convnext_large(weights=ConvNeXt_Large_Weights.IMAGENET1K_V1)
|
| 45 |
+
cache_name = Path(ConvNeXt_Large_Weights.IMAGENET1K_V1.url).name
|
| 46 |
+
cache_path = Path(torch.hub.get_dir()) / "checkpoints" / cache_name
|
| 47 |
+
if not cache_path.is_file():
|
| 48 |
+
raise FileNotFoundError(f"torchvision cache weight not found: {cache_path}")
|
| 49 |
+
shutil.copy2(cache_path, convnext_path)
|
| 50 |
+
print(f"ConvNeXt-L local weight saved to {convnext_path}")
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
if __name__ == "__main__":
|
| 54 |
+
main()
|
coral_seg/tools/eval_ensemble_val.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import sys
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
import torch
|
| 7 |
+
from PIL import Image
|
| 8 |
+
|
| 9 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 10 |
+
sys.path.insert(0, str(ROOT))
|
| 11 |
+
|
| 12 |
+
from coral_seg.utils import compute_iou, fast_hist, format_metrics, load_config, read_image, set_seed
|
| 13 |
+
from coral_seg.splits import read_ids
|
| 14 |
+
from tools.infer_ensemble import load_convnext, load_mask2former, predict_convnext, predict_mask2former
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def main() -> None:
|
| 18 |
+
parser = argparse.ArgumentParser()
|
| 19 |
+
parser.add_argument('--config', default=str(ROOT / 'configs/final_dual.yaml'))
|
| 20 |
+
parser.add_argument('--convnext-checkpoint', default='')
|
| 21 |
+
parser.add_argument('--mask2former-checkpoint', default='')
|
| 22 |
+
parser.add_argument('--split-file', default='')
|
| 23 |
+
parser.add_argument('--max-samples', type=int, default=0)
|
| 24 |
+
args = parser.parse_args()
|
| 25 |
+
|
| 26 |
+
cfg = load_config(args.config)
|
| 27 |
+
set_seed(int(cfg.get('seed', 2026)))
|
| 28 |
+
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
| 29 |
+
infer_cfg = cfg['infer']
|
| 30 |
+
num_classes = int(cfg['num_classes'])
|
| 31 |
+
|
| 32 |
+
conv_model = load_convnext(args.convnext_checkpoint, cfg, device) if args.convnext_checkpoint else None
|
| 33 |
+
mask_model = load_mask2former(args.mask2former_checkpoint, cfg, device) if args.mask2former_checkpoint else None
|
| 34 |
+
if conv_model is None and mask_model is None:
|
| 35 |
+
raise ValueError('Provide --convnext-checkpoint and/or --mask2former-checkpoint')
|
| 36 |
+
|
| 37 |
+
conv_w = float(infer_cfg.get('convnext_weight', 0.45)) if conv_model is not None else 0.0
|
| 38 |
+
mask_w = float(infer_cfg.get('mask2former_weight', 0.55)) if mask_model is not None else 0.0
|
| 39 |
+
norm = max(1e-6, conv_w + mask_w)
|
| 40 |
+
conv_w /= norm
|
| 41 |
+
mask_w /= norm
|
| 42 |
+
flips = list(infer_cfg.get('tta_flips', ['none']))
|
| 43 |
+
|
| 44 |
+
split_file = args.split_file or str(Path(cfg['data']['split_dir']) / 'val.txt')
|
| 45 |
+
ids = read_ids(split_file)
|
| 46 |
+
if args.max_samples > 0:
|
| 47 |
+
ids = ids[:args.max_samples]
|
| 48 |
+
|
| 49 |
+
hist = np.zeros((num_classes, num_classes), dtype=np.int64)
|
| 50 |
+
image_dir = Path(cfg['data']['train_images'])
|
| 51 |
+
mask_dir = Path(cfg['data']['train_masks'])
|
| 52 |
+
|
| 53 |
+
for idx, sample_id in enumerate(ids, start=1):
|
| 54 |
+
image_path = image_dir / f'{sample_id}.png'
|
| 55 |
+
mask_path = mask_dir / f'{sample_id}.png'
|
| 56 |
+
image = read_image(image_path)
|
| 57 |
+
target = np.array(Image.open(mask_path), dtype=np.uint8)
|
| 58 |
+
total = None
|
| 59 |
+
if conv_model is not None:
|
| 60 |
+
probs = predict_convnext(
|
| 61 |
+
conv_model,
|
| 62 |
+
image,
|
| 63 |
+
infer_cfg.get('convnext_sizes', [cfg['convnext']['image_size']]),
|
| 64 |
+
flips,
|
| 65 |
+
num_classes,
|
| 66 |
+
device,
|
| 67 |
+
)
|
| 68 |
+
total = conv_w * probs if total is None else total + conv_w * probs
|
| 69 |
+
if mask_model is not None:
|
| 70 |
+
probs = predict_mask2former(
|
| 71 |
+
mask_model,
|
| 72 |
+
image,
|
| 73 |
+
infer_cfg.get('mask2former_sizes', [cfg['mask2former']['image_size']]),
|
| 74 |
+
flips,
|
| 75 |
+
num_classes,
|
| 76 |
+
device,
|
| 77 |
+
)
|
| 78 |
+
total = mask_w * probs if total is None else total + mask_w * probs
|
| 79 |
+
pred = total.argmax(dim=1).squeeze(0).cpu().numpy().astype(np.uint8)
|
| 80 |
+
hist += fast_hist(pred, target, num_classes)
|
| 81 |
+
if idx % 50 == 0 or idx == len(ids):
|
| 82 |
+
iou, miou = compute_iou(hist)
|
| 83 |
+
print(f'evaluated {idx}/{len(ids)} {format_metrics(iou, miou, cfg["class_names"])}')
|
| 84 |
+
|
| 85 |
+
iou, miou = compute_iou(hist)
|
| 86 |
+
print('final', format_metrics(iou, miou, cfg['class_names']))
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
if __name__ == '__main__':
|
| 90 |
+
main()
|
coral_seg/tools/eval_predictions.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from typing import Dict, Tuple
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
from PIL import Image
|
| 7 |
+
|
| 8 |
+
CLASS_NAMES = ['background', 'live_coral', 'dead_coral', 'bleached_coral']
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def parse_color_map(text: str) -> Dict[Tuple[int, int, int], int]:
|
| 12 |
+
mapping = {}
|
| 13 |
+
if not text:
|
| 14 |
+
return mapping
|
| 15 |
+
for item in text.split(';'):
|
| 16 |
+
item = item.strip()
|
| 17 |
+
if not item:
|
| 18 |
+
continue
|
| 19 |
+
color, label = item.split(':')
|
| 20 |
+
rgb = tuple(int(x) for x in color.split(','))
|
| 21 |
+
if len(rgb) != 3:
|
| 22 |
+
raise ValueError(f'Bad RGB color: {color}')
|
| 23 |
+
mapping[rgb] = int(label)
|
| 24 |
+
return mapping
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def read_pred(path: Path) -> np.ndarray:
|
| 28 |
+
arr = np.array(Image.open(path))
|
| 29 |
+
if arr.ndim == 3:
|
| 30 |
+
arr = arr[:, :, 0]
|
| 31 |
+
return arr.astype(np.uint8)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def read_gt(path: Path, color_map: Dict[Tuple[int, int, int], int]) -> np.ndarray:
|
| 35 |
+
arr = np.array(Image.open(path))
|
| 36 |
+
if arr.ndim == 2:
|
| 37 |
+
return arr.astype(np.uint8)
|
| 38 |
+
if not color_map:
|
| 39 |
+
colors = np.unique(arr.reshape(-1, arr.shape[-1])[:, :3], axis=0)
|
| 40 |
+
raise ValueError(
|
| 41 |
+
'GT is RGB. Provide --color-map, for example '
|
| 42 |
+
'"0,0,0:0;0,162,232:1;240,110,170:2". '
|
| 43 |
+
f'Found colors: {colors.tolist()}'
|
| 44 |
+
)
|
| 45 |
+
rgb = arr[:, :, :3]
|
| 46 |
+
out = np.full(rgb.shape[:2], 255, dtype=np.uint8)
|
| 47 |
+
for color, label in color_map.items():
|
| 48 |
+
out[np.all(rgb == np.array(color, dtype=np.uint8), axis=-1)] = label
|
| 49 |
+
unknown = out == 255
|
| 50 |
+
if unknown.any():
|
| 51 |
+
colors = np.unique(rgb[unknown].reshape(-1, 3), axis=0)
|
| 52 |
+
raise ValueError(f'Unknown GT colors: {colors.tolist()}')
|
| 53 |
+
return out
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def fast_hist(pred: np.ndarray, target: np.ndarray, num_classes: int) -> np.ndarray:
|
| 57 |
+
pred = pred.reshape(-1)
|
| 58 |
+
target = target.reshape(-1)
|
| 59 |
+
valid = (target >= 0) & (target < num_classes)
|
| 60 |
+
hist = np.bincount(num_classes * target[valid].astype(np.int64) + pred[valid].astype(np.int64), minlength=num_classes**2)
|
| 61 |
+
return hist.reshape(num_classes, num_classes)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def main() -> None:
|
| 65 |
+
parser = argparse.ArgumentParser()
|
| 66 |
+
parser.add_argument('--pred-dir', default='/root/autodl-tmp/coral/coral_seg/submissions/results')
|
| 67 |
+
parser.add_argument('--gt-dir', required=True)
|
| 68 |
+
parser.add_argument('--color-map', default='')
|
| 69 |
+
parser.add_argument('--num-classes', type=int, default=4)
|
| 70 |
+
args = parser.parse_args()
|
| 71 |
+
|
| 72 |
+
pred_dir = Path(args.pred_dir)
|
| 73 |
+
gt_dir = Path(args.gt_dir)
|
| 74 |
+
color_map = parse_color_map(args.color_map)
|
| 75 |
+
hist = np.zeros((args.num_classes, args.num_classes), dtype=np.int64)
|
| 76 |
+
count = 0
|
| 77 |
+
for pred_path in sorted(pred_dir.glob('*.png')):
|
| 78 |
+
gt_path = gt_dir / pred_path.name
|
| 79 |
+
if not gt_path.exists():
|
| 80 |
+
continue
|
| 81 |
+
pred = read_pred(pred_path)
|
| 82 |
+
gt = read_gt(gt_path, color_map)
|
| 83 |
+
if pred.shape != gt.shape:
|
| 84 |
+
raise ValueError(f'Shape mismatch for {pred_path.name}: pred={pred.shape}, gt={gt.shape}')
|
| 85 |
+
hist += fast_hist(pred, gt, args.num_classes)
|
| 86 |
+
count += 1
|
| 87 |
+
if count == 0:
|
| 88 |
+
raise RuntimeError('No matched prediction/GT PNG files found')
|
| 89 |
+
denom = hist.sum(1) + hist.sum(0) - np.diag(hist)
|
| 90 |
+
iou = np.divide(np.diag(hist), denom, out=np.full(args.num_classes, np.nan, dtype=np.float64), where=denom != 0)
|
| 91 |
+
print('matched_files:', count)
|
| 92 |
+
print('mIoU:', float(np.nanmean(iou)))
|
| 93 |
+
for idx, value in enumerate(iou):
|
| 94 |
+
name = CLASS_NAMES[idx] if idx < len(CLASS_NAMES) else f'class_{idx}'
|
| 95 |
+
print(f'{idx} {name}: {value}')
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
if __name__ == '__main__':
|
| 99 |
+
main()
|
coral_seg/tools/infer_ensemble.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import sys
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from typing import Dict, Iterable, List, Optional
|
| 5 |
+
|
| 6 |
+
import cv2
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
from PIL import Image
|
| 11 |
+
from transformers import Mask2FormerForUniversalSegmentation
|
| 12 |
+
|
| 13 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 14 |
+
sys.path.insert(0, str(ROOT))
|
| 15 |
+
|
| 16 |
+
from coral_seg.model_convnext_fpn import ConvNeXtFPN
|
| 17 |
+
from coral_seg.utils import (
|
| 18 |
+
ensure_dir,
|
| 19 |
+
list_pngs,
|
| 20 |
+
load_config,
|
| 21 |
+
make_results_zip,
|
| 22 |
+
normalize_tensor,
|
| 23 |
+
read_image,
|
| 24 |
+
save_mask,
|
| 25 |
+
set_seed,
|
| 26 |
+
timestamp,
|
| 27 |
+
)
|
| 28 |
+
from tools.train_mask2former import semantic_logits_from_mask2former
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def apply_flip_tensor(x: torch.Tensor, flip: str) -> torch.Tensor:
|
| 32 |
+
if flip == "h":
|
| 33 |
+
return torch.flip(x, dims=[-1])
|
| 34 |
+
if flip == "v":
|
| 35 |
+
return torch.flip(x, dims=[-2])
|
| 36 |
+
if flip == "hv":
|
| 37 |
+
return torch.flip(x, dims=[-2, -1])
|
| 38 |
+
return x
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def resize_normalize(image: np.ndarray, size: int) -> torch.Tensor:
|
| 42 |
+
resized = cv2.resize(image, (size, size), interpolation=cv2.INTER_LINEAR)
|
| 43 |
+
return normalize_tensor(resized).unsqueeze(0)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def load_convnext(checkpoint: str, cfg: Dict, device: torch.device) -> ConvNeXtFPN:
|
| 47 |
+
model = ConvNeXtFPN(num_classes=int(cfg["num_classes"]), pretrained=False)
|
| 48 |
+
ckpt = torch.load(checkpoint, map_location="cpu")
|
| 49 |
+
model.load_state_dict(ckpt["model"], strict=True)
|
| 50 |
+
return model.to(device).eval()
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def load_mask2former(path_or_ckpt: str, cfg: Dict, device: torch.device) -> Mask2FormerForUniversalSegmentation:
|
| 54 |
+
path = Path(path_or_ckpt)
|
| 55 |
+
if path.is_dir():
|
| 56 |
+
model = Mask2FormerForUniversalSegmentation.from_pretrained(path)
|
| 57 |
+
else:
|
| 58 |
+
mcfg = cfg["mask2former"]
|
| 59 |
+
base = mcfg.get("pretrained_dir") if Path(str(mcfg.get("pretrained_dir", ""))).exists() else mcfg["pretrained_name"]
|
| 60 |
+
model = Mask2FormerForUniversalSegmentation.from_pretrained(
|
| 61 |
+
base,
|
| 62 |
+
num_labels=int(cfg["num_classes"]),
|
| 63 |
+
ignore_mismatched_sizes=True,
|
| 64 |
+
)
|
| 65 |
+
ckpt = torch.load(path_or_ckpt, map_location="cpu")
|
| 66 |
+
model.load_state_dict(ckpt["model"], strict=True)
|
| 67 |
+
return model.to(device).eval()
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
@torch.no_grad()
|
| 71 |
+
def predict_convnext(
|
| 72 |
+
model: ConvNeXtFPN,
|
| 73 |
+
image: np.ndarray,
|
| 74 |
+
sizes: Iterable[int],
|
| 75 |
+
flips: Iterable[str],
|
| 76 |
+
num_classes: int,
|
| 77 |
+
device: torch.device,
|
| 78 |
+
) -> torch.Tensor:
|
| 79 |
+
h, w = image.shape[:2]
|
| 80 |
+
probs_sum = torch.zeros((1, num_classes, h, w), device=device)
|
| 81 |
+
count = 0
|
| 82 |
+
for size in sizes:
|
| 83 |
+
x = resize_normalize(image, int(size)).to(device)
|
| 84 |
+
for flip in flips:
|
| 85 |
+
xf = apply_flip_tensor(x, flip)
|
| 86 |
+
logits = model(xf)
|
| 87 |
+
logits = apply_flip_tensor(logits, flip)
|
| 88 |
+
logits = F.interpolate(logits, size=(h, w), mode="bilinear", align_corners=False)
|
| 89 |
+
probs_sum += torch.softmax(logits, dim=1)
|
| 90 |
+
count += 1
|
| 91 |
+
return probs_sum / max(1, count)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
@torch.no_grad()
|
| 95 |
+
def predict_mask2former(
|
| 96 |
+
model: Mask2FormerForUniversalSegmentation,
|
| 97 |
+
image: np.ndarray,
|
| 98 |
+
sizes: Iterable[int],
|
| 99 |
+
flips: Iterable[str],
|
| 100 |
+
num_classes: int,
|
| 101 |
+
device: torch.device,
|
| 102 |
+
) -> torch.Tensor:
|
| 103 |
+
h, w = image.shape[:2]
|
| 104 |
+
probs_sum = torch.zeros((1, num_classes, h, w), device=device)
|
| 105 |
+
count = 0
|
| 106 |
+
for size in sizes:
|
| 107 |
+
x = resize_normalize(image, int(size)).to(device)
|
| 108 |
+
for flip in flips:
|
| 109 |
+
xf = apply_flip_tensor(x, flip)
|
| 110 |
+
outputs = model(pixel_values=xf)
|
| 111 |
+
logits = semantic_logits_from_mask2former(outputs, target_size=(h, w))
|
| 112 |
+
logits = apply_flip_tensor(logits, flip)
|
| 113 |
+
probs_sum += torch.softmax(logits, dim=1)
|
| 114 |
+
count += 1
|
| 115 |
+
return probs_sum / max(1, count)
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def main() -> None:
|
| 119 |
+
parser = argparse.ArgumentParser()
|
| 120 |
+
parser.add_argument("--config", default=str(ROOT / "configs/final_dual.yaml"))
|
| 121 |
+
parser.add_argument("--convnext-checkpoint", default="")
|
| 122 |
+
parser.add_argument("--mask2former-checkpoint", default="")
|
| 123 |
+
parser.add_argument("--test-dir", default="")
|
| 124 |
+
parser.add_argument("--out-dir", default="")
|
| 125 |
+
parser.add_argument("--zip-path", default="")
|
| 126 |
+
parser.add_argument("--no-zip", action="store_true")
|
| 127 |
+
args = parser.parse_args()
|
| 128 |
+
|
| 129 |
+
cfg = load_config(args.config)
|
| 130 |
+
set_seed(int(cfg.get("seed", 2026)))
|
| 131 |
+
infer_cfg = cfg["infer"]
|
| 132 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 133 |
+
test_dir = args.test_dir or cfg["data"]["test_images"]
|
| 134 |
+
out_dir = ensure_dir(args.out_dir or infer_cfg["out_dir"])
|
| 135 |
+
num_classes = int(cfg["num_classes"])
|
| 136 |
+
|
| 137 |
+
conv_model = None
|
| 138 |
+
mask_model = None
|
| 139 |
+
if args.convnext_checkpoint:
|
| 140 |
+
conv_model = load_convnext(args.convnext_checkpoint, cfg, device)
|
| 141 |
+
if args.mask2former_checkpoint:
|
| 142 |
+
mask_model = load_mask2former(args.mask2former_checkpoint, cfg, device)
|
| 143 |
+
if conv_model is None and mask_model is None:
|
| 144 |
+
raise ValueError("Provide at least one checkpoint: --convnext-checkpoint or --mask2former-checkpoint")
|
| 145 |
+
|
| 146 |
+
conv_w = float(infer_cfg.get("convnext_weight", 0.45)) if conv_model is not None else 0.0
|
| 147 |
+
mask_w = float(infer_cfg.get("mask2former_weight", 0.55)) if mask_model is not None else 0.0
|
| 148 |
+
norm = max(1e-6, conv_w + mask_w)
|
| 149 |
+
conv_w /= norm
|
| 150 |
+
mask_w /= norm
|
| 151 |
+
flips = list(infer_cfg.get("tta_flips", ["none"]))
|
| 152 |
+
|
| 153 |
+
image_paths = list_pngs(test_dir)
|
| 154 |
+
for idx, image_path in enumerate(image_paths, start=1):
|
| 155 |
+
image = read_image(image_path)
|
| 156 |
+
total = None
|
| 157 |
+
if conv_model is not None:
|
| 158 |
+
probs = predict_convnext(
|
| 159 |
+
conv_model,
|
| 160 |
+
image,
|
| 161 |
+
infer_cfg.get("convnext_sizes", [cfg["convnext"]["image_size"]]),
|
| 162 |
+
flips,
|
| 163 |
+
num_classes,
|
| 164 |
+
device,
|
| 165 |
+
)
|
| 166 |
+
total = conv_w * probs if total is None else total + conv_w * probs
|
| 167 |
+
if mask_model is not None:
|
| 168 |
+
probs = predict_mask2former(
|
| 169 |
+
mask_model,
|
| 170 |
+
image,
|
| 171 |
+
infer_cfg.get("mask2former_sizes", [cfg["mask2former"]["image_size"]]),
|
| 172 |
+
flips,
|
| 173 |
+
num_classes,
|
| 174 |
+
device,
|
| 175 |
+
)
|
| 176 |
+
total = mask_w * probs if total is None else total + mask_w * probs
|
| 177 |
+
pred = total.argmax(dim=1).squeeze(0).cpu().numpy().astype(np.uint8)
|
| 178 |
+
save_mask(out_dir / image_path.name, pred)
|
| 179 |
+
if idx % 50 == 0 or idx == len(image_paths):
|
| 180 |
+
print(f"{timestamp()} inferred {idx}/{len(image_paths)}")
|
| 181 |
+
|
| 182 |
+
if not args.no_zip:
|
| 183 |
+
zip_path = args.zip_path or infer_cfg["zip_path"]
|
| 184 |
+
make_results_zip(out_dir, zip_path)
|
| 185 |
+
print(f"saved zip: {zip_path}")
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
if __name__ == "__main__":
|
| 189 |
+
main()
|
coral_seg/tools/train_convnext.py
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import functools
|
| 3 |
+
import sys
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from typing import Dict
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
from torch.cuda.amp import GradScaler, autocast
|
| 11 |
+
from torch.optim import AdamW
|
| 12 |
+
from torch.optim.lr_scheduler import LambdaLR
|
| 13 |
+
from torch.utils.data import DataLoader
|
| 14 |
+
|
| 15 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 16 |
+
sys.path.insert(0, str(ROOT))
|
| 17 |
+
|
| 18 |
+
from coral_seg.dataset import CoralSegDataset, build_train_transform, build_val_transform, segmentation_collate
|
| 19 |
+
from coral_seg.losses import ComboSegLoss
|
| 20 |
+
from coral_seg.model_convnext_fpn import ConvNeXtFPN
|
| 21 |
+
from coral_seg.splits import create_split_files
|
| 22 |
+
from coral_seg.utils import (
|
| 23 |
+
AverageMeter,
|
| 24 |
+
compute_iou,
|
| 25 |
+
cosine_warmup_lambda,
|
| 26 |
+
ensure_dir,
|
| 27 |
+
fast_hist,
|
| 28 |
+
format_metrics,
|
| 29 |
+
load_config,
|
| 30 |
+
save_json,
|
| 31 |
+
set_seed,
|
| 32 |
+
timestamp,
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def build_loaders(cfg: Dict, image_size: int, batch_size: int, full_train: bool) -> tuple[DataLoader, DataLoader | None]:
|
| 37 |
+
data_cfg = cfg["data"]
|
| 38 |
+
train_file, val_file, full_file = create_split_files(
|
| 39 |
+
data_cfg["train_images"],
|
| 40 |
+
data_cfg["train_masks"],
|
| 41 |
+
data_cfg["split_dir"],
|
| 42 |
+
val_ratio=float(data_cfg.get("val_ratio", 0.15)),
|
| 43 |
+
seed=int(cfg.get("seed", 2026)),
|
| 44 |
+
)
|
| 45 |
+
split_file = full_file if full_train else train_file
|
| 46 |
+
train_ds = CoralSegDataset(
|
| 47 |
+
data_cfg["train_images"],
|
| 48 |
+
data_cfg["train_masks"],
|
| 49 |
+
str(split_file),
|
| 50 |
+
build_train_transform(image_size),
|
| 51 |
+
)
|
| 52 |
+
train_loader = DataLoader(
|
| 53 |
+
train_ds,
|
| 54 |
+
batch_size=batch_size,
|
| 55 |
+
shuffle=True,
|
| 56 |
+
num_workers=int(cfg["train"].get("num_workers", 8)),
|
| 57 |
+
pin_memory=True,
|
| 58 |
+
drop_last=True,
|
| 59 |
+
collate_fn=segmentation_collate,
|
| 60 |
+
persistent_workers=int(cfg["train"].get("num_workers", 8)) > 0,
|
| 61 |
+
)
|
| 62 |
+
val_loader = None
|
| 63 |
+
if not full_train:
|
| 64 |
+
val_ds = CoralSegDataset(
|
| 65 |
+
data_cfg["train_images"],
|
| 66 |
+
data_cfg["train_masks"],
|
| 67 |
+
str(val_file),
|
| 68 |
+
build_val_transform(image_size),
|
| 69 |
+
)
|
| 70 |
+
val_loader = DataLoader(
|
| 71 |
+
val_ds,
|
| 72 |
+
batch_size=batch_size,
|
| 73 |
+
shuffle=False,
|
| 74 |
+
num_workers=int(cfg["train"].get("num_workers", 8)),
|
| 75 |
+
pin_memory=True,
|
| 76 |
+
collate_fn=segmentation_collate,
|
| 77 |
+
persistent_workers=int(cfg["train"].get("num_workers", 8)) > 0,
|
| 78 |
+
)
|
| 79 |
+
return train_loader, val_loader
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
@torch.no_grad()
|
| 83 |
+
def validate(model: torch.nn.Module, loader: DataLoader, cfg: Dict, device: torch.device) -> tuple[float, np.ndarray]:
|
| 84 |
+
model.eval()
|
| 85 |
+
num_classes = int(cfg["num_classes"])
|
| 86 |
+
hist = np.zeros((num_classes, num_classes), dtype=np.int64)
|
| 87 |
+
for batch in loader:
|
| 88 |
+
images = batch["image"].to(device, non_blocking=True)
|
| 89 |
+
masks = batch["mask"].numpy()
|
| 90 |
+
logits = model(images)
|
| 91 |
+
preds = logits.argmax(dim=1).cpu().numpy().astype(np.uint8)
|
| 92 |
+
for pred, target in zip(preds, masks):
|
| 93 |
+
hist += fast_hist(pred, target, num_classes)
|
| 94 |
+
iou, miou = compute_iou(hist)
|
| 95 |
+
return miou, iou
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def main() -> None:
|
| 99 |
+
parser = argparse.ArgumentParser()
|
| 100 |
+
parser.add_argument("--config", default=str(ROOT / "configs/final_dual.yaml"))
|
| 101 |
+
parser.add_argument("--resume", default="")
|
| 102 |
+
parser.add_argument("--full-train", action="store_true")
|
| 103 |
+
args = parser.parse_args()
|
| 104 |
+
|
| 105 |
+
cfg = load_config(args.config)
|
| 106 |
+
set_seed(int(cfg.get("seed", 2026)))
|
| 107 |
+
conv_cfg = cfg["convnext"]
|
| 108 |
+
work_dir = ensure_dir(conv_cfg["work_dir"])
|
| 109 |
+
save_json(work_dir / "resolved_config.json", cfg)
|
| 110 |
+
|
| 111 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 112 |
+
train_loader, val_loader = build_loaders(
|
| 113 |
+
cfg,
|
| 114 |
+
image_size=int(conv_cfg["image_size"]),
|
| 115 |
+
batch_size=int(conv_cfg["batch_size"]),
|
| 116 |
+
full_train=args.full_train,
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
model = ConvNeXtFPN(
|
| 120 |
+
num_classes=int(cfg["num_classes"]),
|
| 121 |
+
pretrained=bool(conv_cfg.get("pretrained", True)),
|
| 122 |
+
pretrained_path=conv_cfg.get("pretrained_path"),
|
| 123 |
+
).to(device)
|
| 124 |
+
|
| 125 |
+
if args.resume:
|
| 126 |
+
ckpt = torch.load(args.resume, map_location="cpu")
|
| 127 |
+
model.load_state_dict(ckpt["model"], strict=True)
|
| 128 |
+
|
| 129 |
+
loss_cfg = conv_cfg["loss"]
|
| 130 |
+
criterion = ComboSegLoss(
|
| 131 |
+
num_classes=int(cfg["num_classes"]),
|
| 132 |
+
ce_weight=float(loss_cfg.get("ce", 1.0)),
|
| 133 |
+
dice_weight=float(loss_cfg.get("dice", 1.0)),
|
| 134 |
+
lovasz_weight=float(loss_cfg.get("lovasz", 0.5)),
|
| 135 |
+
label_smoothing=float(loss_cfg.get("label_smoothing", 0.05)),
|
| 136 |
+
)
|
| 137 |
+
|
| 138 |
+
backbone_params = []
|
| 139 |
+
head_params = []
|
| 140 |
+
for name, param in model.named_parameters():
|
| 141 |
+
if not param.requires_grad:
|
| 142 |
+
continue
|
| 143 |
+
if name.startswith("features"):
|
| 144 |
+
backbone_params.append(param)
|
| 145 |
+
else:
|
| 146 |
+
head_params.append(param)
|
| 147 |
+
|
| 148 |
+
optimizer = AdamW(
|
| 149 |
+
[
|
| 150 |
+
{"params": backbone_params, "lr": float(conv_cfg["lr"]) * float(conv_cfg.get("backbone_lr_mult", 0.25))},
|
| 151 |
+
{"params": head_params, "lr": float(conv_cfg["lr"])},
|
| 152 |
+
],
|
| 153 |
+
weight_decay=float(conv_cfg["weight_decay"]),
|
| 154 |
+
)
|
| 155 |
+
epochs = int(conv_cfg["epochs"])
|
| 156 |
+
total_steps = epochs * len(train_loader)
|
| 157 |
+
warmup_steps = int(conv_cfg.get("warmup_epochs", 5)) * len(train_loader)
|
| 158 |
+
scheduler = LambdaLR(
|
| 159 |
+
optimizer,
|
| 160 |
+
functools.partial(cosine_warmup_lambda, total_steps=total_steps, warmup_steps=warmup_steps),
|
| 161 |
+
)
|
| 162 |
+
scaler = GradScaler(enabled=bool(cfg["train"].get("amp", True)))
|
| 163 |
+
best_miou = -1.0
|
| 164 |
+
|
| 165 |
+
for epoch in range(1, epochs + 1):
|
| 166 |
+
model.train()
|
| 167 |
+
meter = AverageMeter()
|
| 168 |
+
for step, batch in enumerate(train_loader, start=1):
|
| 169 |
+
images = batch["image"].to(device, non_blocking=True)
|
| 170 |
+
masks = batch["mask"].to(device, non_blocking=True)
|
| 171 |
+
optimizer.zero_grad(set_to_none=True)
|
| 172 |
+
with autocast(enabled=bool(cfg["train"].get("amp", True))):
|
| 173 |
+
logits = model(images)
|
| 174 |
+
loss = criterion(logits, masks, epoch)
|
| 175 |
+
scaler.scale(loss).backward()
|
| 176 |
+
grad_clip = float(cfg["train"].get("grad_clip_norm", 0.0))
|
| 177 |
+
if grad_clip > 0:
|
| 178 |
+
scaler.unscale_(optimizer)
|
| 179 |
+
torch.nn.utils.clip_grad_norm_(model.parameters(), grad_clip)
|
| 180 |
+
scaler.step(optimizer)
|
| 181 |
+
scaler.update()
|
| 182 |
+
scheduler.step()
|
| 183 |
+
meter.update(loss.item(), images.size(0))
|
| 184 |
+
if step % int(cfg["train"].get("print_freq", 50)) == 0:
|
| 185 |
+
lr = optimizer.param_groups[-1]["lr"]
|
| 186 |
+
print(f"{timestamp()} epoch={epoch}/{epochs} step={step}/{len(train_loader)} loss={meter.avg:.5f} lr={lr:.8f}")
|
| 187 |
+
|
| 188 |
+
metrics = {"epoch": epoch, "train_loss": meter.avg}
|
| 189 |
+
if val_loader is not None:
|
| 190 |
+
miou, iou = validate(model, val_loader, cfg, device)
|
| 191 |
+
metrics.update({"val_miou": miou, "val_iou": iou.tolist()})
|
| 192 |
+
print(f"{timestamp()} convnext val {format_metrics(iou, miou, cfg['class_names'])}")
|
| 193 |
+
is_best = miou > best_miou
|
| 194 |
+
best_miou = max(best_miou, miou)
|
| 195 |
+
else:
|
| 196 |
+
is_best = True
|
| 197 |
+
|
| 198 |
+
state = {
|
| 199 |
+
"model": model.state_dict(),
|
| 200 |
+
"epoch": epoch,
|
| 201 |
+
"best_miou": best_miou,
|
| 202 |
+
"config": cfg,
|
| 203 |
+
"metrics": metrics,
|
| 204 |
+
}
|
| 205 |
+
torch.save(state, work_dir / "latest.pth")
|
| 206 |
+
if is_best:
|
| 207 |
+
torch.save(state, work_dir / "best.pth")
|
| 208 |
+
print(f"{timestamp()} saved {work_dir / 'best.pth'}")
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
if __name__ == "__main__":
|
| 212 |
+
main()
|
coral_seg/tools/train_mask2former.py
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import functools
|
| 3 |
+
import sys
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from typing import Dict, List
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
from torch.cuda.amp import GradScaler, autocast
|
| 11 |
+
from torch.optim import AdamW
|
| 12 |
+
from torch.optim.lr_scheduler import LambdaLR
|
| 13 |
+
from torch.utils.data import DataLoader
|
| 14 |
+
from transformers import Mask2FormerForUniversalSegmentation
|
| 15 |
+
|
| 16 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 17 |
+
sys.path.insert(0, str(ROOT))
|
| 18 |
+
|
| 19 |
+
from coral_seg.dataset import CoralSegDataset, build_train_transform, build_val_transform, mask2former_collate
|
| 20 |
+
from coral_seg.splits import create_split_files
|
| 21 |
+
from coral_seg.utils import (
|
| 22 |
+
AverageMeter,
|
| 23 |
+
compute_iou,
|
| 24 |
+
cosine_warmup_lambda,
|
| 25 |
+
ensure_dir,
|
| 26 |
+
fast_hist,
|
| 27 |
+
format_metrics,
|
| 28 |
+
load_config,
|
| 29 |
+
save_json,
|
| 30 |
+
set_seed,
|
| 31 |
+
timestamp,
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def semantic_logits_from_mask2former(outputs, target_size: tuple[int, int]) -> torch.Tensor:
|
| 36 |
+
class_logits = outputs.class_queries_logits
|
| 37 |
+
mask_logits = outputs.masks_queries_logits
|
| 38 |
+
class_probs = torch.softmax(class_logits, dim=-1)[..., :-1]
|
| 39 |
+
mask_probs = torch.sigmoid(mask_logits)
|
| 40 |
+
semseg = torch.einsum("bqc,bqhw->bchw", class_probs, mask_probs)
|
| 41 |
+
return F.interpolate(semseg, size=target_size, mode="bilinear", align_corners=False)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def build_model(cfg: Dict) -> Mask2FormerForUniversalSegmentation:
|
| 45 |
+
mcfg = cfg["mask2former"]
|
| 46 |
+
id2label = {i: name for i, name in enumerate(cfg["class_names"])}
|
| 47 |
+
label2id = {name: i for i, name in id2label.items()}
|
| 48 |
+
model_name_or_path = mcfg.get("pretrained_dir") or mcfg["pretrained_name"]
|
| 49 |
+
if not Path(str(model_name_or_path)).exists():
|
| 50 |
+
model_name_or_path = mcfg["pretrained_name"]
|
| 51 |
+
model = Mask2FormerForUniversalSegmentation.from_pretrained(
|
| 52 |
+
model_name_or_path,
|
| 53 |
+
num_labels=int(cfg["num_classes"]),
|
| 54 |
+
id2label=id2label,
|
| 55 |
+
label2id=label2id,
|
| 56 |
+
ignore_mismatched_sizes=True,
|
| 57 |
+
)
|
| 58 |
+
if bool(mcfg.get("gradient_checkpointing", True)):
|
| 59 |
+
try:
|
| 60 |
+
model.gradient_checkpointing_enable()
|
| 61 |
+
except ValueError:
|
| 62 |
+
print("Gradient checkpointing is not supported by this Mask2Former class; continuing without it.")
|
| 63 |
+
return model
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def build_loaders(cfg: Dict, image_size: int, batch_size: int, full_train: bool) -> tuple[DataLoader, DataLoader | None]:
|
| 67 |
+
data_cfg = cfg["data"]
|
| 68 |
+
train_file, val_file, full_file = create_split_files(
|
| 69 |
+
data_cfg["train_images"],
|
| 70 |
+
data_cfg["train_masks"],
|
| 71 |
+
data_cfg["split_dir"],
|
| 72 |
+
val_ratio=float(data_cfg.get("val_ratio", 0.15)),
|
| 73 |
+
seed=int(cfg.get("seed", 2026)),
|
| 74 |
+
)
|
| 75 |
+
split_file = full_file if full_train else train_file
|
| 76 |
+
collate = functools.partial(mask2former_collate, num_classes=int(cfg["num_classes"]))
|
| 77 |
+
train_ds = CoralSegDataset(
|
| 78 |
+
data_cfg["train_images"],
|
| 79 |
+
data_cfg["train_masks"],
|
| 80 |
+
str(split_file),
|
| 81 |
+
build_train_transform(image_size),
|
| 82 |
+
)
|
| 83 |
+
train_loader = DataLoader(
|
| 84 |
+
train_ds,
|
| 85 |
+
batch_size=batch_size,
|
| 86 |
+
shuffle=True,
|
| 87 |
+
num_workers=int(cfg["train"].get("num_workers", 8)),
|
| 88 |
+
pin_memory=True,
|
| 89 |
+
drop_last=True,
|
| 90 |
+
collate_fn=collate,
|
| 91 |
+
persistent_workers=int(cfg["train"].get("num_workers", 8)) > 0,
|
| 92 |
+
)
|
| 93 |
+
val_loader = None
|
| 94 |
+
if not full_train:
|
| 95 |
+
val_ds = CoralSegDataset(
|
| 96 |
+
data_cfg["train_images"],
|
| 97 |
+
data_cfg["train_masks"],
|
| 98 |
+
str(val_file),
|
| 99 |
+
build_val_transform(image_size),
|
| 100 |
+
)
|
| 101 |
+
val_loader = DataLoader(
|
| 102 |
+
val_ds,
|
| 103 |
+
batch_size=batch_size,
|
| 104 |
+
shuffle=False,
|
| 105 |
+
num_workers=int(cfg["train"].get("num_workers", 8)),
|
| 106 |
+
pin_memory=True,
|
| 107 |
+
collate_fn=collate,
|
| 108 |
+
persistent_workers=int(cfg["train"].get("num_workers", 8)) > 0,
|
| 109 |
+
)
|
| 110 |
+
return train_loader, val_loader
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
@torch.no_grad()
|
| 114 |
+
def validate(model: torch.nn.Module, loader: DataLoader, cfg: Dict, device: torch.device) -> tuple[float, np.ndarray]:
|
| 115 |
+
model.eval()
|
| 116 |
+
num_classes = int(cfg["num_classes"])
|
| 117 |
+
hist = np.zeros((num_classes, num_classes), dtype=np.int64)
|
| 118 |
+
for batch in loader:
|
| 119 |
+
images = batch["image"].to(device, non_blocking=True)
|
| 120 |
+
masks = batch["raw_mask"].numpy()
|
| 121 |
+
outputs = model(pixel_values=images)
|
| 122 |
+
logits = semantic_logits_from_mask2former(outputs, target_size=masks.shape[-2:])
|
| 123 |
+
preds = logits.argmax(dim=1).cpu().numpy().astype(np.uint8)
|
| 124 |
+
for pred, target in zip(preds, masks):
|
| 125 |
+
hist += fast_hist(pred, target, num_classes)
|
| 126 |
+
iou, miou = compute_iou(hist)
|
| 127 |
+
return miou, iou
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def main() -> None:
|
| 131 |
+
parser = argparse.ArgumentParser()
|
| 132 |
+
parser.add_argument("--config", default=str(ROOT / "configs/final_dual.yaml"))
|
| 133 |
+
parser.add_argument("--resume", default="")
|
| 134 |
+
parser.add_argument("--full-train", action="store_true")
|
| 135 |
+
args = parser.parse_args()
|
| 136 |
+
|
| 137 |
+
cfg = load_config(args.config)
|
| 138 |
+
set_seed(int(cfg.get("seed", 2026)))
|
| 139 |
+
mcfg = cfg["mask2former"]
|
| 140 |
+
work_dir = ensure_dir(mcfg["work_dir"])
|
| 141 |
+
save_json(work_dir / "resolved_config.json", cfg)
|
| 142 |
+
|
| 143 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 144 |
+
train_loader, val_loader = build_loaders(
|
| 145 |
+
cfg,
|
| 146 |
+
image_size=int(mcfg["image_size"]),
|
| 147 |
+
batch_size=int(mcfg["batch_size"]),
|
| 148 |
+
full_train=args.full_train,
|
| 149 |
+
)
|
| 150 |
+
model = build_model(cfg).to(device)
|
| 151 |
+
if args.resume:
|
| 152 |
+
ckpt = torch.load(args.resume, map_location="cpu")
|
| 153 |
+
model.load_state_dict(ckpt["model"], strict=True)
|
| 154 |
+
|
| 155 |
+
no_decay = ("bias", "LayerNorm.weight", "layer_norm.weight", "norm.weight")
|
| 156 |
+
grouped = [
|
| 157 |
+
{
|
| 158 |
+
"params": [p for n, p in model.named_parameters() if p.requires_grad and not any(nd in n for nd in no_decay)],
|
| 159 |
+
"weight_decay": float(mcfg["weight_decay"]),
|
| 160 |
+
},
|
| 161 |
+
{
|
| 162 |
+
"params": [p for n, p in model.named_parameters() if p.requires_grad and any(nd in n for nd in no_decay)],
|
| 163 |
+
"weight_decay": 0.0,
|
| 164 |
+
},
|
| 165 |
+
]
|
| 166 |
+
optimizer = AdamW(grouped, lr=float(mcfg["lr"]))
|
| 167 |
+
epochs = int(mcfg["epochs"])
|
| 168 |
+
total_steps = epochs * len(train_loader)
|
| 169 |
+
warmup_steps = int(mcfg.get("warmup_epochs", 5)) * len(train_loader)
|
| 170 |
+
scheduler = LambdaLR(
|
| 171 |
+
optimizer,
|
| 172 |
+
functools.partial(cosine_warmup_lambda, total_steps=total_steps, warmup_steps=warmup_steps),
|
| 173 |
+
)
|
| 174 |
+
scaler = GradScaler(enabled=bool(cfg["train"].get("amp", True)))
|
| 175 |
+
best_miou = -1.0
|
| 176 |
+
|
| 177 |
+
for epoch in range(1, epochs + 1):
|
| 178 |
+
model.train()
|
| 179 |
+
meter = AverageMeter()
|
| 180 |
+
for step, batch in enumerate(train_loader, start=1):
|
| 181 |
+
images = batch["image"].to(device, non_blocking=True)
|
| 182 |
+
mask_labels = [m.to(device, non_blocking=True) for m in batch["mask_labels"]]
|
| 183 |
+
class_labels = [c.to(device, non_blocking=True) for c in batch["class_labels"]]
|
| 184 |
+
optimizer.zero_grad(set_to_none=True)
|
| 185 |
+
with autocast(enabled=bool(cfg["train"].get("amp", True))):
|
| 186 |
+
outputs = model(pixel_values=images, mask_labels=mask_labels, class_labels=class_labels)
|
| 187 |
+
loss = outputs.loss
|
| 188 |
+
scaler.scale(loss).backward()
|
| 189 |
+
grad_clip = float(cfg["train"].get("grad_clip_norm", 0.0))
|
| 190 |
+
if grad_clip > 0:
|
| 191 |
+
scaler.unscale_(optimizer)
|
| 192 |
+
torch.nn.utils.clip_grad_norm_(model.parameters(), grad_clip)
|
| 193 |
+
scaler.step(optimizer)
|
| 194 |
+
scaler.update()
|
| 195 |
+
scheduler.step()
|
| 196 |
+
meter.update(loss.item(), images.size(0))
|
| 197 |
+
if step % int(cfg["train"].get("print_freq", 50)) == 0:
|
| 198 |
+
lr = optimizer.param_groups[0]["lr"]
|
| 199 |
+
print(f"{timestamp()} epoch={epoch}/{epochs} step={step}/{len(train_loader)} loss={meter.avg:.5f} lr={lr:.8f}")
|
| 200 |
+
|
| 201 |
+
metrics = {"epoch": epoch, "train_loss": meter.avg}
|
| 202 |
+
if val_loader is not None:
|
| 203 |
+
miou, iou = validate(model, val_loader, cfg, device)
|
| 204 |
+
metrics.update({"val_miou": miou, "val_iou": iou.tolist()})
|
| 205 |
+
print(f"{timestamp()} mask2former val {format_metrics(iou, miou, cfg['class_names'])}")
|
| 206 |
+
is_best = miou > best_miou
|
| 207 |
+
best_miou = max(best_miou, miou)
|
| 208 |
+
else:
|
| 209 |
+
is_best = True
|
| 210 |
+
|
| 211 |
+
state = {
|
| 212 |
+
"model": model.state_dict(),
|
| 213 |
+
"epoch": epoch,
|
| 214 |
+
"best_miou": best_miou,
|
| 215 |
+
"config": cfg,
|
| 216 |
+
"metrics": metrics,
|
| 217 |
+
}
|
| 218 |
+
torch.save(state, work_dir / "latest.pth")
|
| 219 |
+
if is_best:
|
| 220 |
+
torch.save(state, work_dir / "best.pth")
|
| 221 |
+
model.save_pretrained(work_dir / "best_hf")
|
| 222 |
+
print(f"{timestamp()} saved {work_dir / 'best.pth'} and {work_dir / 'best_hf'}")
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
if __name__ == "__main__":
|
| 226 |
+
main()
|
coral_seg/tools/visualize_results.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from typing import Optional
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 7 |
+
|
| 8 |
+
PALETTE = np.array(
|
| 9 |
+
[
|
| 10 |
+
[0, 0, 0],
|
| 11 |
+
[0, 162, 232],
|
| 12 |
+
[240, 110, 170],
|
| 13 |
+
[255, 242, 0],
|
| 14 |
+
],
|
| 15 |
+
dtype=np.uint8,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def label_to_color(mask: np.ndarray) -> np.ndarray:
|
| 20 |
+
mask = np.asarray(mask)
|
| 21 |
+
if mask.ndim == 3:
|
| 22 |
+
return mask.astype(np.uint8)
|
| 23 |
+
mask = np.clip(mask, 0, len(PALETTE) - 1)
|
| 24 |
+
return PALETTE[mask]
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def overlay(image: np.ndarray, color_mask: np.ndarray, alpha: float = 0.45) -> np.ndarray:
|
| 28 |
+
image = image.astype(np.float32)
|
| 29 |
+
color_mask = color_mask.astype(np.float32)
|
| 30 |
+
fg = color_mask.sum(axis=-1) > 0
|
| 31 |
+
out = image.copy()
|
| 32 |
+
out[fg] = image[fg] * (1.0 - alpha) + color_mask[fg] * alpha
|
| 33 |
+
return np.clip(out, 0, 255).astype(np.uint8)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def add_title(arr: np.ndarray, title: str) -> np.ndarray:
|
| 37 |
+
h, w = arr.shape[:2]
|
| 38 |
+
canvas = np.full((h + 28, w, 3), 255, dtype=np.uint8)
|
| 39 |
+
canvas[28:] = arr
|
| 40 |
+
img = Image.fromarray(canvas)
|
| 41 |
+
draw = ImageDraw.Draw(img)
|
| 42 |
+
draw.text((8, 7), title, fill=(0, 0, 0))
|
| 43 |
+
return np.array(img)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def read_rgb(path: Path) -> np.ndarray:
|
| 47 |
+
return np.array(Image.open(path).convert('RGB'))
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def read_mask(path: Path) -> np.ndarray:
|
| 51 |
+
arr = np.array(Image.open(path))
|
| 52 |
+
if arr.ndim == 3:
|
| 53 |
+
return arr[:, :, :3]
|
| 54 |
+
return arr.astype(np.uint8)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def main() -> None:
|
| 58 |
+
parser = argparse.ArgumentParser()
|
| 59 |
+
parser.add_argument('--image-dir', default='/root/autodl-tmp/coral/data_fresh/test_raw/PrecisionLabel800/images')
|
| 60 |
+
parser.add_argument('--pred-dir', default='/root/autodl-tmp/coral/coral_seg/submissions/results')
|
| 61 |
+
parser.add_argument('--gt-dir', default='')
|
| 62 |
+
parser.add_argument('--out-dir', default='/root/autodl-tmp/coral/coral_seg/vis_results')
|
| 63 |
+
parser.add_argument('--num', type=int, default=24)
|
| 64 |
+
parser.add_argument('--alpha', type=float, default=0.45)
|
| 65 |
+
args = parser.parse_args()
|
| 66 |
+
|
| 67 |
+
image_dir = Path(args.image_dir)
|
| 68 |
+
pred_dir = Path(args.pred_dir)
|
| 69 |
+
gt_dir = Path(args.gt_dir) if args.gt_dir else None
|
| 70 |
+
out_dir = Path(args.out_dir)
|
| 71 |
+
out_dir.mkdir(parents=True, exist_ok=True)
|
| 72 |
+
|
| 73 |
+
pred_paths = sorted(pred_dir.glob('*.png'))[: args.num]
|
| 74 |
+
if not pred_paths:
|
| 75 |
+
raise RuntimeError(f'No prediction PNG files found in {pred_dir}')
|
| 76 |
+
|
| 77 |
+
for pred_path in pred_paths:
|
| 78 |
+
image_path = image_dir / pred_path.name
|
| 79 |
+
if not image_path.exists():
|
| 80 |
+
raise FileNotFoundError(image_path)
|
| 81 |
+
image = read_rgb(image_path)
|
| 82 |
+
pred = read_mask(pred_path)
|
| 83 |
+
pred_color = label_to_color(pred)
|
| 84 |
+
panels = [
|
| 85 |
+
add_title(image, 'image'),
|
| 86 |
+
add_title(pred_color, 'prediction'),
|
| 87 |
+
add_title(overlay(image, pred_color, args.alpha), 'pred overlay'),
|
| 88 |
+
]
|
| 89 |
+
if gt_dir is not None:
|
| 90 |
+
gt_path = gt_dir / pred_path.name
|
| 91 |
+
if gt_path.exists():
|
| 92 |
+
gt = read_mask(gt_path)
|
| 93 |
+
gt_color = label_to_color(gt)
|
| 94 |
+
panels.append(add_title(gt_color, 'gt'))
|
| 95 |
+
panels.append(add_title(overlay(image, gt_color, args.alpha), 'gt overlay'))
|
| 96 |
+
canvas = np.concatenate(panels, axis=1)
|
| 97 |
+
Image.fromarray(canvas).save(out_dir / pred_path.name)
|
| 98 |
+
print(f'saved {len(pred_paths)} visualizations to {out_dir}')
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
if __name__ == '__main__':
|
| 102 |
+
main()
|
coral_seg/vis_results/image_0001.png
ADDED
|
Git LFS Details
|