main.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import argparse
  2. import codecs
  3. import logging
  4. import os
  5. import sys
  6. import yaml
  7. from qtpy import QtWidgets
  8. from labelme import __appname__
  9. from labelme import __version__
  10. from labelme.app import MainWindow
  11. from labelme.config import get_config
  12. from labelme.logger import logger
  13. from labelme.utils import newIcon
  14. def main():
  15. try:
  16. _main()
  17. except Exception as e:
  18. logger.error(e)
  19. def _main():
  20. parser = argparse.ArgumentParser()
  21. parser.add_argument(
  22. '--version', '-V', action='store_true', help='show version'
  23. )
  24. parser.add_argument(
  25. '--reset-config', action='store_true', help='reset qt config'
  26. )
  27. parser.add_argument(
  28. '--logger-level',
  29. default='info',
  30. choices=['debug', 'info', 'warning', 'fatal', 'error'],
  31. help='logger level',
  32. )
  33. parser.add_argument('filename', nargs='?', help='image or label filename')
  34. parser.add_argument(
  35. '--output',
  36. '-O',
  37. '-o',
  38. help='output file or directory (if it ends with .json it is '
  39. 'recognized as file, else as directory)'
  40. )
  41. default_config_file = os.path.join(os.path.expanduser('~'), '.labelmerc')
  42. parser.add_argument(
  43. '--config',
  44. dest='config_file',
  45. help='config file (default: %s)' % default_config_file,
  46. default=default_config_file,
  47. )
  48. # config for the gui
  49. parser.add_argument(
  50. '--nodata',
  51. dest='store_data',
  52. action='store_false',
  53. help='stop storing image data to JSON file',
  54. default=argparse.SUPPRESS,
  55. )
  56. parser.add_argument(
  57. '--autosave',
  58. dest='auto_save',
  59. action='store_true',
  60. help='auto save',
  61. default=argparse.SUPPRESS,
  62. )
  63. parser.add_argument(
  64. '--nosortlabels',
  65. dest='sort_labels',
  66. action='store_false',
  67. help='stop sorting labels',
  68. default=argparse.SUPPRESS,
  69. )
  70. parser.add_argument(
  71. '--flags',
  72. help='comma separated list of flags OR file containing flags',
  73. default=argparse.SUPPRESS,
  74. )
  75. parser.add_argument(
  76. '--labelflags',
  77. dest='label_flags',
  78. help='yaml string of label specific flags OR file containing json '
  79. 'string of label specific flags (ex. {person: [male, tall], '
  80. 'dog: [big, black, brown, white], __all__: [occluded]})',
  81. default=argparse.SUPPRESS,
  82. )
  83. parser.add_argument(
  84. '--labels',
  85. help='comma separated list of labels OR file containing labels',
  86. default=argparse.SUPPRESS,
  87. )
  88. parser.add_argument(
  89. '--validatelabel',
  90. dest='validate_label',
  91. choices=['exact', 'instance'],
  92. help='label validation types',
  93. default=argparse.SUPPRESS,
  94. )
  95. parser.add_argument(
  96. '--keep-prev',
  97. action='store_true',
  98. help='keep annotation of previous frame',
  99. default=argparse.SUPPRESS,
  100. )
  101. parser.add_argument(
  102. '--epsilon',
  103. type=float,
  104. help='epsilon to find nearest vertex on canvas',
  105. default=argparse.SUPPRESS,
  106. )
  107. args = parser.parse_args()
  108. if args.version:
  109. print('{0} {1}'.format(__appname__, __version__))
  110. sys.exit(0)
  111. logger.setLevel(getattr(logging, args.logger_level.upper()))
  112. if hasattr(args, 'flags'):
  113. if os.path.isfile(args.flags):
  114. with codecs.open(args.flags, 'r', encoding='utf-8') as f:
  115. args.flags = [l.strip() for l in f if l.strip()]
  116. else:
  117. args.flags = [l for l in args.flags.split(',') if l]
  118. if hasattr(args, 'labels'):
  119. if os.path.isfile(args.labels):
  120. with codecs.open(args.labels, 'r', encoding='utf-8') as f:
  121. args.labels = [l.strip() for l in f if l.strip()]
  122. else:
  123. args.labels = [l for l in args.labels.split(',') if l]
  124. if hasattr(args, 'label_flags'):
  125. if os.path.isfile(args.label_flags):
  126. with codecs.open(args.label_flags, 'r', encoding='utf-8') as f:
  127. args.label_flags = yaml.load(f)
  128. else:
  129. args.label_flags = yaml.load(args.label_flags)
  130. # add not overlapping labels from label flags
  131. if not hasattr(args, 'labels'):
  132. args.labels = []
  133. for label in args.label_flags.keys():
  134. if label != '__all__' and label not in args.labels:
  135. args.labels.append(label)
  136. config_from_args = args.__dict__
  137. config_from_args.pop('version')
  138. reset_config = config_from_args.pop('reset_config')
  139. filename = config_from_args.pop('filename')
  140. output = config_from_args.pop('output')
  141. config_file = config_from_args.pop('config_file')
  142. config = get_config(config_from_args, config_file)
  143. if not config['labels'] and config['validate_label']:
  144. logger.error('--labels must be specified with --validatelabel or '
  145. 'validate_label: true in the config file '
  146. '(ex. ~/.labelmerc).')
  147. sys.exit(1)
  148. output_file = None
  149. output_dir = None
  150. if output is not None:
  151. if output.endswith('.json'):
  152. output_file = output
  153. else:
  154. output_dir = output
  155. app = QtWidgets.QApplication(sys.argv)
  156. app.setApplicationName(__appname__)
  157. app.setWindowIcon(newIcon('icon'))
  158. win = MainWindow(
  159. config=config,
  160. filename=filename,
  161. output_file=output_file,
  162. output_dir=output_dir,
  163. )
  164. if reset_config:
  165. logger.info('Resetting Qt config: %s' % win.settings.fileName())
  166. win.settings.clear()
  167. sys.exit(0)
  168. win.show()
  169. win.raise_()
  170. sys.exit(app.exec_())
  171. # this main block is required to generate executable by pyinstaller
  172. if __name__ == '__main__':
  173. main()