ocr.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. # Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # TODO: Should we use a third-party CLI library to auto-generate command-line
  15. # arguments from the pipeline class, to reduce boilerplate and improve
  16. # maintainability?
  17. import sys
  18. import warnings
  19. from .._utils.cli import (
  20. add_simple_inference_args,
  21. get_subcommand_args,
  22. perform_simple_inference,
  23. str2bool,
  24. )
  25. from .._utils.deprecation import (
  26. DeprecatedOptionAction,
  27. deprecated,
  28. warn_deprecated_param,
  29. )
  30. from .._utils.logging import logger
  31. from .base import PaddleXPipelineWrapper, PipelineCLISubcommandExecutor
  32. from .utils import create_config_from_structure
  33. _DEPRECATED_PARAM_NAME_MAPPING = {
  34. "det_model_dir": "text_detection_model_dir",
  35. "det_limit_side_len": "text_det_limit_side_len",
  36. "det_limit_type": "text_det_limit_type",
  37. "det_db_thresh": "text_det_thresh",
  38. "det_db_box_thresh": "text_det_box_thresh",
  39. "det_db_unclip_ratio": "text_det_unclip_ratio",
  40. "rec_model_dir": "text_recognition_model_dir",
  41. "rec_batch_num": "text_recognition_batch_size",
  42. "use_angle_cls": "use_textline_orientation",
  43. "cls_model_dir": "textline_orientation_model_dir",
  44. "cls_batch_num": "textline_orientation_batch_size",
  45. }
  46. _SUPPORTED_OCR_VERSIONS = ["PP-OCRv3", "PP-OCRv4", "PP-OCRv5"]
  47. # Be comptable with PaddleOCR 2.x interfaces
  48. class PaddleOCR(PaddleXPipelineWrapper):
  49. def __init__(
  50. self,
  51. doc_orientation_classify_model_name=None,
  52. doc_orientation_classify_model_dir=None,
  53. doc_unwarping_model_name=None,
  54. doc_unwarping_model_dir=None,
  55. text_detection_model_name=None,
  56. text_detection_model_dir=None,
  57. textline_orientation_model_name=None,
  58. textline_orientation_model_dir=None,
  59. textline_orientation_batch_size=None,
  60. text_recognition_model_name=None,
  61. text_recognition_model_dir=None,
  62. text_recognition_batch_size=None,
  63. use_doc_orientation_classify=None,
  64. use_doc_unwarping=None,
  65. use_textline_orientation=None,
  66. text_det_limit_side_len=None,
  67. text_det_limit_type=None,
  68. text_det_thresh=None,
  69. text_det_box_thresh=None,
  70. text_det_unclip_ratio=None,
  71. text_det_input_shape=None,
  72. text_rec_score_thresh=None,
  73. return_word_box=None,
  74. text_rec_input_shape=None,
  75. lang=None,
  76. ocr_version=None,
  77. **kwargs,
  78. ):
  79. if ocr_version is not None and ocr_version not in _SUPPORTED_OCR_VERSIONS:
  80. raise ValueError(
  81. f"Invalid OCR version: {ocr_version}. Supported values are {_SUPPORTED_OCR_VERSIONS}."
  82. )
  83. if all(
  84. map(
  85. lambda p: p is None,
  86. (
  87. text_detection_model_name,
  88. text_detection_model_dir,
  89. text_recognition_model_name,
  90. text_recognition_model_dir,
  91. ),
  92. )
  93. ):
  94. if lang is not None or ocr_version is not None:
  95. det_model_name, rec_model_name = self._get_ocr_model_names(
  96. lang, ocr_version
  97. )
  98. if det_model_name is None or rec_model_name is None:
  99. raise ValueError(
  100. f"No models are available for the language {repr(lang)} and OCR version {repr(ocr_version)}."
  101. )
  102. text_detection_model_name = det_model_name
  103. text_recognition_model_name = rec_model_name
  104. else:
  105. if lang is not None or ocr_version is not None:
  106. warnings.warn(
  107. "`lang` and `ocr_version` will be ignored when model names or model directories are not `None`.",
  108. stacklevel=2,
  109. )
  110. params = {
  111. "doc_orientation_classify_model_name": doc_orientation_classify_model_name,
  112. "doc_orientation_classify_model_dir": doc_orientation_classify_model_dir,
  113. "doc_unwarping_model_name": doc_unwarping_model_name,
  114. "doc_unwarping_model_dir": doc_unwarping_model_dir,
  115. "text_detection_model_name": text_detection_model_name,
  116. "text_detection_model_dir": text_detection_model_dir,
  117. "textline_orientation_model_name": textline_orientation_model_name,
  118. "textline_orientation_model_dir": textline_orientation_model_dir,
  119. "textline_orientation_batch_size": textline_orientation_batch_size,
  120. "text_recognition_model_name": text_recognition_model_name,
  121. "text_recognition_model_dir": text_recognition_model_dir,
  122. "text_recognition_batch_size": text_recognition_batch_size,
  123. "use_doc_orientation_classify": use_doc_orientation_classify,
  124. "use_doc_unwarping": use_doc_unwarping,
  125. "use_textline_orientation": use_textline_orientation,
  126. "text_det_limit_side_len": text_det_limit_side_len,
  127. "text_det_limit_type": text_det_limit_type,
  128. "text_det_thresh": text_det_thresh,
  129. "text_det_box_thresh": text_det_box_thresh,
  130. "text_det_unclip_ratio": text_det_unclip_ratio,
  131. "text_det_input_shape": text_det_input_shape,
  132. "text_rec_score_thresh": text_rec_score_thresh,
  133. "return_word_box": return_word_box,
  134. "text_rec_input_shape": text_rec_input_shape,
  135. }
  136. base_params = {}
  137. for name, val in kwargs.items():
  138. if name in _DEPRECATED_PARAM_NAME_MAPPING:
  139. new_name = _DEPRECATED_PARAM_NAME_MAPPING[name]
  140. warn_deprecated_param(name, new_name)
  141. assert (
  142. new_name in params
  143. ), f"{repr(new_name)} is not a valid parameter name."
  144. if params[new_name] is not None:
  145. raise ValueError(
  146. f"`{name}` and `{new_name}` are mutually exclusive."
  147. )
  148. params[new_name] = val
  149. else:
  150. base_params[name] = val
  151. self._params = params
  152. super().__init__(**base_params)
  153. @property
  154. def _paddlex_pipeline_name(self):
  155. return "OCR"
  156. def predict_iter(
  157. self,
  158. input,
  159. *,
  160. use_doc_orientation_classify=None,
  161. use_doc_unwarping=None,
  162. use_textline_orientation=None,
  163. text_det_limit_side_len=None,
  164. text_det_limit_type=None,
  165. text_det_thresh=None,
  166. text_det_box_thresh=None,
  167. text_det_unclip_ratio=None,
  168. text_rec_score_thresh=None,
  169. return_word_box=None,
  170. ):
  171. return self.paddlex_pipeline.predict(
  172. input,
  173. use_doc_orientation_classify=use_doc_orientation_classify,
  174. use_doc_unwarping=use_doc_unwarping,
  175. use_textline_orientation=use_textline_orientation,
  176. text_det_limit_side_len=text_det_limit_side_len,
  177. text_det_limit_type=text_det_limit_type,
  178. text_det_thresh=text_det_thresh,
  179. text_det_box_thresh=text_det_box_thresh,
  180. text_det_unclip_ratio=text_det_unclip_ratio,
  181. text_rec_score_thresh=text_rec_score_thresh,
  182. return_word_box=return_word_box,
  183. )
  184. def predict(
  185. self,
  186. input,
  187. *,
  188. use_doc_orientation_classify=None,
  189. use_doc_unwarping=None,
  190. use_textline_orientation=None,
  191. text_det_limit_side_len=None,
  192. text_det_limit_type=None,
  193. text_det_thresh=None,
  194. text_det_box_thresh=None,
  195. text_det_unclip_ratio=None,
  196. text_rec_score_thresh=None,
  197. return_word_box=None,
  198. ):
  199. return list(
  200. self.predict_iter(
  201. input,
  202. use_doc_orientation_classify=use_doc_orientation_classify,
  203. use_doc_unwarping=use_doc_unwarping,
  204. use_textline_orientation=use_textline_orientation,
  205. text_det_limit_side_len=text_det_limit_side_len,
  206. text_det_limit_type=text_det_limit_type,
  207. text_det_thresh=text_det_thresh,
  208. text_det_box_thresh=text_det_box_thresh,
  209. text_det_unclip_ratio=text_det_unclip_ratio,
  210. text_rec_score_thresh=text_rec_score_thresh,
  211. return_word_box=return_word_box,
  212. )
  213. )
  214. @deprecated("Please use `predict` instead.")
  215. def ocr(self, img, **kwargs):
  216. return self.predict(img, **kwargs)
  217. @classmethod
  218. def get_cli_subcommand_executor(cls):
  219. return PaddleOCRCLISubcommandExecutor()
  220. def _get_paddlex_config_overrides(self):
  221. STRUCTURE = {
  222. "SubPipelines.DocPreprocessor.SubModules.DocOrientationClassify.model_name": self._params[
  223. "doc_orientation_classify_model_name"
  224. ],
  225. "SubPipelines.DocPreprocessor.SubModules.DocOrientationClassify.model_dir": self._params[
  226. "doc_orientation_classify_model_dir"
  227. ],
  228. "SubPipelines.DocPreprocessor.SubModules.DocUnwarping.model_name": self._params[
  229. "doc_unwarping_model_name"
  230. ],
  231. "SubPipelines.DocPreprocessor.SubModules.DocUnwarping.model_dir": self._params[
  232. "doc_unwarping_model_dir"
  233. ],
  234. "SubModules.TextDetection.model_name": self._params[
  235. "text_detection_model_name"
  236. ],
  237. "SubModules.TextDetection.model_dir": self._params[
  238. "text_detection_model_dir"
  239. ],
  240. "SubModules.TextLineOrientation.model_name": self._params[
  241. "textline_orientation_model_name"
  242. ],
  243. "SubModules.TextLineOrientation.model_dir": self._params[
  244. "textline_orientation_model_dir"
  245. ],
  246. "SubModules.TextLineOrientation.batch_size": self._params[
  247. "textline_orientation_batch_size"
  248. ],
  249. "SubModules.TextRecognition.model_name": self._params[
  250. "text_recognition_model_name"
  251. ],
  252. "SubModules.TextRecognition.model_dir": self._params[
  253. "text_recognition_model_dir"
  254. ],
  255. "SubModules.TextRecognition.batch_size": self._params[
  256. "text_recognition_batch_size"
  257. ],
  258. "SubPipelines.DocPreprocessor.use_doc_orientation_classify": self._params[
  259. "use_doc_orientation_classify"
  260. ],
  261. "SubPipelines.DocPreprocessor.use_doc_unwarping": self._params[
  262. "use_doc_unwarping"
  263. ],
  264. "use_doc_preprocessor": self._params["use_doc_orientation_classify"]
  265. or self._params["use_doc_unwarping"],
  266. "use_textline_orientation": self._params["use_textline_orientation"],
  267. "SubModules.TextDetection.limit_side_len": self._params[
  268. "text_det_limit_side_len"
  269. ],
  270. "SubModules.TextDetection.limit_type": self._params["text_det_limit_type"],
  271. "SubModules.TextDetection.thresh": self._params["text_det_thresh"],
  272. "SubModules.TextDetection.box_thresh": self._params["text_det_box_thresh"],
  273. "SubModules.TextDetection.unclip_ratio": self._params[
  274. "text_det_unclip_ratio"
  275. ],
  276. "SubModules.TextDetection.input_shape": self._params[
  277. "text_det_input_shape"
  278. ],
  279. "SubModules.TextRecognition.score_thresh": self._params[
  280. "text_rec_score_thresh"
  281. ],
  282. "SubModules.TextRecognition.return_word_box": self._params[
  283. "return_word_box"
  284. ],
  285. "SubModules.TextRecognition.input_shape": self._params[
  286. "text_rec_input_shape"
  287. ],
  288. }
  289. return create_config_from_structure(STRUCTURE)
  290. def _get_ocr_model_names(self, lang, ppocr_version):
  291. LATIN_LANGS = [
  292. "af",
  293. "az",
  294. "bs",
  295. "cs",
  296. "cy",
  297. "da",
  298. "de",
  299. "es",
  300. "et",
  301. "fr",
  302. "ga",
  303. "hr",
  304. "hu",
  305. "id",
  306. "is",
  307. "it",
  308. "ku",
  309. "la",
  310. "lt",
  311. "lv",
  312. "mi",
  313. "ms",
  314. "mt",
  315. "nl",
  316. "no",
  317. "oc",
  318. "pi",
  319. "pl",
  320. "pt",
  321. "ro",
  322. "rs_latin",
  323. "sk",
  324. "sl",
  325. "sq",
  326. "sv",
  327. "sw",
  328. "tl",
  329. "tr",
  330. "uz",
  331. "vi",
  332. "french",
  333. "german",
  334. "fi",
  335. "eu",
  336. "gl",
  337. "lb",
  338. "rm",
  339. "ca",
  340. "qu",
  341. ]
  342. ARABIC_LANGS = ["ar", "fa", "ug", "ur", "ps", "ku", "sd", "bal"]
  343. ESLAV_LANGS = ["ru", "be", "uk"]
  344. CYRILLIC_LANGS = [
  345. "ru",
  346. "rs_cyrillic",
  347. "be",
  348. "bg",
  349. "uk",
  350. "mn",
  351. "abq",
  352. "ady",
  353. "kbd",
  354. "ava",
  355. "dar",
  356. "inh",
  357. "che",
  358. "lbe",
  359. "lez",
  360. "tab",
  361. "kk",
  362. "ky",
  363. "tg",
  364. "mk",
  365. "tt",
  366. "cv",
  367. "ba",
  368. "mhr",
  369. "mo",
  370. "udm",
  371. "kv",
  372. "os",
  373. "bua",
  374. "xal",
  375. "tyv",
  376. "sah",
  377. "kaa",
  378. ]
  379. DEVANAGARI_LANGS = [
  380. "hi",
  381. "mr",
  382. "ne",
  383. "bh",
  384. "mai",
  385. "ang",
  386. "bho",
  387. "mah",
  388. "sck",
  389. "new",
  390. "gom",
  391. "sa",
  392. "bgc",
  393. ]
  394. SPECIFIC_LANGS = [
  395. "ch",
  396. "en",
  397. "korean",
  398. "japan",
  399. "chinese_cht",
  400. "te",
  401. "ka",
  402. "ta",
  403. ]
  404. if lang is None:
  405. lang = "ch"
  406. if ppocr_version is None:
  407. if (
  408. lang
  409. in [
  410. "ch",
  411. "chinese_cht",
  412. "en",
  413. "japan",
  414. "korean",
  415. "th",
  416. "el",
  417. "te",
  418. "ta",
  419. ]
  420. + LATIN_LANGS
  421. + ESLAV_LANGS
  422. + ARABIC_LANGS
  423. + CYRILLIC_LANGS
  424. + DEVANAGARI_LANGS
  425. ):
  426. ppocr_version = "PP-OCRv5"
  427. elif lang in (SPECIFIC_LANGS):
  428. ppocr_version = "PP-OCRv3"
  429. else:
  430. # Unknown language specified
  431. return None, None
  432. if ppocr_version == "PP-OCRv5":
  433. rec_lang, rec_model_name = None, None
  434. if lang in ("ch", "chinese_cht", "japan"):
  435. rec_model_name = "PP-OCRv5_server_rec"
  436. elif lang == "en":
  437. rec_model_name = "en_PP-OCRv5_mobile_rec"
  438. elif lang in LATIN_LANGS:
  439. rec_lang = "latin"
  440. elif lang in ESLAV_LANGS:
  441. rec_lang = "eslav"
  442. elif lang in ARABIC_LANGS:
  443. rec_lang = "arabic"
  444. elif lang in CYRILLIC_LANGS:
  445. rec_lang = "cyrillic"
  446. elif lang in DEVANAGARI_LANGS:
  447. rec_lang = "devanagari"
  448. elif lang == "korean":
  449. rec_lang = "korean"
  450. elif lang == "th":
  451. rec_lang = "th"
  452. elif lang == "el":
  453. rec_lang = "el"
  454. elif lang == "te":
  455. rec_lang = "te"
  456. elif lang == "ta":
  457. rec_lang = "ta"
  458. if rec_lang is not None:
  459. rec_model_name = f"{rec_lang}_PP-OCRv5_mobile_rec"
  460. return "PP-OCRv5_server_det", rec_model_name
  461. elif ppocr_version == "PP-OCRv4":
  462. if lang == "ch":
  463. return "PP-OCRv4_mobile_det", "PP-OCRv4_mobile_rec"
  464. elif lang == "en":
  465. return "PP-OCRv4_mobile_det", "en_PP-OCRv4_mobile_rec"
  466. else:
  467. return None, None
  468. else:
  469. # PP-OCRv3
  470. rec_lang = None
  471. if lang in LATIN_LANGS:
  472. rec_lang = "latin"
  473. elif lang in ARABIC_LANGS:
  474. rec_lang = "arabic"
  475. elif lang in CYRILLIC_LANGS:
  476. rec_lang = "cyrillic"
  477. elif lang in DEVANAGARI_LANGS:
  478. rec_lang = "devanagari"
  479. else:
  480. if lang in SPECIFIC_LANGS:
  481. rec_lang = lang
  482. rec_model_name = None
  483. if rec_lang == "ch":
  484. rec_model_name = "PP-OCRv3_mobile_rec"
  485. elif rec_lang is not None:
  486. rec_model_name = f"{rec_lang}_PP-OCRv3_mobile_rec"
  487. return "PP-OCRv3_mobile_det", rec_model_name
  488. class PaddleOCRCLISubcommandExecutor(PipelineCLISubcommandExecutor):
  489. @property
  490. def subparser_name(self):
  491. return "ocr"
  492. def _update_subparser(self, subparser):
  493. add_simple_inference_args(subparser)
  494. subparser.add_argument(
  495. "--doc_orientation_classify_model_name",
  496. type=str,
  497. help="Name of the document image orientation classification model.",
  498. )
  499. subparser.add_argument(
  500. "--doc_orientation_classify_model_dir",
  501. type=str,
  502. help="Path to the document image orientation classification model directory.",
  503. )
  504. subparser.add_argument(
  505. "--doc_unwarping_model_name",
  506. type=str,
  507. help="Name of the text image unwarping model.",
  508. )
  509. subparser.add_argument(
  510. "--doc_unwarping_model_dir",
  511. type=str,
  512. help="Path to the image unwarping model directory.",
  513. )
  514. subparser.add_argument(
  515. "--text_detection_model_name",
  516. type=str,
  517. help="Name of the text detection model.",
  518. )
  519. subparser.add_argument(
  520. "--text_detection_model_dir",
  521. type=str,
  522. help="Path to the text detection model directory.",
  523. )
  524. subparser.add_argument(
  525. "--textline_orientation_model_name",
  526. type=str,
  527. help="Name of the text line orientation classification model.",
  528. )
  529. subparser.add_argument(
  530. "--textline_orientation_model_dir",
  531. type=str,
  532. help="Path to the text line orientation classification model directory.",
  533. )
  534. subparser.add_argument(
  535. "--textline_orientation_batch_size",
  536. type=int,
  537. help="Batch size for the text line orientation classification model.",
  538. )
  539. subparser.add_argument(
  540. "--text_recognition_model_name",
  541. type=str,
  542. help="Name of the text recognition model.",
  543. )
  544. subparser.add_argument(
  545. "--text_recognition_model_dir",
  546. type=str,
  547. help="Path to the text recognition model directory.",
  548. )
  549. subparser.add_argument(
  550. "--text_recognition_batch_size",
  551. type=int,
  552. help="Batch size for the text recognition model.",
  553. )
  554. subparser.add_argument(
  555. "--use_doc_orientation_classify",
  556. type=str2bool,
  557. help="Whether to use document image orientation classification.",
  558. )
  559. subparser.add_argument(
  560. "--use_doc_unwarping",
  561. type=str2bool,
  562. help="Whether to use text image unwarping.",
  563. )
  564. subparser.add_argument(
  565. "--use_textline_orientation",
  566. type=str2bool,
  567. help="Whether to use text line orientation classification.",
  568. )
  569. subparser.add_argument(
  570. "--text_det_limit_side_len",
  571. type=int,
  572. help="This sets a limit on the side length of the input image for the text detection model.",
  573. )
  574. subparser.add_argument(
  575. "--text_det_limit_type",
  576. type=str,
  577. help="This determines how the side length limit is applied to the input image before feeding it into the text deteciton model.",
  578. )
  579. subparser.add_argument(
  580. "--text_det_thresh",
  581. type=float,
  582. help="Detection pixel threshold for the text detection model. Pixels with scores greater than this threshold in the output probability map are considered text pixels.",
  583. )
  584. subparser.add_argument(
  585. "--text_det_box_thresh",
  586. type=float,
  587. help="Detection box threshold for the text detection model. A detection result is considered a text region if the average score of all pixels within the border of the result is greater than this threshold.",
  588. )
  589. subparser.add_argument(
  590. "--text_det_unclip_ratio",
  591. type=float,
  592. help="Text detection expansion coefficient, which expands the text region using this method. The larger the value, the larger the expansion area.",
  593. )
  594. subparser.add_argument(
  595. "--text_det_input_shape",
  596. nargs=3,
  597. type=int,
  598. metavar=("C", "H", "W"),
  599. help="Input shape of the text detection model.",
  600. )
  601. subparser.add_argument(
  602. "--text_rec_score_thresh",
  603. type=float,
  604. help="Text recognition threshold. Text results with scores greater than this threshold are retained.",
  605. )
  606. subparser.add_argument(
  607. "--return_word_box",
  608. type=str2bool,
  609. help="Whether to return the coordinates of the recognition result.",
  610. )
  611. subparser.add_argument(
  612. "--text_rec_input_shape",
  613. nargs=3,
  614. type=int,
  615. metavar=("C", "H", "W"),
  616. help="Input shape of the text recognition model.",
  617. )
  618. subparser.add_argument(
  619. "--lang", type=str, help="Language in the input image for OCR processing."
  620. )
  621. subparser.add_argument(
  622. "--ocr_version",
  623. type=str,
  624. choices=_SUPPORTED_OCR_VERSIONS,
  625. help="PP-OCR version to use.",
  626. )
  627. deprecated_arg_types = {
  628. "det_model_dir": str,
  629. "det_limit_side_len": int,
  630. "det_limit_type": str,
  631. "det_db_thresh": float,
  632. "det_db_box_thresh": float,
  633. "det_db_unclip_ratio": float,
  634. "rec_model_dir": str,
  635. "rec_batch_num": int,
  636. "use_angle_cls": str2bool,
  637. "cls_model_dir": str,
  638. "cls_batch_num": int,
  639. }
  640. for name, new_name in _DEPRECATED_PARAM_NAME_MAPPING.items():
  641. assert name in deprecated_arg_types, name
  642. subparser.add_argument(
  643. "--" + name,
  644. action=DeprecatedOptionAction,
  645. type=str,
  646. help=f"[Deprecated] Please use `--{new_name}` instead.",
  647. )
  648. def execute_with_args(self, args):
  649. params = get_subcommand_args(args)
  650. for name, new_name in _DEPRECATED_PARAM_NAME_MAPPING.items():
  651. assert name in params
  652. val = params[name]
  653. new_val = params[new_name]
  654. if val is not None and new_val is not None:
  655. logger.error(
  656. "`--%s` and `--%s` are mutually exclusive.", name, new_name
  657. )
  658. sys.exit(2)
  659. if val is None:
  660. params.pop(name)
  661. perform_simple_inference(PaddleOCR, params)