kaito4681 commited on
Commit
7f2a208
·
verified ·
1 Parent(s): 10afe37

Add model usage documentation

Browse files
Files changed (1) hide show
  1. README.md +184 -0
README.md ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: ultralytics
3
+ tags:
4
+ - mahjong
5
+ - object-detection
6
+ - image-segmentation
7
+ - image-classification
8
+ - yolo
9
+ - resnet
10
+ ---
11
+
12
+ # Mahjong models
13
+
14
+ 麻雀卓の領域分割、各領域内の牌検出、牌種分類を行うための学習済みモデルです。
15
+
16
+ ## ファイル
17
+
18
+ | ファイル | 役割 | 出力 |
19
+ | --- | --- | --- |
20
+ | `regions-yolo-26n.pt` | 卓上画像から手牌・河・副露などの領域を抽出 | 15クラスのセグメンテーション |
21
+ | `tile-yolo-26n.pt` | 領域画像から個々の牌面を抽出 | `tile` 1クラスのセグメンテーション |
22
+ | `classifier-resnet50.pt` | 正規化した牌面画像の牌種を分類 | 38クラス |
23
+
24
+ ## ダウンロード
25
+
26
+ Hugging Face CLIを使用する場合:
27
+
28
+ ```bash
29
+ hf download HaseLab/mahjong-models --local-dir models
30
+ ```
31
+
32
+ Pythonから取得する場合:
33
+
34
+ ```python
35
+ from huggingface_hub import snapshot_download
36
+
37
+ snapshot_download(
38
+ repo_id="HaseLab/mahjong-models",
39
+ local_dir="models",
40
+ )
41
+ ```
42
+
43
+ ## 推奨パイプライン
44
+
45
+ 1. 元画像を`regions-yolo-26n.pt`へ入力し、卓上の各領域をセグメンテーションする。
46
+ 2. 領域の四隅を使って透視変換し、`1024 x 1024`の正方形画像にする。
47
+ 3. 正方形の領域画像を`tile-yolo-26n.pt`へ入力する。
48
+ 4. 検出された牌面ポリゴンを透視変換し、`224 x 224`の正方形画像にする。
49
+ 5. 正規化した牌面画像を`classifier-resnet50.pt`へ入力して牌種を分類する。
50
+
51
+ 牌分類器には、bboxで単純に切り出した画像ではなく、セグメンテーション結果から牌面を正方形へ透視補正した画像を入力することを推奨します。
52
+
53
+ このリポジトリ内の評価パイプラインは次のように実行できます。
54
+
55
+ ```bash
56
+ uv run python src/evaluation/grouping_yolo_pipeline.py \
57
+ --config configs/eval/grouping-yolo-26n-real-val-tiles-oof.toml
58
+ ```
59
+
60
+ ## YOLOモデルの読み込み
61
+
62
+ ```python
63
+ from ultralytics import YOLO
64
+
65
+ regions = YOLO("models/regions-yolo-26n.pt", task="segment")
66
+ tiles = YOLO("models/tile-yolo-26n.pt", task="segment")
67
+
68
+ region_results = regions.predict(
69
+ "input.jpg",
70
+ imgsz=(1152, 1536),
71
+ conf=0.25,
72
+ iou=0.50,
73
+ )
74
+
75
+ # tile-yoloには、region結果から作った1024 x 1024の領域画像を入力する
76
+ tile_results = tiles.predict(
77
+ "region_crop.png",
78
+ imgsz=1024,
79
+ conf=0.25,
80
+ iou=0.50,
81
+ )
82
+ ```
83
+
84
+ 領域モデルのクラスは次の15種類です。
85
+
86
+ ```text
87
+ 0 self_hand
88
+ 1 discard_0
89
+ 2 discard_1
90
+ 3 discard_2
91
+ 4 discard_3
92
+ 5 meld_0
93
+ 6 meld_1
94
+ 7 meld_2
95
+ 8 meld_3
96
+ 9 dora
97
+ 10 riichi_0
98
+ 11 riichi_1
99
+ 12 riichi_2
100
+ 13 riichi_3
101
+ 14 table_roi
102
+ ```
103
+
104
+ ## ResNet-50分類器の読み込み
105
+
106
+ `classifier-resnet50.pt`は、38クラスのResNet-50の`state_dict`です。
107
+
108
+ ```python
109
+ import torch
110
+ from PIL import Image
111
+ from torchvision.models import resnet50
112
+ from torchvision.transforms import Compose, Normalize, Resize, ToTensor
113
+
114
+ tile_codes = (
115
+ [f"{i}m" for i in range(10)]
116
+ + [f"{i}p" for i in range(10)]
117
+ + [f"{i}s" for i in range(10)]
118
+ + [f"{i}z" for i in range(8)]
119
+ )
120
+
121
+ # ImageFolderでの学習時と同じ辞書順。必ずこの順序を使用する。
122
+ classes = sorted(tile_codes)
123
+
124
+ model = resnet50(weights=None)
125
+ model.fc = torch.nn.Linear(model.fc.in_features, len(classes))
126
+ state_dict = torch.load(
127
+ "models/classifier-resnet50.pt",
128
+ map_location="cpu",
129
+ weights_only=True,
130
+ )
131
+ model.load_state_dict(state_dict)
132
+ model.eval()
133
+
134
+ preprocess = Compose(
135
+ [
136
+ Resize((224, 224)),
137
+ ToTensor(),
138
+ Normalize(
139
+ mean=[0.485, 0.456, 0.406],
140
+ std=[0.229, 0.224, 0.225],
141
+ ),
142
+ ]
143
+ )
144
+
145
+ image = Image.open("tile_crop.png").convert("RGB")
146
+ x = preprocess(image).unsqueeze(0)
147
+
148
+ with torch.inference_mode():
149
+ class_index = int(model(x).argmax(dim=1))
150
+
151
+ print(classes[class_index])
152
+ ```
153
+
154
+ ### クラスindexの対応
155
+
156
+ この分類器のindexは、牌コードを数牌・字牌の意味順に並べた順序ではなく、Pythonの`sorted()`による辞書順です。
157
+
158
+ ```text
159
+ 0m, 0p, 0s, 0z,
160
+ 1m, 1p, 1s, 1z,
161
+ 2m, 2p, 2s, 2z,
162
+ 3m, 3p, 3s, 3z,
163
+ 4m, 4p, 4s, 4z,
164
+ 5m, 5p, 5s, 5z,
165
+ 6m, 6p, 6s, 6z,
166
+ 7m, 7p, 7s, 7z,
167
+ 8m, 8p, 8s,
168
+ 9m, 9p, 9s
169
+ ```
170
+
171
+ 順序を変えると、同じ画像でも異なる牌コードへ対応付けられるため注意してください。また、この38クラス分類器には`back`クラスは含まれていません。
172
+
173
+ ## 推奨入力
174
+
175
+ - 横長で、着座したプレイヤー側から麻雀卓を斜めに見下ろした画像
176
+ - 領域モデル: 元画像
177
+ - 牌検出モデル: 領域モデルから透視補正した正方形画像
178
+ - 分類器: 牌検出モデルのポリゴンから透視補正したRGBの牌面画像
179
+
180
+ ## 関連リポジトリ
181
+
182
+ 実行コードと設定ファイル:
183
+
184
+ https://github.com/HaseLab/mahjong-cg