openocr-mlt-cuda 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openocr_mlt/__init__.py +11 -0
- openocr_mlt/__main__.py +2 -0
- openocr_mlt/api.py +275 -0
- openocr_mlt/assets/THIRD_PARTY_NOTICES.txt +26 -0
- openocr_mlt/assets/detector-models.json +37 -0
- openocr_mlt/assets/dict.txt +19683 -0
- openocr_mlt/assets/manifest.json +21 -0
- openocr_mlt/assets/model-bundle.json +175 -0
- openocr_mlt/assets/onnx-model.json +1565 -0
- openocr_mlt/assets/ppocrv6_onnx-LICENSE.txt +21 -0
- openocr_mlt/assets.py +37 -0
- openocr_mlt/cli.py +59 -0
- openocr_mlt/config.py +45 -0
- openocr_mlt/detection/__init__.py +4 -0
- openocr_mlt/detection/config.py +34 -0
- openocr_mlt/detection/cuda_runtime.py +44 -0
- openocr_mlt/detection/db.py +268 -0
- openocr_mlt/detection/onnx_backend.py +85 -0
- openocr_mlt/geometry.py +37 -0
- openocr_mlt/model_assets.py +34 -0
- openocr_mlt/model_fetch.py +166 -0
- openocr_mlt/onnx_runtime.py +87 -0
- openocr_mlt/processing.py +82 -0
- openocr_mlt/recognition/__init__.py +1 -0
- openocr_mlt/recognition/cuda_stream.py +39 -0
- openocr_mlt/recognition/modeling.py +777 -0
- openocr_mlt/recognition/onnx_backend.py +100 -0
- openocr_mlt/recognition/partitioned_prefill.py +67 -0
- openocr_mlt/recognition/postprocess.py +87 -0
- openocr_mlt/recognition/torch_backend.py +31 -0
- openocr_mlt/types.py +71 -0
- openocr_mlt_cuda-0.4.0.dist-info/METADATA +120 -0
- openocr_mlt_cuda-0.4.0.dist-info/RECORD +36 -0
- openocr_mlt_cuda-0.4.0.dist-info/WHEEL +5 -0
- openocr_mlt_cuda-0.4.0.dist-info/entry_points.txt +2 -0
- openocr_mlt_cuda-0.4.0.dist-info/top_level.txt +1 -0
openocr_mlt/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Offline, serial, FP32 ScriptMoE recognition."""
|
|
2
|
+
from .api import OpenOCRMLT
|
|
3
|
+
from .config import RecognitionConfig
|
|
4
|
+
from .types import RecognitionResult, DetectionResult, OCRLine, OCRResult
|
|
5
|
+
from .detection import TextDetector, DetectionConfig
|
|
6
|
+
|
|
7
|
+
__version__ = "0.4.0"
|
|
8
|
+
__all__ = ["OpenOCRMLT", "RecognitionConfig", "RecognitionResult", "DetectionResult", "OCRLine", "OCRResult", "TextDetector", "DetectionConfig"]
|
|
9
|
+
|
|
10
|
+
from .model_fetch import fetch_models
|
|
11
|
+
__all__.append("fetch_models")
|
openocr_mlt/__main__.py
ADDED
openocr_mlt/api.py
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""ScriptMoE recognition, optionally composed with pinned ONNX detection."""
|
|
2
|
+
import os
|
|
3
|
+
from dataclasses import asdict
|
|
4
|
+
from PIL import Image
|
|
5
|
+
import numpy as np
|
|
6
|
+
from .assets import resolve_assets
|
|
7
|
+
from .config import MODEL_ID, RecognitionConfig, resolve_device
|
|
8
|
+
from .processing import read_image, resize_max_side
|
|
9
|
+
from .types import RecognitionResult, DetectionResult, OCRLine, OCRResult
|
|
10
|
+
from .geometry import crop_quad
|
|
11
|
+
|
|
12
|
+
class _ConfiguredOCR:
|
|
13
|
+
def __init__(self, *, model_dir=None, weights_path=None, character_dict_path=None,
|
|
14
|
+
rec_backend="onnx", rec_device=None, rec_batch_size=1,
|
|
15
|
+
offline=True, preset="default", rec_threshold=None, max_side=None,
|
|
16
|
+
det_backend=None, det_model_dir=None,
|
|
17
|
+
det_model_id="ppocrv6-medium-det-bce-v1", det_device=None,
|
|
18
|
+
det_config=None, page_max_side=0, device=None, threads=4):
|
|
19
|
+
if rec_backend not in ("torch","onnx"):
|
|
20
|
+
raise ValueError("rec_backend must be torch or onnx")
|
|
21
|
+
if isinstance(threads,bool) or not isinstance(threads,int) or threads<1:
|
|
22
|
+
raise ValueError("threads must be a positive integer")
|
|
23
|
+
common = device if device is not None else "cpu"
|
|
24
|
+
rec_device = common if rec_device is None else rec_device
|
|
25
|
+
det_device = common if det_device is None else det_device
|
|
26
|
+
if det_backend is None and det_model_dir is not None:
|
|
27
|
+
det_backend = "onnx"
|
|
28
|
+
self.backend=rec_backend
|
|
29
|
+
self._closed=False
|
|
30
|
+
if rec_batch_size != 1:
|
|
31
|
+
raise ValueError("Only rec_batch_size=1 is supported; lists are processed serially")
|
|
32
|
+
if offline is not True:
|
|
33
|
+
raise ValueError("Only offline=True is supported; no online downloader is implemented")
|
|
34
|
+
if det_backend not in (None,"onnx"):
|
|
35
|
+
raise ValueError("det_backend must be None or 'onnx'")
|
|
36
|
+
if det_backend is None and det_model_dir is not None:
|
|
37
|
+
raise ValueError("det_model_dir requires det_backend='onnx'")
|
|
38
|
+
if det_backend=="onnx" and det_model_dir is None:
|
|
39
|
+
raise ValueError("det_backend='onnx' requires det_model_dir")
|
|
40
|
+
if isinstance(page_max_side,bool) or not isinstance(page_max_side,int) or page_max_side<0:
|
|
41
|
+
raise ValueError("page_max_side must be an integer >=0")
|
|
42
|
+
self.config = RecognitionConfig.from_preset(preset, rec_threshold=rec_threshold, max_side=max_side)
|
|
43
|
+
self.page_max_side=page_max_side
|
|
44
|
+
self._detector=None
|
|
45
|
+
if rec_backend=="torch":
|
|
46
|
+
from .recognition.torch_backend import TorchRecognizer
|
|
47
|
+
self.device=resolve_device(rec_device)
|
|
48
|
+
weights,dictionary=resolve_assets(model_dir,weights_path,character_dict_path)
|
|
49
|
+
self._recognizer=TorchRecognizer(weights,dictionary,self.device,self.config)
|
|
50
|
+
self.model_id=MODEL_ID
|
|
51
|
+
else:
|
|
52
|
+
if weights_path is not None:
|
|
53
|
+
raise ValueError("ONNX requires model_dir, not a safetensors weights_path")
|
|
54
|
+
from .recognition.onnx_backend import OnnxRecognizer
|
|
55
|
+
self._recognizer=OnnxRecognizer(model_dir,character_dict_path,rec_device,self.config,threads)
|
|
56
|
+
self.device=self._recognizer.device
|
|
57
|
+
self.model_id=self._recognizer.model_id
|
|
58
|
+
if det_backend=="onnx" and det_config is None:
|
|
59
|
+
from .detection import DetectionConfig
|
|
60
|
+
det_config=DetectionConfig(intra_threads=threads)
|
|
61
|
+
if det_backend=="onnx":
|
|
62
|
+
from .detection import TextDetector
|
|
63
|
+
self._detector=TextDetector(det_model_dir,model_id=det_model_id,device=det_device,config=det_config,offline=offline)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def info(self):
|
|
67
|
+
info={"model_id":self.model_id,"backend":self.backend,"device":str(self.device),
|
|
68
|
+
"precision":"float32","effective_batch_size":1,"offline":True,"config":asdict(self.config)}
|
|
69
|
+
if self._detector is not None:
|
|
70
|
+
info["detector"]=self._detector.info
|
|
71
|
+
info["page_max_side"]=self.page_max_side
|
|
72
|
+
if self.backend=="onnx": info["recognizer"]=self._recognizer.info
|
|
73
|
+
return info
|
|
74
|
+
|
|
75
|
+
def _recognize_loaded(self,image,*,resize):
|
|
76
|
+
if self._closed: raise RuntimeError("OpenOCRMLT is closed")
|
|
77
|
+
height,width=image.shape[:2]
|
|
78
|
+
if resize:
|
|
79
|
+
image=resize_max_side(image,self.config.max_side)
|
|
80
|
+
raw,score,termination,steps=self._recognizer.recognize(image)
|
|
81
|
+
accepted=score>=self.config.rec_threshold
|
|
82
|
+
status="empty" if not raw else ("ok" if accepted else "filtered")
|
|
83
|
+
return RecognitionResult(raw if accepted else "",raw,score,status,termination,steps,
|
|
84
|
+
(width,height),self.model_id,self.backend,str(self.device))
|
|
85
|
+
|
|
86
|
+
def recognize(self,images,*,color_order="BGR"):
|
|
87
|
+
"""Unchanged rec-only semantics, independent of any configured detector."""
|
|
88
|
+
if isinstance(images,(str,os.PathLike,Image.Image,np.ndarray)):
|
|
89
|
+
images=[images]
|
|
90
|
+
if not isinstance(images,(list,tuple)):
|
|
91
|
+
raise TypeError("images must be an image or a list/tuple of images")
|
|
92
|
+
loaded=[read_image(image,color_order) for image in images]
|
|
93
|
+
return [self._recognize_loaded(image,resize=True) for image in loaded]
|
|
94
|
+
|
|
95
|
+
def _detect_page(self,image):
|
|
96
|
+
if self._detector is None:
|
|
97
|
+
raise RuntimeError("Configure det_backend='onnx' and det_model_dir before detect/ocr")
|
|
98
|
+
height,width=image.shape[:2]
|
|
99
|
+
working=resize_max_side(image,self.page_max_side)
|
|
100
|
+
detections=self._detector._detect_bgr(working)
|
|
101
|
+
sy,sx=height/working.shape[0],width/working.shape[1]
|
|
102
|
+
mapped=[DetectionResult(tuple((min(max(x*sx,0.0),float(width)),min(max(y*sy,0.0),float(height))) for x,y in d.points),
|
|
103
|
+
d.score,d.source_id,d.model_id,d.backend,d.device) for d in detections]
|
|
104
|
+
return working,detections,mapped
|
|
105
|
+
|
|
106
|
+
def detect(self,image,*,color_order="BGR"):
|
|
107
|
+
_,_,mapped=self._detect_page(read_image(image,color_order))
|
|
108
|
+
return mapped
|
|
109
|
+
|
|
110
|
+
def ocr(self,image,*,color_order="BGR"):
|
|
111
|
+
bgr=read_image(image,color_order)
|
|
112
|
+
height,width=bgr.shape[:2]
|
|
113
|
+
working,detections,mapped=self._detect_page(bgr)
|
|
114
|
+
items=[]
|
|
115
|
+
for detection,original in zip(detections,mapped):
|
|
116
|
+
crop,error=crop_quad(working,detection.points)
|
|
117
|
+
if error is not None:
|
|
118
|
+
items.append(OCRLine(original,None,error))
|
|
119
|
+
else:
|
|
120
|
+
# Legacy whole-page pipeline resizes the page, not every crop.
|
|
121
|
+
result=self._recognize_loaded(crop,resize=False)
|
|
122
|
+
items.append(OCRLine(original,result,None))
|
|
123
|
+
return OCRResult((width,height),tuple(items),self.info)
|
|
124
|
+
|
|
125
|
+
def __call__(self,image,*,color_order="BGR"):
|
|
126
|
+
"""One crop without a detector; one page with an explicitly configured detector."""
|
|
127
|
+
if getattr(self,"_detector",None) is not None:
|
|
128
|
+
return self.ocr(image,color_order=color_order)
|
|
129
|
+
return self.recognize([image],color_order=color_order)[0]
|
|
130
|
+
|
|
131
|
+
def close(self):
|
|
132
|
+
if self._detector is not None:
|
|
133
|
+
self._detector.close()
|
|
134
|
+
if self._recognizer is not None:
|
|
135
|
+
if hasattr(self._recognizer,"close"):self._recognizer.close()
|
|
136
|
+
elif hasattr(self._recognizer,"model"):self._recognizer.model=None
|
|
137
|
+
self._closed=True
|
|
138
|
+
|
|
139
|
+
def __enter__(self):
|
|
140
|
+
if self._closed:raise RuntimeError("OpenOCRMLT is closed")
|
|
141
|
+
return self
|
|
142
|
+
|
|
143
|
+
def __exit__(self,*args):
|
|
144
|
+
self.close()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class OpenOCRMLT(_ConfiguredOCR):
|
|
148
|
+
"""Use an explicit model configuration or select a task with lazy setup."""
|
|
149
|
+
|
|
150
|
+
def __init__(
|
|
151
|
+
self, *, task=None, device=None, offline=None, cache_dir=None,
|
|
152
|
+
model_source=None, model_dir=None, det_model_dir=None, **options
|
|
153
|
+
):
|
|
154
|
+
self._task = task
|
|
155
|
+
if task is None:
|
|
156
|
+
if cache_dir is not None or model_source is not None:
|
|
157
|
+
raise ValueError("cache_dir and model_source require a task")
|
|
158
|
+
super().__init__(
|
|
159
|
+
device=device, offline=True if offline is None else offline,
|
|
160
|
+
model_dir=model_dir, det_model_dir=det_model_dir, **options
|
|
161
|
+
)
|
|
162
|
+
return
|
|
163
|
+
|
|
164
|
+
if task not in ("ocr", "det", "rec"):
|
|
165
|
+
raise ValueError("task must be ocr, det, or rec")
|
|
166
|
+
if offline is not None and not isinstance(offline, bool):
|
|
167
|
+
raise TypeError("offline must be a bool")
|
|
168
|
+
if task == "det":
|
|
169
|
+
unsupported = set(options) - {"det_model_id", "det_config", "threads", "det_device"}
|
|
170
|
+
if unsupported or model_dir is not None:
|
|
171
|
+
raise ValueError("The detection task accepts detector configuration only")
|
|
172
|
+
elif task == "rec" and (det_model_dir is not None or options.get("det_backend") is not None):
|
|
173
|
+
raise ValueError("The recognition task accepts recognizer configuration only")
|
|
174
|
+
if options.get("rec_backend", "onnx") != "onnx":
|
|
175
|
+
raise ValueError("Task mode uses ONNX; provide explicit model paths for Torch")
|
|
176
|
+
|
|
177
|
+
self._requested_device = device if device is not None else "auto"
|
|
178
|
+
self._offline = bool(offline)
|
|
179
|
+
self._cache_dir = cache_dir
|
|
180
|
+
self._model_source = model_source
|
|
181
|
+
self._model_dir = model_dir
|
|
182
|
+
self._det_model_dir = det_model_dir
|
|
183
|
+
self._options = options
|
|
184
|
+
self._engine = None
|
|
185
|
+
self._closed = False
|
|
186
|
+
|
|
187
|
+
def _initialize(self):
|
|
188
|
+
from .model_fetch import fetch_models
|
|
189
|
+
from .onnx_runtime import _CUDAUnavailableError, resolve_ort_device
|
|
190
|
+
|
|
191
|
+
model_dir = self._model_dir
|
|
192
|
+
det_model_dir = self._det_model_dir
|
|
193
|
+
if (self._task != "det" and model_dir is None) or (
|
|
194
|
+
self._task != "rec" and det_model_dir is None
|
|
195
|
+
):
|
|
196
|
+
assets = fetch_models(
|
|
197
|
+
source=self._model_source, cache_dir=self._cache_dir, offline=self._offline
|
|
198
|
+
)
|
|
199
|
+
if model_dir is None:
|
|
200
|
+
model_dir = assets["recognition_dir"]
|
|
201
|
+
if det_model_dir is None:
|
|
202
|
+
det_model_dir = assets["detector_dir"]
|
|
203
|
+
|
|
204
|
+
def create(device):
|
|
205
|
+
if self._task == "det":
|
|
206
|
+
from .detection import DetectionConfig, TextDetector
|
|
207
|
+
|
|
208
|
+
config = self._options.get("det_config")
|
|
209
|
+
if config is None:
|
|
210
|
+
config = DetectionConfig(intra_threads=self._options.get("threads", 4))
|
|
211
|
+
return TextDetector(
|
|
212
|
+
det_model_dir, config=config,
|
|
213
|
+
model_id=self._options.get("det_model_id", "ppocrv6-medium-det-bce-v1"),
|
|
214
|
+
device=self._options.get("det_device") or device,
|
|
215
|
+
)
|
|
216
|
+
return _ConfiguredOCR(
|
|
217
|
+
model_dir=model_dir,
|
|
218
|
+
det_model_dir=det_model_dir if self._task == "ocr" else None,
|
|
219
|
+
device=device, **self._options
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
requested = self._requested_device
|
|
223
|
+
device = resolve_ort_device(requested)
|
|
224
|
+
try:
|
|
225
|
+
return create(device)
|
|
226
|
+
except _CUDAUnavailableError:
|
|
227
|
+
if requested != "auto" or device == "cpu" or any(
|
|
228
|
+
self._options.get(key) for key in ("det_device", "rec_device")
|
|
229
|
+
):
|
|
230
|
+
raise
|
|
231
|
+
return create("cpu")
|
|
232
|
+
|
|
233
|
+
def _task_engine(self, task):
|
|
234
|
+
if self._closed:
|
|
235
|
+
raise RuntimeError("OpenOCRMLT is closed")
|
|
236
|
+
if self._task != task:
|
|
237
|
+
raise ValueError(f"This instance was configured for task={self._task!r}")
|
|
238
|
+
if self._engine is None:
|
|
239
|
+
self._engine = self._initialize()
|
|
240
|
+
return self._engine
|
|
241
|
+
|
|
242
|
+
def __call__(self, image=None, *, image_path=None, color_order="BGR"):
|
|
243
|
+
if (image is None) == (image_path is None):
|
|
244
|
+
raise ValueError("Provide exactly one image or image_path")
|
|
245
|
+
image = image if image_path is None else image_path
|
|
246
|
+
if self._task is None:
|
|
247
|
+
return super().__call__(image, color_order=color_order)
|
|
248
|
+
method = {"ocr": self.ocr, "det": self.detect, "rec": self.recognize}[self._task]
|
|
249
|
+
return method(image, color_order=color_order)
|
|
250
|
+
|
|
251
|
+
def recognize(self, images, *, color_order="BGR"):
|
|
252
|
+
engine = super() if self._task is None else self._task_engine("rec")
|
|
253
|
+
return engine.recognize(images, color_order=color_order)
|
|
254
|
+
|
|
255
|
+
def detect(self, image, *, color_order="BGR"):
|
|
256
|
+
engine = super() if self._task is None else self._task_engine("det")
|
|
257
|
+
return engine.detect(image, color_order=color_order)
|
|
258
|
+
|
|
259
|
+
def ocr(self, image, *, color_order="BGR"):
|
|
260
|
+
engine = super() if self._task is None else self._task_engine("ocr")
|
|
261
|
+
return engine.ocr(image, color_order=color_order)
|
|
262
|
+
|
|
263
|
+
@property
|
|
264
|
+
def info(self):
|
|
265
|
+
if self._task is None:
|
|
266
|
+
return super().info
|
|
267
|
+
info = {} if self._engine is None else self._engine.info
|
|
268
|
+
return {**info, "task": self._task, "requested_device": self._requested_device}
|
|
269
|
+
|
|
270
|
+
def close(self):
|
|
271
|
+
if self._task is None:
|
|
272
|
+
return super().close()
|
|
273
|
+
if self._engine is not None:
|
|
274
|
+
self._engine.close()
|
|
275
|
+
self._closed = True
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Third-Party Model Sources and Licensing
|
|
2
|
+
|
|
3
|
+
## ScriptMoE Recognition
|
|
4
|
+
|
|
5
|
+
Recognition models are derived from [ScriptMoE](https://github.com/YesianRohn/ScriptMoE) at upstream revision `5dde99867aaee6b4af3e75a3020b225eab17ac53`. ONNX conversion preserves the character dictionary and autoregressive decoding rules and uses KV caching and optimized MoE execution.
|
|
6
|
+
|
|
7
|
+
| Artifact | SHA256 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Original recognition weights | 60c74a924404b652c3a9550ec370c74d78850151785341729bdac268c014650d |
|
|
10
|
+
| Character dictionary | 7b4eb2ca5fd6c9b6c6ecf423f69d35d8da48088697303e53624af196ee9ab6c0 |
|
|
11
|
+
|
|
12
|
+
## PP-OCRv6 Medium Detection
|
|
13
|
+
|
|
14
|
+
The detector is distributed by Paddle as [PP-OCRv6_medium_det_onnx.tar](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/tmp/PP-OCRv6_medium_det_onnx.tar).
|
|
15
|
+
|
|
16
|
+
| Property | Value |
|
|
17
|
+
|---|---|
|
|
18
|
+
| File | inference.onnx |
|
|
19
|
+
| Size | 62,026,563 bytes |
|
|
20
|
+
| SHA256 | a0d14865d3a297970899b5c246f0e47c43879bb406c3a1fa4e505aba84b134e4 |
|
|
21
|
+
|
|
22
|
+
The accompanying Python package adapts detection preprocessing and postprocessing from [ppocrv6_onnx](https://github.com/AIwork4me/ppocrv6_onnx), revision `d638eb0bb5d8222522abcc1bae4394cbeeb636f0`, under its MIT license. The package includes the license text for that code.
|
|
23
|
+
|
|
24
|
+
## Licensing Status
|
|
25
|
+
|
|
26
|
+
A unified redistribution license has not been specified for this combined model bundle. The MIT license of the detection adapter applies to that code; model weights have separate licensing requirements.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"models": {
|
|
4
|
+
"ppocrv6-tiny-det-bce-v1": {
|
|
5
|
+
"filename": "inference.onnx",
|
|
6
|
+
"size": 1780621,
|
|
7
|
+
"sha256": "a56a3430a96a6c691f8bfbbb297208bb9573c3d70083d6382071cbd92d0a152e",
|
|
8
|
+
"source_url": "https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/tmp/PP-OCRv6_tiny_det_onnx.tar",
|
|
9
|
+
"source_revision": null,
|
|
10
|
+
"artifact_etag": "700445c8a6ebcaeac88d4622ddb68dba",
|
|
11
|
+
"runtime_profile": "ppocrv6-reference-v1",
|
|
12
|
+
"config_sha256": "626e4e3b45bd2f943d2282114b461ef5804f4620ae54d7ff7ff9fb6365f3a608",
|
|
13
|
+
"license_status": "official family model card states Apache-2.0; BCE binary redistribution not independently resolved"
|
|
14
|
+
},
|
|
15
|
+
"ppocrv5-server-det-hf-v1": {
|
|
16
|
+
"filename": "inference.onnx",
|
|
17
|
+
"size": 88116791,
|
|
18
|
+
"sha256": "10803475a591f7dc623e24670fb5752ec94d39a1f8cf069aac1b6f0ce19cfc85",
|
|
19
|
+
"source_url": "https://huggingface.co/PaddlePaddle/PP-OCRv5_server_det_onnx",
|
|
20
|
+
"source_revision": "dcf248c4dcc064c6d030db241255f9e8fbc6733a",
|
|
21
|
+
"runtime_profile": "ppocrv6-reference-v1",
|
|
22
|
+
"license_status": "official model card Apache-2.0; no public release in this task"
|
|
23
|
+
},
|
|
24
|
+
"ppocrv6-medium-det-bce-v1": {
|
|
25
|
+
"name": "inference.onnx",
|
|
26
|
+
"size": 62026563,
|
|
27
|
+
"sha256": "a0d14865d3a297970899b5c246f0e47c43879bb406c3a1fa4e505aba84b134e4",
|
|
28
|
+
"filename": "inference.onnx",
|
|
29
|
+
"source_url": "https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/tmp/PP-OCRv6_medium_det_onnx.tar",
|
|
30
|
+
"source_revision": null,
|
|
31
|
+
"source_etag": "\"33e0718cf119c8fcc545eb249bc69e06\"",
|
|
32
|
+
"archive_sha256": "46849788192d7882e52440d81cdfa437156f433368411c04b832ffa5433e5418",
|
|
33
|
+
"runtime_profile": "ppocrv6-reference-v1",
|
|
34
|
+
"license_status": "Source attribution preserved; no public redistribution performed"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|