Skip to content

Commit 04e2816

Browse files
authoredAug 6, 2022
Better Automodel Design (#146)
* improve automodel design 1. raise warning for no available models 2. identify models based on dataset names * more tests for automodels * fix paddle detection protobuf error? * Case matters
1 parent 89aca03 commit 04e2816

File tree

3 files changed

+90
-19
lines changed

3 files changed

+90
-19
lines changed
 

‎.github/workflows/ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ jobs:
6161
pip install pytest
6262
pip install -e ".[paddledetection]"
6363
pytest tests_deps/test_only_paddledetection.py
64+
env:
65+
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python
6466

6567
test_all_methods_all_backends:
6668
needs: [test_only_effdet_backend, test_only_detectron2_backend, test_only_paddledetection_backend]

‎src/layoutparser/models/auto_layoutmodel.py

+58-12
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,57 @@
1313
# limitations under the License.
1414

1515
from typing import Optional, Dict, Union, List
16-
from .detectron2.layoutmodel import Detectron2LayoutModel
17-
from .paddledetection.layoutmodel import PaddleDetectionLayoutModel
18-
from .effdet.layoutmodel import EfficientDetLayoutModel
16+
from collections import defaultdict
17+
1918
from .model_config import (
2019
is_lp_layout_model_config_any_format,
2120
)
21+
from ..file_utils import (
22+
is_effdet_available,
23+
is_detectron2_available,
24+
is_paddle_available,
25+
)
26+
27+
ALL_AVAILABLE_BACKENDS = dict()
28+
ALL_AVAILABLE_DATASETS = defaultdict(list)
29+
30+
if is_effdet_available():
31+
from .effdet.layoutmodel import EfficientDetLayoutModel
32+
from .effdet.catalog import MODEL_CATALOG as _effdet_model_catalog
33+
34+
# fmt: off
35+
ALL_AVAILABLE_BACKENDS[EfficientDetLayoutModel.DETECTOR_NAME] = EfficientDetLayoutModel
36+
for dataset_name in _effdet_model_catalog:
37+
ALL_AVAILABLE_DATASETS[dataset_name].append(EfficientDetLayoutModel.DETECTOR_NAME)
38+
# fmt: on
39+
40+
if is_detectron2_available():
41+
from .detectron2.layoutmodel import Detectron2LayoutModel
42+
from .detectron2.catalog import MODEL_CATALOG as _detectron2_model_catalog
43+
44+
# fmt: off
45+
ALL_AVAILABLE_BACKENDS[Detectron2LayoutModel.DETECTOR_NAME] = Detectron2LayoutModel
46+
for dataset_name in _detectron2_model_catalog:
47+
ALL_AVAILABLE_DATASETS[dataset_name].append(Detectron2LayoutModel.DETECTOR_NAME)
48+
# fmt: on
49+
50+
if is_paddle_available():
51+
from .paddledetection.layoutmodel import PaddleDetectionLayoutModel
52+
from .paddledetection.catalog import MODEL_CATALOG as _paddle_model_catalog
2253

23-
ALL_AVAILABLE_BACKENDS = {
24-
Detectron2LayoutModel.DETECTOR_NAME: Detectron2LayoutModel,
25-
PaddleDetectionLayoutModel.DETECTOR_NAME: PaddleDetectionLayoutModel,
26-
EfficientDetLayoutModel.DETECTOR_NAME: EfficientDetLayoutModel,
27-
}
54+
# fmt: off
55+
ALL_AVAILABLE_BACKENDS[PaddleDetectionLayoutModel.DETECTOR_NAME] = PaddleDetectionLayoutModel
56+
for dataset_name in _paddle_model_catalog:
57+
ALL_AVAILABLE_DATASETS[dataset_name].append(PaddleDetectionLayoutModel.DETECTOR_NAME)
58+
# fmt: on
2859

2960

3061
def AutoLayoutModel(
3162
config_path: str,
3263
model_path: Optional[str] = None,
33-
label_map: Optional[Dict]=None,
34-
device: Optional[str]=None,
35-
extra_config: Optional[Union[Dict, List]]=None,
64+
label_map: Optional[Dict] = None,
65+
device: Optional[str] = None,
66+
extra_config: Optional[Union[Dict, List]] = None,
3667
) -> "BaseLayoutModel":
3768
"""[summary]
3869
@@ -50,7 +81,7 @@ def AutoLayoutModel(
5081
Defaults to `None`.
5182
device(:obj:`str`, optional):
5283
Whether to use cuda or cpu devices. If not set, LayoutParser will
53-
automatically determine the device to initialize the models on.
84+
automatically determine the device to initialize the models on.
5485
extra_config (:obj:`dict`, optional):
5586
Extra configuration passed used for initializing the layout model.
5687
@@ -59,6 +90,8 @@ def AutoLayoutModel(
5990
"""
6091
if not is_lp_layout_model_config_any_format(config_path):
6192
raise ValueError(f"Invalid model config_path {config_path}")
93+
94+
# Try to search for the model keywords
6295
for backend_name in ALL_AVAILABLE_BACKENDS:
6396
if backend_name in config_path:
6497
return ALL_AVAILABLE_BACKENDS[backend_name](
@@ -68,3 +101,16 @@ def AutoLayoutModel(
68101
extra_config=extra_config,
69102
device=device,
70103
)
104+
105+
# Try to search for the dataset keywords
106+
for dataset_name in ALL_AVAILABLE_DATASETS:
107+
if dataset_name in config_path:
108+
return ALL_AVAILABLE_BACKENDS[ALL_AVAILABLE_DATASETS[dataset_name][0]](
109+
config_path,
110+
model_path=model_path,
111+
label_map=label_map,
112+
extra_config=extra_config,
113+
device=device,
114+
)
115+
116+
raise ValueError(f"No available model found for {config_path}")

‎tests/test_model.py

+30-7
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@
4444
"lp://MFD/tf_efficientdet_d1/config",
4545
]
4646

47-
AUTOMODEL_CONFIGS = [
48-
"lp://detectron2/PubLayNet/faster_rcnn_R_50_FPN_3x/config",
49-
"lp://paddledetection/PubLayNet/ppyolov2_r50vd_dcn_365e/config",
50-
"lp://efficientdet/PubLayNet/tf_efficientdet_d0/config",
51-
]
5247

5348
def _construct_valid_config_variations(config, backend_name):
5449
dataset_name, arch_name, identifier = config[len("lp://") :].split("/")
@@ -152,8 +147,36 @@ def test_EffDetModel(is_large_scale=False):
152147
EfficientDetLayoutModel, ALL_EFFDET_MODEL_CONFIGS[0]
153148
)
154149

