args.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import argparse
  2. import os
  3. from urllib.parse import unquote
  4. from .detection import DETECTORS
  5. from .ocr import OCRS
  6. from .inpainting import INPAINTERS
  7. from .translators import VALID_LANGUAGES, TRANSLATORS, TranslatorChain
  8. from .upscaling import UPSCALERS
  9. from .colorization import COLORIZERS
  10. from .save import OUTPUT_FORMATS
  11. def url_decode(s):
  12. s = unquote(s)
  13. if s.startswith('file:///'):
  14. s = s[len('file://'):]
  15. return s
  16. # Additional argparse types
  17. def path(string):
  18. if not string:
  19. return ''
  20. s = url_decode(os.path.expanduser(string))
  21. if not os.path.exists(s):
  22. raise argparse.ArgumentTypeError(f'No such file or directory: "{string}"')
  23. return s
  24. def file_path(string):
  25. if not string:
  26. return ''
  27. s = url_decode(os.path.expanduser(string))
  28. if not os.path.exists(s):
  29. raise argparse.ArgumentTypeError(f'No such file: "{string}"')
  30. return s
  31. def dir_path(string):
  32. if not string:
  33. return ''
  34. s = url_decode(os.path.expanduser(string))
  35. if not os.path.exists(s):
  36. raise argparse.ArgumentTypeError(f'No such directory: "{string}"')
  37. return s
  38. # def choice_chain(choices):
  39. # """Argument type for string chains from choices separated by ':'. Example: 'choice1:choice2:choice3'"""
  40. # def _func(string):
  41. # if choices is not None:
  42. # for s in string.split(':') or ['']:
  43. # if s not in choices:
  44. # raise argparse.ArgumentTypeError(f'Invalid choice: %s (choose from %s)' % (s, ', '.join(map(repr, choices))))
  45. # return string
  46. # return _func
  47. def translator_chain(string):
  48. try:
  49. return TranslatorChain(string)
  50. except ValueError as e:
  51. raise argparse.ArgumentTypeError(e)
  52. except Exception:
  53. raise argparse.ArgumentTypeError(f'Invalid translator_chain value: "{string}". Example usage: --translator "google:sugoi" -l "JPN:ENG"')
  54. class HelpFormatter(argparse.HelpFormatter):
  55. INDENT_INCREMENT = 2
  56. MAX_HELP_POSITION = 24
  57. WIDTH = None
  58. def __init__(self, prog: str, indent_increment: int = 2, max_help_position: int = 24, width: int = None):
  59. super().__init__(prog, self.INDENT_INCREMENT, self.MAX_HELP_POSITION, self.WIDTH)
  60. def _format_action_invocation(self, action: argparse.Action) -> str:
  61. if action.option_strings:
  62. # if the Optional doesn't take a value, format is:
  63. # -s, --long
  64. if action.nargs == 0:
  65. return ', '.join(action.option_strings)
  66. # if the Optional takes a value, format is:
  67. # -s, --long ARGS
  68. else:
  69. default = self._get_default_metavar_for_optional(action)
  70. args_string = self._format_args(action, default)
  71. return ', '.join(action.option_strings) + ' ' + args_string
  72. else:
  73. return super()._format_action_invocation(action)
  74. parser = argparse.ArgumentParser(prog='manga_translator', description='Seamlessly translate mangas into a chosen language', formatter_class=HelpFormatter)
  75. parser.add_argument('-m', '--mode', default='batch', type=str, choices=['demo', 'batch', 'web', 'web_client', 'ws', 'api'], help='Run demo in single image demo mode (demo), batch translation mode (batch), web service mode (web)')
  76. parser.add_argument('-i', '--input', default=None, type=path, nargs='+', help='Path to an image file if using demo mode, or path to an image folder if using batch mode')
  77. parser.add_argument('-o', '--dest', default='', type=str, help='Path to the destination folder for translated images in batch mode')
  78. parser.add_argument('-l', '--target-lang', default='CHS', type=str, choices=VALID_LANGUAGES, help='Destination language')
  79. parser.add_argument('-v', '--verbose', action='store_true', help='Print debug info and save intermediate images in result folder')
  80. parser.add_argument('-f', '--format', default=None, choices=OUTPUT_FORMATS, help='Output format of the translation.')
  81. parser.add_argument('--attempts', default=0, type=int, help='Retry attempts on encountered error. -1 means infinite times.')
  82. parser.add_argument('--ignore-errors', action='store_true', help='Skip image on encountered error.')
  83. parser.add_argument('--overwrite', action='store_true', help='Overwrite already translated images in batch mode.')
  84. parser.add_argument('--skip-no-text', action='store_true', help='Skip image without text (Will not be saved).')
  85. parser.add_argument('--model-dir', default=None, type=dir_path, help='Model directory (by default ./models in project root)')
  86. parser.add_argument('--skip-lang', default=None, type=str, help='Skip translation if source image is one of the provide languages, use comma to separate multiple languages. Example: JPN,ENG')
  87. g = parser.add_mutually_exclusive_group()
  88. g.add_argument('--use-gpu', action='store_true', help='Turn on/off gpu (auto switch between mps and cuda)')
  89. g.add_argument('--use-gpu-limited', action='store_true', help='Turn on/off gpu (excluding offline translator)')
  90. parser.add_argument('--detector', default='default', type=str, choices=DETECTORS, help='Text detector used for creating a text mask from an image, DO NOT use craft for manga, it\'s not designed for it')
  91. parser.add_argument('--ocr', default='48px', type=str, choices=OCRS, help='Optical character recognition (OCR) model to use')
  92. parser.add_argument('--use-mocr-merge', action='store_true', help='Use bbox merge when Manga OCR inference.')
  93. parser.add_argument('--inpainter', default='lama_large', type=str, choices=INPAINTERS, help='Inpainting model to use')
  94. parser.add_argument('--upscaler', default='esrgan', type=str, choices=UPSCALERS, help='Upscaler to use. --upscale-ratio has to be set for it to take effect')
  95. parser.add_argument('--upscale-ratio', default=None, type=float, help='Image upscale ratio applied before detection. Can improve text detection.')
  96. parser.add_argument('--colorizer', default=None, type=str, choices=COLORIZERS, help='Colorization model to use.')
  97. g = parser.add_mutually_exclusive_group()
  98. g.add_argument('--translator', default='google', type=str, choices=TRANSLATORS, help='Language translator to use')
  99. g.add_argument('--translator-chain', default=None, type=translator_chain, help='Output of one translator goes in another. Example: --translator-chain "google:JPN;sugoi:ENG".')
  100. g.add_argument('--selective-translation', default=None, type=translator_chain, help='Select a translator based on detected language in image. Note the first translation service acts as default if the language isn\'t defined. Example: --translator-chain "google:JPN;sugoi:ENG".')
  101. parser.add_argument('--revert-upscaling', action='store_true', help='Downscales the previously upscaled image after translation back to original size (Use with --upscale-ratio).')
  102. parser.add_argument('--detection-size', default=1536, type=int, help='Size of image used for detection')
  103. parser.add_argument('--det-rotate', action='store_true', help='Rotate the image for detection. Might improve detection.')
  104. parser.add_argument('--det-auto-rotate', action='store_true', help='Rotate the image for detection to prefer vertical textlines. Might improve detection.')
  105. parser.add_argument('--det-invert', action='store_true', help='Invert the image colors for detection. Might improve detection.')
  106. parser.add_argument('--det-gamma-correct', action='store_true', help='Applies gamma correction for detection. Might improve detection.')
  107. parser.add_argument('--unclip-ratio', default=2.3, type=float, help='How much to extend text skeleton to form bounding box')
  108. parser.add_argument('--box-threshold', default=0.7, type=float, help='Threshold for bbox generation')
  109. parser.add_argument('--text-threshold', default=0.5, type=float, help='Threshold for text detection')
  110. parser.add_argument('--min-text-length', default=0, type=int, help='Minimum text length of a text region')
  111. parser.add_argument('--no-text-lang-skip', action='store_true', help='Dont skip text that is seemingly already in the target language.')
  112. parser.add_argument('--inpainting-size', default=2048, type=int, help='Size of image used for inpainting (too large will result in OOM)')
  113. parser.add_argument('--inpainting-precision', default='fp32', type=str, help='Inpainting precision for lama, use bf16 while you can.', choices=['fp32', 'fp16', 'bf16'])
  114. parser.add_argument('--colorization-size', default=576, type=int, help='Size of image used for colorization. Set to -1 to use full image size')
  115. parser.add_argument('--denoise-sigma', default=30, type=int, help='Used by colorizer and affects color strength, range from 0 to 255 (default 30). -1 turns it off.')
  116. parser.add_argument('--mask-dilation-offset', default=0, type=int, help='By how much to extend the text mask to remove left-over text pixels of the original image.')
  117. parser.add_argument('--disable-font-border', action='store_true', help='Disable font border')
  118. parser.add_argument('--font-size', default=None, type=int, help='Use fixed font size for rendering')
  119. parser.add_argument('--font-size-offset', default=0, type=int, help='Offset font size by a given amount, positive number increase font size and vice versa')
  120. parser.add_argument('--font-size-minimum', default=-1, type=int, help='Minimum output font size. Default is image_sides_sum/200')
  121. parser.add_argument('--font-color', default=None, type=str, help='Overwrite the text fg/bg color detected by the OCR model. Use hex string without the "#" such as FFFFFF for a white foreground or FFFFFF:000000 to also have a black background around the text.')
  122. parser.add_argument('--line-spacing', default=None, type=float, help='Line spacing is font_size * this value. Default is 0.01 for horizontal text and 0.2 for vertical.')
  123. g = parser.add_mutually_exclusive_group()
  124. g.add_argument('--force-horizontal', action='store_true', help='Force text to be rendered horizontally')
  125. g.add_argument('--force-vertical', action='store_true', help='Force text to be rendered vertically')
  126. g = parser.add_mutually_exclusive_group()
  127. g.add_argument('--align-left', action='store_true', help='Align rendered text left')
  128. g.add_argument('--align-center', action='store_true', help='Align rendered text centered')
  129. g.add_argument('--align-right', action='store_true', help='Align rendered text right')
  130. g = parser.add_mutually_exclusive_group()
  131. g.add_argument('--uppercase', action='store_true', help='Change text to uppercase')
  132. g.add_argument('--lowercase', action='store_true', help='Change text to lowercase')
  133. parser.add_argument('--no-hyphenation', action='store_true', help='If renderer should be splitting up words using a hyphen character (-)')
  134. parser.add_argument('--manga2eng', action='store_true', help='Render english text translated from manga with some additional typesetting. Ignores some other argument options')
  135. parser.add_argument('--gpt-config', type=file_path, help='Path to GPT config file, more info in README')
  136. parser.add_argument('--use-mtpe', action='store_true', help='Turn on/off machine translation post editing (MTPE) on the command line (works only on linux right now)')
  137. g = parser.add_mutually_exclusive_group()
  138. g.add_argument('--save-text', action='store_true', help='Save extracted text and translations into a text file.')
  139. g.add_argument('--save-text-file', default='', type=str, help='Like --save-text but with a specified file path.')
  140. parser.add_argument('--filter-text', default=None, type=str, help='Filter regions by their text with a regex. Example usage: --text-filter ".*badtext.*"')
  141. parser.add_argument('--prep-manual', action='store_true', help='Prepare for manual typesetting by outputting blank, inpainted images, plus copies of the original for reference')
  142. parser.add_argument('--font-path', default='', type=file_path, help='Path to font file')
  143. parser.add_argument('--gimp-font', default='Sans-serif', type=str, help='Font family to use for gimp rendering.')
  144. parser.add_argument('--host', default='127.0.0.1', type=str, help='Used by web module to decide which host to attach to')
  145. parser.add_argument('--port', default=5003, type=int, help='Used by web module to decide which port to attach to')
  146. parser.add_argument('--nonce', default=os.getenv('MT_WEB_NONCE', ''), type=str, help='Used by web module as secret for securing internal web server communication')
  147. # parser.add_argument('--log-web', action='store_true', help='Used by web module to decide if web logs should be surfaced')
  148. parser.add_argument('--ws-url', default='ws://localhost:5000', type=str, help='Server URL for WebSocket mode')
  149. parser.add_argument('--save-quality', default=100, type=int, help='Quality of saved JPEG image, range from 0 to 100 with 100 being best')
  150. parser.add_argument('--ignore-bubble', default=0, type=int, help='The threshold for ignoring text in non bubble areas, with valid values ranging from 1 to 50, does not ignore others. Recommendation 5 to 10. If it is too low, normal bubble areas may be ignored, and if it is too large, non bubble areas may be considered normal bubbles')
  151. parser.add_argument('--kernel-size', default=3, type=int, help='Set the convolution kernel size of the text erasure area to completely clean up text residues')
  152. # Generares dict with a default value for each argument
  153. DEFAULT_ARGS = vars(parser.parse_args([]))