|
| 1 | +import json |
1 | 2 | import os |
2 | 3 | from shutil import move |
3 | 4 |
|
@@ -177,6 +178,119 @@ def test_detection_dataset(mock_image_folder, mock_detection_label): |
177 | 178 | move(os.path.join(ds.root, "tmp_file"), os.path.join(ds.root, img_name)) |
178 | 179 |
|
179 | 180 |
|
| 181 | +@pytest.mark.parametrize( |
| 182 | + "use_polygons", |
| 183 | + [False, True], |
| 184 | +) |
| 185 | +def test_layout_dataset(mock_image_folder, mock_layout_label, use_polygons): |
| 186 | + input_size = (1024, 1024) |
| 187 | + |
| 188 | + ds = datasets.LayoutDataset( |
| 189 | + img_folder=mock_image_folder, |
| 190 | + label_path=mock_layout_label, |
| 191 | + img_transforms=Resize(input_size), |
| 192 | + use_polygons=use_polygons, |
| 193 | + ) |
| 194 | + |
| 195 | + assert len(ds) == 5 |
| 196 | + img, target_dict = ds[0] |
| 197 | + assert isinstance(img, torch.Tensor) |
| 198 | + assert img.dtype == torch.float32 |
| 199 | + assert img.shape[-2:] == input_size |
| 200 | + assert isinstance(target_dict, dict) |
| 201 | + expected_classes = {"Table", "Header", "Footer", "Text"} |
| 202 | + assert set(target_dict.keys()) == expected_classes |
| 203 | + for class_name, target in target_dict.items(): |
| 204 | + assert isinstance(target, np.ndarray) |
| 205 | + assert target.dtype == np.float32 |
| 206 | + if use_polygons: |
| 207 | + assert target.ndim == 3 |
| 208 | + assert target.shape[1:] == (4, 2) |
| 209 | + else: |
| 210 | + assert target.ndim == 2 |
| 211 | + assert target.shape[1:] == (4,) |
| 212 | + assert np.all(np.logical_and(target >= 0, target <= 1)) |
| 213 | + assert ds.class_names == sorted(expected_classes) |
| 214 | + loader = DataLoader(ds, batch_size=2, collate_fn=ds.collate_fn) |
| 215 | + images, targets = next(iter(loader)) |
| 216 | + assert isinstance(images, torch.Tensor) |
| 217 | + assert images.shape == (2, 3, *input_size) |
| 218 | + assert isinstance(targets, list) |
| 219 | + assert all(isinstance(target, dict) for target in targets) |
| 220 | + for target in targets: |
| 221 | + assert set(target.keys()) == expected_classes |
| 222 | + assert all(isinstance(v, np.ndarray) for v in target.values()) |
| 223 | + |
| 224 | + # File existence check |
| 225 | + img_name, _ = ds.data[0] |
| 226 | + move(os.path.join(ds.root, img_name), os.path.join(ds.root, "tmp_file")) |
| 227 | + with pytest.raises(FileNotFoundError): |
| 228 | + datasets.LayoutDataset( |
| 229 | + img_folder=mock_image_folder, |
| 230 | + label_path=mock_layout_label, |
| 231 | + ) |
| 232 | + move(os.path.join(ds.root, "tmp_file"), os.path.join(ds.root, img_name)) |
| 233 | + |
| 234 | + with pytest.raises(FileNotFoundError): |
| 235 | + datasets.LayoutDataset( |
| 236 | + img_folder=mock_image_folder, |
| 237 | + label_path="/tmp/does_not_exist.json", |
| 238 | + ) |
| 239 | + |
| 240 | + with open(mock_layout_label) as f: |
| 241 | + original_labels = json.load(f) |
| 242 | + first_key = next(iter(original_labels)) |
| 243 | + |
| 244 | + test_cases = [ |
| 245 | + ( |
| 246 | + {"class_names": ["Text"]}, |
| 247 | + KeyError, |
| 248 | + "missing 'polygons'", |
| 249 | + ), |
| 250 | + ( |
| 251 | + {"polygons": [[[0, 0], [1, 0], [1, 1], [0, 1]]]}, |
| 252 | + KeyError, |
| 253 | + "missing 'class_names'", |
| 254 | + ), |
| 255 | + ( |
| 256 | + { |
| 257 | + "polygons": [ |
| 258 | + [[0, 0], [1, 0], [1, 1], [0, 1]], |
| 259 | + [[0, 0], [1, 0], [1, 1], [0, 1]], |
| 260 | + ], |
| 261 | + "class_names": ["Text"], |
| 262 | + }, |
| 263 | + ValueError, |
| 264 | + "number of polygons", |
| 265 | + ), |
| 266 | + ( |
| 267 | + { |
| 268 | + "polygons": [[[0, 0], [1, 0], [1, 1]]], # only 3 points |
| 269 | + "class_names": ["Text"], |
| 270 | + }, |
| 271 | + ValueError, |
| 272 | + "polygons are expected to have shape", |
| 273 | + ), |
| 274 | + ] |
| 275 | + |
| 276 | + for sample, exc_type, match in test_cases: |
| 277 | + broken_labels = dict(original_labels) |
| 278 | + broken_labels[first_key] = sample |
| 279 | + |
| 280 | + with open(mock_layout_label, "w") as f: |
| 281 | + json.dump(broken_labels, f) |
| 282 | + |
| 283 | + with pytest.raises(exc_type, match=match): |
| 284 | + datasets.LayoutDataset( |
| 285 | + img_folder=mock_image_folder, |
| 286 | + label_path=mock_layout_label, |
| 287 | + ) |
| 288 | + |
| 289 | + # Restore original labels |
| 290 | + with open(mock_layout_label, "w") as f: |
| 291 | + json.dump(original_labels, f) |
| 292 | + |
| 293 | + |
180 | 294 | def test_recognition_dataset(mock_image_folder, mock_recognition_label): |
181 | 295 | input_size = (32, 128) |
182 | 296 | ds = datasets.RecognitionDataset( |
|
0 commit comments