150+
155151
def test_AutoModel():
156-
for config in AUTOMODEL_CONFIGS:
152+
153+
# Full configs
154+
auto_model_config_1 = [
155+
"lp://detectron2/PubLayNet/faster_rcnn_R_50_FPN_3x/config",
156+
"lp://paddledetection/PubLayNet/ppyolov2_r50vd_dcn_365e/config",
157+
"lp://efficientdet/PubLayNet/tf_efficientdet_d0/config",
158+
]
159+
for config in auto_model_config_1:
157160
model = AutoLayoutModel(config)
158161
image = cv2.imread("tests/fixtures/model/test_model_image.jpg")
159-
layout = model.detect(image)
162+
layout = model.detect(image)
163+
164+
# Dataset name only
165+
# It will use the first available model
166+
auto_model_config_2 = [
167+
"lp://PubLayNet",
168+
"lp://MFD",
169+
]
170+
for config in auto_model_config_1:
171+
model = AutoLayoutModel(config)
172+
model.DETECTOR_NAME == "efficientdet"
173+
174+
# Automodel name that doesn't work
175+
176+
# 1. No available backend for the model
177+
with pytest.raises(ValueError):
178+
model = AutoLayoutModel("lp://prima")
179+
180+
# 2. Completely invalid name
181+
with pytest.raises(ValueError):
182+
model = AutoLayoutModel("lp://test")

0 commit comments

Comments
 (0)
Please sign in to comment.