Infarondus commited on
Commit
d67fc4b
·
verified ·
1 Parent(s): 9412fbb

Upload 2 files

Browse files
Files changed (2) hide show
  1. README_convnext_binding.md +134 -0
  2. README_dinov2_srednik.md +178 -0
README_convnext_binding.md ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - ru
5
+ - en
6
+ base_model:
7
+ - facebook/convnext-tiny-224
8
+ pipeline_tag: image-classification
9
+ tags:
10
+ - manuscript
11
+ - bookbinding
12
+ - cultural-heritage
13
+ - digital-humanities
14
+ - convnext
15
+ - fine-tuned
16
+ library_name: timm
17
+ ---
18
+
19
+ # Kleine-Marchen — Binding Detector (ConvNeXt-Tiny)
20
+
21
+ Модель на базе **ConvNeXt-Tiny (ImageNet-22k)** для определения является ли изображение фотографией переплёта рукописи.
22
+
23
+ Используется как **первая ступень** в двухэтапном пайплайне классификации переплётов рукописей РГБ.
24
+
25
+ ---
26
+
27
+ ## Назначение
28
+
29
+ Бинарная классификация:
30
+
31
+ - **Класс 1 — переплёт**: изображение является фотографией крышки переплёта рукописи
32
+ - **Класс 0 — не переплёт**: страница текста, разворот, предметная съёмка и т.д.
33
+
34
+ Модель решает задачу фильтрации при массовом скачивании изображений из цифровых архивов рукописей, где первые страницы оцифровки содержат как переплёты, так и текстовые страницы.
35
+
36
+ ---
37
+
38
+ ## Метрики
39
+
40
+ | Метрика | Значение |
41
+ |---|---|
42
+ | Accuracy (валидация) | **96%** |
43
+
44
+ ---
45
+
46
+ ## Данные
47
+
48
+ - **Источник**: фотографии из фондов РГБ
49
+ - **Размер**: ~500 изображений на каждый класс
50
+ - **Классы**: переплёт / не переплёт (страницы текста, развороты)
51
+ - **Разрешение при обучении**: 320×320 px
52
+
53
+ ---
54
+
55
+ ## Архитектура
56
+
57
+ **Базовая модель**: `convnext_tiny.fb_in22k` (ImageNet-22k pretrain, 28M параметров)
58
+
59
+ **Стратегия обучения**: обучение только классификационной головы при замороженном бэкбоне. Подход оправдан для задачи «переплёт vs не-переплёт» — ImageNet-22k фичи достаточно различимы для такого крупного визуального различия без fine-tuning бэкбона.
60
+
61
+ ---
62
+
63
+ ## Использование
64
+
65
+ Готовые скрипты доступны в репозитории:
66
+
67
+ **[https://github.com/Infarondus/Kleine-marchen](https://github.com/Infarondus/Kleine-marchen)**
68
+
69
+ ### Быстрый старт
70
+
71
+ ```python
72
+ import torch
73
+ import timm
74
+ import numpy as np
75
+ from PIL import Image
76
+ import albumentations as A
77
+ from albumentations.pytorch import ToTensorV2
78
+
79
+ IMAGE_SIZE = 320
80
+
81
+ transform = A.Compose([
82
+ A.LongestMaxSize(max_size=IMAGE_SIZE),
83
+ A.PadIfNeeded(min_height=IMAGE_SIZE, min_width=IMAGE_SIZE,
84
+ border_mode=0, value=[255, 255, 255]),
85
+ A.Normalize(mean=[0.485, 0.456, 0.406],
86
+ std=[0.229, 0.224, 0.225]),
87
+ ToTensorV2(),
88
+ ])
89
+
90
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
91
+ model = timm.create_model('convnext_tiny_in22k', pretrained=False, num_classes=2)
92
+ ckpt = torch.load('kleine-marchen_preprocess.pth', map_location=device, weights_only=False)
93
+ model.load_state_dict(ckpt['model_state_dict'])
94
+ model.to(device).eval()
95
+
96
+ img = np.array(Image.open('page.jpg').convert('RGB'))
97
+ tensor = transform(image=img)['image'].unsqueeze(0).to(device)
98
+ with torch.no_grad():
99
+ probs = torch.softmax(model(tensor), dim=1)[0]
100
+
101
+ print(f"Не переплёт: {probs[0]:.1%} | Переплёт: {probs[1]:.1%}")
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Место в пайплайне
107
+
108
+ Эта модель используется совместно с `binding-srednik-dinov2`:
109
+
110
+ ```
111
+ Изображение → [ConvNeXt: переплёт?] → [DINOv2: есть средник?] → Результат
112
+ ```
113
+
114
+ Скрипт двухступенчатого скрапера `scrape_bindings_v2.py` из репозитория **Kleine-Marchen** реализует этот пайплайн полностью.
115
+
116
+ ---
117
+
118
+ ## Ограничения
119
+
120
+ - Не предназначена для определения типа переплёта или его элементов — только факт наличия переплёта на снимке
121
+ - При сильно нестандартных условиях съёмки (белый фон, крупный план фрагмента) точность может снижаться
122
+
123
+ ---
124
+
125
+ ## Цитирование
126
+
127
+ ```
128
+ @misc{kleine-marchen-binding,
129
+ author = {Infarondus},
130
+ title = {Kleine-Marchen — Binding Detector (ConvNeXt-Tiny)},
131
+ year = {2025},
132
+ url = {https://github.com/Infarondus/Kleine-marchen}
133
+ }
134
+ ```
README_dinov2_srednik.md ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - ru
5
+ - en
6
+ base_model:
7
+ - facebook/dinov2-small
8
+ pipeline_tag: image-classification
9
+ tags:
10
+ - manuscript
11
+ - bookbinding
12
+ - cultural-heritage
13
+ - digital-humanities
14
+ - convnext
15
+ - fine-tuned
16
+ library_name: timm
17
+ ---
18
+
19
+ # Kleine-Marchen — Binding Srednik Detector (DINOv2 Ensemble)
20
+
21
+ Ансамбль из 5 моделей на базе **DINOv2 ViT-Small** для классификации переплётов рукописей по наличию **средника** — центрального декоративного элемента крышки переплёта.
22
+
23
+ Модель разработана в рамках исследования рукописного фонда Российской государственной библиотеки (РГБ).
24
+
25
+ ---
26
+
27
+ ## Назначение
28
+
29
+ Модель решает задачу бинарной классификации изображений переплётов:
30
+
31
+ - **Класс 1 — со средником**: на крышке переплёта присутствует средник
32
+ - **Класс 0 — без средника**: средник отсутствует
33
+
34
+ Модель предназначена для автоматической предварительной сортировки больших коллекций фотографий переплётов рукописей. Окончательная верификация результатов производится специалистом.
35
+
36
+ ---
37
+
38
+ ## Метрики
39
+
40
+ Оценка проводилась методом 5-fold стратифицированной кросс-валидации.
41
+
42
+ | Метрика | Значение |
43
+ |---|---|
44
+ | Accuracy (OOF Ensemble) | **94.50%** |
45
+ | F1-macro (OOF Ensemble) | **0.9450** |
46
+ | Precision | 0.9454 |
47
+ | Recall | 0.9450 |
48
+
49
+ **Confusion Matrix (OOF, все 5 фолдов):**
50
+
51
+ | | Предсказано: без средника | Предсказано: со средником |
52
+ |---|---|---|
53
+ | **Реально: без средника** | 471 | 20 |
54
+ | **Реально: со средником** | 34 | 457 |
55
+
56
+ ---
57
+
58
+ ## Данные
59
+
60
+ - **Источник**: фотографии переплётов рукописей из фондов РГБ
61
+ - **Размер обучающей выборки**: 567 изображений на каждый класс (1134 итого)
62
+ - **Формат**: цветные фотографии переплётов на тёмном фоне
63
+ - **Разрешение при обучении**: 280×280 px
64
+
65
+ Датасет собирался итеративно: после каждого цикла обучения производился анализ ошибок и доразметка сложных случаев (изношенные переплёты, пограничные экземпляры).
66
+
67
+ ---
68
+
69
+ ## Архитектура
70
+
71
+ **Базовая модель**: `vit_small_patch14_dinov2.lvd142m` (DINOv2 ViT-Small, 22M параметров)
72
+
73
+ **Голова классификатора**:
74
+ ```
75
+ LayerNorm(384) → Linear(384→256) → GELU → Dropout(0.3) → Linear(256→2)
76
+ ```
77
+
78
+ **Стратегия обучения**: двухфазный fine-tuning
79
+ - Фаза 1 (6 эпох): обучение только головы, LR = 5e-4
80
+ - Фаза 2 (20 эпох): голова + последние 4 блока ViT, дифференциальный LR (голова: 3e-5, бэкбон: 2e-6)
81
+
82
+ **Ансамбль**: 5 моделей (по одной на каждый фолд) с усреднением вероятностей + TTA (5 аугментаций)
83
+
84
+ ---
85
+
86
+ ## Использование
87
+
88
+ Готовые скрипты для обучения, оценки и инференса доступны в репозитории:
89
+
90
+ **[https://github.com/Infarondus/Kleine-marchen](https://github.com/Infarondus/Kleine-marchen)**
91
+
92
+ ### Быстрый старт
93
+
94
+ ```python
95
+ import torch
96
+ import torch.nn as nn
97
+ import torch.nn.functional as F
98
+ import timm
99
+ import numpy as np
100
+ from PIL import Image
101
+ import albumentations as A
102
+ from albumentations.pytorch import ToTensorV2
103
+
104
+ MODEL_NAME = 'vit_small_patch14_dinov2.lvd142m'
105
+ IMAGE_SIZE = 280
106
+ DINO_MEAN = [0.485, 0.456, 0.406]
107
+ DINO_STD = [0.229, 0.224, 0.225]
108
+
109
+ def build_model():
110
+ backbone = timm.create_model(
111
+ MODEL_NAME, pretrained=False, num_classes=0,
112
+ img_size=IMAGE_SIZE, dynamic_img_size=True,
113
+ )
114
+ head = nn.Sequential(
115
+ nn.LayerNorm(backbone.embed_dim),
116
+ nn.Linear(backbone.embed_dim, 256),
117
+ nn.GELU(),
118
+ nn.Dropout(0.3),
119
+ nn.Linear(256, 2),
120
+ )
121
+ class DinoClassifier(nn.Module):
122
+ def __init__(self, b, h):
123
+ super().__init__()
124
+ self.backbone, self.head = b, h
125
+ def forward(self, x):
126
+ return self.head(self.backbone(x))
127
+ return DinoClassifier(backbone, head)
128
+
129
+ transform = A.Compose([
130
+ A.LongestMaxSize(max_size=IMAGE_SIZE),
131
+ A.PadIfNeeded(min_height=IMAGE_SIZE, min_width=IMAGE_SIZE,
132
+ border_mode=0, value=[255, 255, 255]),
133
+ A.Normalize(mean=DINO_MEAN, std=DINO_STD),
134
+ ToTensorV2(),
135
+ ])
136
+
137
+ # Загрузка модели
138
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
139
+ model = build_model().to(device)
140
+ ckpt = torch.load('fold_1_km.pth', map_location=device, weights_only=False)
141
+ model.load_state_dict(ckpt['model_state_dict'])
142
+ model.eval()
143
+
144
+ # Инференс
145
+ img = np.array(Image.open('binding.jpg').convert('RGB'))
146
+ tensor = transform(image=img)['image'].unsqueeze(0).to(device)
147
+ with torch.no_grad():
148
+ probs = F.softmax(model(tensor), dim=1)[0]
149
+
150
+ print(f"Без средника: {probs[0]:.1%} | Со средником: {probs[1]:.1%}")
151
+ ```
152
+
153
+ ### Рекомендуемый порог
154
+
155
+ При использовании ансамбля рекомендуется порог **0.55–0.75** для класса «со средником» в зависимости от допустимого уровня ложных срабатываний.
156
+
157
+ ---
158
+
159
+ ## Ограничения
160
+
161
+ - Модель обучена на фотографиях переплётов РГБ и может хуже работать на изображениях из других коллекций (domain shift)
162
+ - Сильно изношенные переплёты с плохо читаемым средником являются наиболее сложными случаями
163
+ - Не предназначена для работы с изображениями страниц, не являющихся переплётами — для фильтрации используйте модель `binding-detector-convnext` на первом этапе
164
+
165
+ ---
166
+
167
+ ## Цитирование
168
+
169
+ Если вы используете эту модель в исследовании, пожалуйста укажите репозиторий:
170
+
171
+ ```
172
+ @misc{kleine-marchen-srednik,
173
+ author = {Infarondus},
174
+ title = {Kleine-Marchen — Binding Srednik Detector (DINOv2 Ensemble)},
175
+ year = {2025},
176
+ url = {https://github.com/Infarondus/Kleine-marchen}
177
+ }
178
+ ```