Move icons to resource folder, fix the unicode issue, support zh-tw lang
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
icons/.DS_Store
|
resources/icons/.DS_Store
|
||||||
|
|
||||||
resources.py
|
resources.py
|
||||||
|
|
||||||
|
|||||||
173
labelImg.py
@ -32,6 +32,7 @@ from libs.constants import *
|
|||||||
from libs.lib import struct, newAction, newIcon, addActions, fmtShortcut, generateColorByText
|
from libs.lib import struct, newAction, newIcon, addActions, fmtShortcut, generateColorByText
|
||||||
from libs.settings import Settings
|
from libs.settings import Settings
|
||||||
from libs.shape import Shape, DEFAULT_LINE_COLOR, DEFAULT_FILL_COLOR
|
from libs.shape import Shape, DEFAULT_LINE_COLOR, DEFAULT_FILL_COLOR
|
||||||
|
from libs.stringBundle import StringBundle
|
||||||
from libs.canvas import Canvas
|
from libs.canvas import Canvas
|
||||||
from libs.zoomWidget import ZoomWidget
|
from libs.zoomWidget import ZoomWidget
|
||||||
from libs.labelDialog import LabelDialog
|
from libs.labelDialog import LabelDialog
|
||||||
@ -44,6 +45,7 @@ from libs.yolo_io import YoloReader
|
|||||||
from libs.yolo_io import TXT_EXT
|
from libs.yolo_io import TXT_EXT
|
||||||
from libs.ustr import ustr
|
from libs.ustr import ustr
|
||||||
from libs.version import __version__
|
from libs.version import __version__
|
||||||
|
from libs.hashableQListWidgetItem import HashableQListWidgetItem
|
||||||
|
|
||||||
__appname__ = 'labelImg'
|
__appname__ = 'labelImg'
|
||||||
|
|
||||||
@ -76,16 +78,6 @@ class WindowMixin(object):
|
|||||||
return toolbar
|
return toolbar
|
||||||
|
|
||||||
|
|
||||||
# PyQt5: TypeError: unhashable type: 'QListWidgetItem'
|
|
||||||
class HashableQListWidgetItem(QListWidgetItem):
|
|
||||||
|
|
||||||
def __init__(self, *args):
|
|
||||||
super(HashableQListWidgetItem, self).__init__(*args)
|
|
||||||
|
|
||||||
def __hash__(self):
|
|
||||||
return hash(id(self))
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow, WindowMixin):
|
class MainWindow(QMainWindow, WindowMixin):
|
||||||
FIT_WINDOW, FIT_WIDTH, MANUAL_ZOOM = list(range(3))
|
FIT_WINDOW, FIT_WIDTH, MANUAL_ZOOM = list(range(3))
|
||||||
|
|
||||||
@ -98,6 +90,10 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
self.settings.load()
|
self.settings.load()
|
||||||
settings = self.settings
|
settings = self.settings
|
||||||
|
|
||||||
|
# Load string bundle for i18n
|
||||||
|
self.stringBundle = StringBundle.getBundle()
|
||||||
|
getStr = lambda strId: self.stringBundle.getString(strId)
|
||||||
|
|
||||||
# Save as Pascal voc xml
|
# Save as Pascal voc xml
|
||||||
self.defaultSaveDir = defaultSaveDir
|
self.defaultSaveDir = defaultSaveDir
|
||||||
self.usingPascalVocFormat = True
|
self.usingPascalVocFormat = True
|
||||||
@ -131,7 +127,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
listLayout.setContentsMargins(0, 0, 0, 0)
|
listLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
# Create a widget for using default label
|
# Create a widget for using default label
|
||||||
self.useDefaultLabelCheckbox = QCheckBox(u'Use default label')
|
self.useDefaultLabelCheckbox = QCheckBox(getStr('useDefaultLabel'))
|
||||||
self.useDefaultLabelCheckbox.setChecked(False)
|
self.useDefaultLabelCheckbox.setChecked(False)
|
||||||
self.defaultLabelTextLine = QLineEdit()
|
self.defaultLabelTextLine = QLineEdit()
|
||||||
useDefaultLabelQHBoxLayout = QHBoxLayout()
|
useDefaultLabelQHBoxLayout = QHBoxLayout()
|
||||||
@ -141,7 +137,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
useDefaultLabelContainer.setLayout(useDefaultLabelQHBoxLayout)
|
useDefaultLabelContainer.setLayout(useDefaultLabelQHBoxLayout)
|
||||||
|
|
||||||
# Create a widget for edit and diffc button
|
# Create a widget for edit and diffc button
|
||||||
self.diffcButton = QCheckBox(u'difficult')
|
self.diffcButton = QCheckBox(getStr('useDifficult'))
|
||||||
self.diffcButton.setChecked(False)
|
self.diffcButton.setChecked(False)
|
||||||
self.diffcButton.stateChanged.connect(self.btnstate)
|
self.diffcButton.stateChanged.connect(self.btnstate)
|
||||||
self.editButton = QToolButton()
|
self.editButton = QToolButton()
|
||||||
@ -163,11 +159,10 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
self.labelList.itemChanged.connect(self.labelItemChanged)
|
self.labelList.itemChanged.connect(self.labelItemChanged)
|
||||||
listLayout.addWidget(self.labelList)
|
listLayout.addWidget(self.labelList)
|
||||||
|
|
||||||
self.dock = QDockWidget(u'Box Labels', self)
|
self.dock = QDockWidget(getStr('boxLabelText'), self)
|
||||||
self.dock.setObjectName(u'Labels')
|
self.dock.setObjectName(getStr('labels'))
|
||||||
self.dock.setWidget(labelListContainer)
|
self.dock.setWidget(labelListContainer)
|
||||||
|
|
||||||
# Tzutalin 20160906 : Add file list and dock to move faster
|
|
||||||
self.fileListWidget = QListWidget()
|
self.fileListWidget = QListWidget()
|
||||||
self.fileListWidget.itemDoubleClicked.connect(self.fileitemDoubleClicked)
|
self.fileListWidget.itemDoubleClicked.connect(self.fileitemDoubleClicked)
|
||||||
filelistLayout = QVBoxLayout()
|
filelistLayout = QVBoxLayout()
|
||||||
@ -175,8 +170,8 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
filelistLayout.addWidget(self.fileListWidget)
|
filelistLayout.addWidget(self.fileListWidget)
|
||||||
fileListContainer = QWidget()
|
fileListContainer = QWidget()
|
||||||
fileListContainer.setLayout(filelistLayout)
|
fileListContainer.setLayout(filelistLayout)
|
||||||
self.filedock = QDockWidget(u'File List', self)
|
self.filedock = QDockWidget(getStr('fileList'), self)
|
||||||
self.filedock.setObjectName(u'Files')
|
self.filedock.setObjectName(getStr('files'))
|
||||||
self.filedock.setWidget(fileListContainer)
|
self.filedock.setWidget(fileListContainer)
|
||||||
|
|
||||||
self.zoomWidget = ZoomWidget()
|
self.zoomWidget = ZoomWidget()
|
||||||
@ -203,7 +198,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
|
|
||||||
self.setCentralWidget(scroll)
|
self.setCentralWidget(scroll)
|
||||||
self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
|
self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
|
||||||
# Tzutalin 20160906 : Add file list and dock to move faster
|
|
||||||
self.addDockWidget(Qt.RightDockWidgetArea, self.filedock)
|
self.addDockWidget(Qt.RightDockWidgetArea, self.filedock)
|
||||||
self.filedock.setFeatures(QDockWidget.DockWidgetFloatable)
|
self.filedock.setFeatures(QDockWidget.DockWidgetFloatable)
|
||||||
|
|
||||||
@ -212,72 +206,72 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
|
|
||||||
# Actions
|
# Actions
|
||||||
action = partial(newAction, self)
|
action = partial(newAction, self)
|
||||||
quit = action('&Quit', self.close,
|
quit = action(getStr('quit'), self.close,
|
||||||
'Ctrl+Q', 'quit', u'Quit application')
|
'Ctrl+Q', 'quit', getStr('quitApp'))
|
||||||
|
|
||||||
open = action('&Open', self.openFile,
|
open = action(getStr('openFile'), self.openFile,
|
||||||
'Ctrl+O', 'open', u'Open image or label file')
|
'Ctrl+O', 'open', getStr('openFileDetail'))
|
||||||
|
|
||||||
opendir = action('&Open Dir', self.openDirDialog,
|
opendir = action(getStr('openDir'), self.openDirDialog,
|
||||||
'Ctrl+u', 'open', u'Open Dir')
|
'Ctrl+u', 'open', getStr('openDir'))
|
||||||
|
|
||||||
changeSavedir = action('&Change Save Dir', self.changeSavedirDialog,
|
changeSavedir = action(getStr('changeSaveDir'), self.changeSavedirDialog,
|
||||||
'Ctrl+r', 'open', u'Change default saved Annotation dir')
|
'Ctrl+r', 'open', getStr('changeSavedAnnotationDir'))
|
||||||
|
|
||||||
openAnnotation = action('&Open Annotation', self.openAnnotationDialog,
|
openAnnotation = action(getStr('openAnnotation'), self.openAnnotationDialog,
|
||||||
'Ctrl+Shift+O', 'open', u'Open Annotation')
|
'Ctrl+Shift+O', 'open', getStr('openAnnotationDetail'))
|
||||||
|
|
||||||
openNextImg = action('&Next Image', self.openNextImg,
|
openNextImg = action(getStr('nextImg'), self.openNextImg,
|
||||||
'd', 'next', u'Open Next')
|
'd', 'next', getStr('nextImgDetail'))
|
||||||
|
|
||||||
openPrevImg = action('&Prev Image', self.openPrevImg,
|
openPrevImg = action(getStr('prevImg'), self.openPrevImg,
|
||||||
'a', 'prev', u'Open Prev')
|
'a', 'prev', getStr('prevImgDetail'))
|
||||||
|
|
||||||
verify = action('&Verify Image', self.verifyImg,
|
verify = action(getStr('verifyImg'), self.verifyImg,
|
||||||
'space', 'verify', u'Verify Image')
|
'space', 'verify', getStr('verifyImgDetail'))
|
||||||
|
|
||||||
save = action('&Save', self.saveFile,
|
save = action(getStr('save'), self.saveFile,
|
||||||
'Ctrl+S', 'save', u'Save labels to file', enabled=False)
|
'Ctrl+S', 'save', getStr('saveDetail'), enabled=False)
|
||||||
|
|
||||||
save_format = action('&PascalVOC', self.change_format,
|
save_format = action('&PascalVOC', self.change_format,
|
||||||
'Ctrl+', 'format_voc', u'Change save format', enabled=True)
|
'Ctrl+', 'format_voc', getStr('changeSaveFormat'), enabled=True)
|
||||||
|
|
||||||
saveAs = action('&Save As', self.saveFileAs,
|
saveAs = action(getStr('saveAs'), self.saveFileAs,
|
||||||
'Ctrl+Shift+S', 'save-as', u'Save labels to a different file', enabled=False)
|
'Ctrl+Shift+S', 'save-as', getStr('saveAsDetail'), enabled=False)
|
||||||
|
|
||||||
close = action('&Close', self.closeFile, 'Ctrl+W', 'close', u'Close current file')
|
close = action(getStr('closeCur'), self.closeFile, 'Ctrl+W', 'close', getStr('closeCurDetail'))
|
||||||
|
|
||||||
resetAll = action('&ResetAll', self.resetAll, None, 'resetall', u'Reset all')
|
resetAll = action(getStr('resetAll'), self.resetAll, None, 'resetall', getStr('resetAllDetail'))
|
||||||
|
|
||||||
color1 = action('Box Line Color', self.chooseColor1,
|
color1 = action(getStr('boxLineColor'), self.chooseColor1,
|
||||||
'Ctrl+L', 'color_line', u'Choose Box line color')
|
'Ctrl+L', 'color_line', getStr('boxLineColorDetail'))
|
||||||
|
|
||||||
createMode = action('Create\nRectBox', self.setCreateMode,
|
createMode = action(getStr('crtBox'), self.setCreateMode,
|
||||||
'w', 'new', u'Start drawing Boxs', enabled=False)
|
'w', 'new', getStr('crtBoxDetail'), enabled=False)
|
||||||
editMode = action('&Edit\nRectBox', self.setEditMode,
|
editMode = action('&Edit\nRectBox', self.setEditMode,
|
||||||
'Ctrl+J', 'edit', u'Move and edit Boxs', enabled=False)
|
'Ctrl+J', 'edit', u'Move and edit Boxs', enabled=False)
|
||||||
|
|
||||||
create = action('Create\nRectBox', self.createShape,
|
create = action(getStr('crtBox'), self.createShape,
|
||||||
'w', 'new', u'Draw a new Box', enabled=False)
|
'w', 'new', getStr('crtBoxDetail'), enabled=False)
|
||||||
delete = action('Delete\nRectBox', self.deleteSelectedShape,
|
delete = action(getStr('delBox'), self.deleteSelectedShape,
|
||||||
'Delete', 'delete', u'Delete', enabled=False)
|
'Delete', 'delete', getStr('delBoxDetail'), enabled=False)
|
||||||
copy = action('&Duplicate\nRectBox', self.copySelectedShape,
|
copy = action(getStr('dupBox'), self.copySelectedShape,
|
||||||
'Ctrl+D', 'copy', u'Create a duplicate of the selected Box',
|
'Ctrl+D', 'copy', getStr('dupBoxDetail'),
|
||||||
enabled=False)
|
enabled=False)
|
||||||
|
|
||||||
advancedMode = action('&Advanced Mode', self.toggleAdvancedMode,
|
advancedMode = action(getStr('advancedMode'), self.toggleAdvancedMode,
|
||||||
'Ctrl+Shift+A', 'expert', u'Switch to advanced mode',
|
'Ctrl+Shift+A', 'expert', getStr('advancedModeDetail'),
|
||||||
checkable=True)
|
checkable=True)
|
||||||
|
|
||||||
hideAll = action('&Hide\nRectBox', partial(self.togglePolygons, False),
|
hideAll = action('&Hide\nRectBox', partial(self.togglePolygons, False),
|
||||||
'Ctrl+H', 'hide', u'Hide all Boxs',
|
'Ctrl+H', 'hide', getStr('hideAllBoxDetail'),
|
||||||
enabled=False)
|
enabled=False)
|
||||||
showAll = action('&Show\nRectBox', partial(self.togglePolygons, True),
|
showAll = action('&Show\nRectBox', partial(self.togglePolygons, True),
|
||||||
'Ctrl+A', 'hide', u'Show all Boxs',
|
'Ctrl+A', 'hide', getStr('showAllBoxDetail'),
|
||||||
enabled=False)
|
enabled=False)
|
||||||
|
|
||||||
help = action('&Tutorial', self.showTutorialDialog, None, 'help', u'Show demos')
|
help = action(getStr('tutorial'), self.showTutorialDialog, None, 'help', getStr('tutorialDetail'))
|
||||||
showInfo = action('&Information', self.showInfoDialog, None, 'help', u'Information')
|
showInfo = action(getStr('info'), self.showInfoDialog, None, 'help', getStr('info'))
|
||||||
|
|
||||||
zoom = QWidgetAction(self)
|
zoom = QWidgetAction(self)
|
||||||
zoom.setDefaultWidget(self.zoomWidget)
|
zoom.setDefaultWidget(self.zoomWidget)
|
||||||
@ -287,17 +281,17 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
fmtShortcut("Ctrl+Wheel")))
|
fmtShortcut("Ctrl+Wheel")))
|
||||||
self.zoomWidget.setEnabled(False)
|
self.zoomWidget.setEnabled(False)
|
||||||
|
|
||||||
zoomIn = action('Zoom &In', partial(self.addZoom, 10),
|
zoomIn = action(getStr('zoomin'), partial(self.addZoom, 10),
|
||||||
'Ctrl++', 'zoom-in', u'Increase zoom level', enabled=False)
|
'Ctrl++', 'zoom-in', getStr('zoominDetail'), enabled=False)
|
||||||
zoomOut = action('&Zoom Out', partial(self.addZoom, -10),
|
zoomOut = action(getStr('zoomout'), partial(self.addZoom, -10),
|
||||||
'Ctrl+-', 'zoom-out', u'Decrease zoom level', enabled=False)
|
'Ctrl+-', 'zoom-out', getStr('zoomoutDetail'), enabled=False)
|
||||||
zoomOrg = action('&Original size', partial(self.setZoom, 100),
|
zoomOrg = action(getStr('originalsize'), partial(self.setZoom, 100),
|
||||||
'Ctrl+=', 'zoom', u'Zoom to original size', enabled=False)
|
'Ctrl+=', 'zoom', getStr('originalsizeDetail'), enabled=False)
|
||||||
fitWindow = action('&Fit Window', self.setFitWindow,
|
fitWindow = action(getStr('fitWin'), self.setFitWindow,
|
||||||
'Ctrl+F', 'fit-window', u'Zoom follows window size',
|
'Ctrl+F', 'fit-window', getStr('fitWinDetail'),
|
||||||
checkable=True, enabled=False)
|
checkable=True, enabled=False)
|
||||||
fitWidth = action('Fit &Width', self.setFitWidth,
|
fitWidth = action(getStr('fitWidth'), self.setFitWidth,
|
||||||
'Ctrl+Shift+F', 'fit-width', u'Zoom follows window width',
|
'Ctrl+Shift+F', 'fit-width', getStr('fitWidthDetail'),
|
||||||
checkable=True, enabled=False)
|
checkable=True, enabled=False)
|
||||||
# Group zoom controls into a list for easier toggling.
|
# Group zoom controls into a list for easier toggling.
|
||||||
zoomActions = (self.zoomWidget, zoomIn, zoomOut,
|
zoomActions = (self.zoomWidget, zoomIn, zoomOut,
|
||||||
@ -310,20 +304,20 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
self.MANUAL_ZOOM: lambda: 1,
|
self.MANUAL_ZOOM: lambda: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
edit = action('&Edit Label', self.editLabel,
|
edit = action(getStr('editLabel'), self.editLabel,
|
||||||
'Ctrl+E', 'edit', u'Modify the label of the selected Box',
|
'Ctrl+E', 'edit', getStr('editLabelDetail'),
|
||||||
enabled=False)
|
enabled=False)
|
||||||
self.editButton.setDefaultAction(edit)
|
self.editButton.setDefaultAction(edit)
|
||||||
|
|
||||||
shapeLineColor = action('Shape &Line Color', self.chshapeLineColor,
|
shapeLineColor = action(getStr('shapeLineColor'), self.chshapeLineColor,
|
||||||
icon='color_line', tip=u'Change the line color for this specific shape',
|
icon='color_line', tip=getStr('shapeLineColorDetail'),
|
||||||
enabled=False)
|
enabled=False)
|
||||||
shapeFillColor = action('Shape &Fill Color', self.chshapeFillColor,
|
shapeFillColor = action(getStr('shapeFillColor'), self.chshapeFillColor,
|
||||||
icon='color', tip=u'Change the fill color for this specific shape',
|
icon='color', tip=getStr('shapeFillColorDetail'),
|
||||||
enabled=False)
|
enabled=False)
|
||||||
|
|
||||||
labels = self.dock.toggleViewAction()
|
labels = self.dock.toggleViewAction()
|
||||||
labels.setText('Show/Hide Label Panel')
|
labels.setText(getStr('showHide'))
|
||||||
labels.setShortcut('Ctrl+Shift+L')
|
labels.setShortcut('Ctrl+Shift+L')
|
||||||
|
|
||||||
# Lavel list context menu.
|
# Lavel list context menu.
|
||||||
@ -369,21 +363,21 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
labelList=labelMenu)
|
labelList=labelMenu)
|
||||||
|
|
||||||
# Auto saving : Enable auto saving if pressing next
|
# Auto saving : Enable auto saving if pressing next
|
||||||
self.autoSaving = QAction("Auto Saving", self)
|
self.autoSaving = QAction(getStr('autoSaveMode'), self)
|
||||||
self.autoSaving.setCheckable(True)
|
self.autoSaving.setCheckable(True)
|
||||||
self.autoSaving.setChecked(settings.get(SETTING_AUTO_SAVE, False))
|
self.autoSaving.setChecked(settings.get(SETTING_AUTO_SAVE, False))
|
||||||
# Sync single class mode from PR#106
|
# Sync single class mode from PR#106
|
||||||
self.singleClassMode = QAction("Single Class Mode", self)
|
self.singleClassMode = QAction(getStr('singleClsMode'), self)
|
||||||
self.singleClassMode.setShortcut("Ctrl+Shift+S")
|
self.singleClassMode.setShortcut("Ctrl+Shift+S")
|
||||||
self.singleClassMode.setCheckable(True)
|
self.singleClassMode.setCheckable(True)
|
||||||
self.singleClassMode.setChecked(settings.get(SETTING_SINGLE_CLASS, False))
|
self.singleClassMode.setChecked(settings.get(SETTING_SINGLE_CLASS, False))
|
||||||
self.lastLabel = None
|
self.lastLabel = None
|
||||||
# Add option to enable/disable labels being painted at the top of bounding boxes
|
# Add option to enable/disable labels being displayed at the top of bounding boxes
|
||||||
self.paintLabelsOption = QAction("Paint Labels", self)
|
self.displayLabelOption = QAction(getStr('displayLabel'), self)
|
||||||
self.paintLabelsOption.setShortcut("Ctrl+Shift+P")
|
self.displayLabelOption.setShortcut("Ctrl+Shift+P")
|
||||||
self.paintLabelsOption.setCheckable(True)
|
self.displayLabelOption.setCheckable(True)
|
||||||
self.paintLabelsOption.setChecked(settings.get(SETTING_PAINT_LABEL, False))
|
self.displayLabelOption.setChecked(settings.get(SETTING_PAINT_LABEL, False))
|
||||||
self.paintLabelsOption.triggered.connect(self.togglePaintLabelsOption)
|
self.displayLabelOption.triggered.connect(self.togglePaintLabelsOption)
|
||||||
|
|
||||||
addActions(self.menus.file,
|
addActions(self.menus.file,
|
||||||
(open, opendir, changeSavedir, openAnnotation, self.menus.recentFiles, save, save_format, saveAs, close, resetAll, quit))
|
(open, opendir, changeSavedir, openAnnotation, self.menus.recentFiles, save, save_format, saveAs, close, resetAll, quit))
|
||||||
@ -391,7 +385,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
addActions(self.menus.view, (
|
addActions(self.menus.view, (
|
||||||
self.autoSaving,
|
self.autoSaving,
|
||||||
self.singleClassMode,
|
self.singleClassMode,
|
||||||
self.paintLabelsOption,
|
self.displayLabelOption,
|
||||||
labels, advancedMode, None,
|
labels, advancedMode, None,
|
||||||
hideAll, showAll, None,
|
hideAll, showAll, None,
|
||||||
zoomIn, zoomOut, zoomOrg, None,
|
zoomIn, zoomOut, zoomOrg, None,
|
||||||
@ -739,7 +733,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
self.actions.shapeFillColor.setEnabled(selected)
|
self.actions.shapeFillColor.setEnabled(selected)
|
||||||
|
|
||||||
def addLabel(self, shape):
|
def addLabel(self, shape):
|
||||||
shape.paintLabel = self.paintLabelsOption.isChecked()
|
shape.paintLabel = self.displayLabelOption.isChecked()
|
||||||
item = HashableQListWidgetItem(shape.label)
|
item = HashableQListWidgetItem(shape.label)
|
||||||
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
||||||
item.setCheckState(Qt.Checked)
|
item.setCheckState(Qt.Checked)
|
||||||
@ -1112,19 +1106,18 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
if self.defaultSaveDir and os.path.exists(self.defaultSaveDir):
|
if self.defaultSaveDir and os.path.exists(self.defaultSaveDir):
|
||||||
settings[SETTING_SAVE_DIR] = ustr(self.defaultSaveDir)
|
settings[SETTING_SAVE_DIR] = ustr(self.defaultSaveDir)
|
||||||
else:
|
else:
|
||||||
settings[SETTING_SAVE_DIR] = ""
|
settings[SETTING_SAVE_DIR] = ''
|
||||||
|
|
||||||
if self.lastOpenDir and os.path.exists(self.lastOpenDir):
|
if self.lastOpenDir and os.path.exists(self.lastOpenDir):
|
||||||
settings[SETTING_LAST_OPEN_DIR] = self.lastOpenDir
|
settings[SETTING_LAST_OPEN_DIR] = self.lastOpenDir
|
||||||
else:
|
else:
|
||||||
settings[SETTING_LAST_OPEN_DIR] = ""
|
settings[SETTING_LAST_OPEN_DIR] = ''
|
||||||
|
|
||||||
settings[SETTING_AUTO_SAVE] = self.autoSaving.isChecked()
|
settings[SETTING_AUTO_SAVE] = self.autoSaving.isChecked()
|
||||||
settings[SETTING_SINGLE_CLASS] = self.singleClassMode.isChecked()
|
settings[SETTING_SINGLE_CLASS] = self.singleClassMode.isChecked()
|
||||||
settings[SETTING_PAINT_LABEL] = self.paintLabelsOption.isChecked()
|
settings[SETTING_PAINT_LABEL] = self.displayLabelOption.isChecked()
|
||||||
settings[SETTING_DRAW_SQUARE] = self.drawSquaresOption.isChecked()
|
settings[SETTING_DRAW_SQUARE] = self.drawSquaresOption.isChecked()
|
||||||
settings.save()
|
settings.save()
|
||||||
## User Dialogs ##
|
|
||||||
|
|
||||||
def loadRecent(self, filename):
|
def loadRecent(self, filename):
|
||||||
if self.mayContinue():
|
if self.mayContinue():
|
||||||
@ -1195,7 +1188,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
if not self.mayContinue() or not dirpath:
|
if not self.mayContinue() or not dirpath:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
self.lastOpenDir = dirpath
|
self.lastOpenDir = dirpath
|
||||||
self.dirname = dirpath
|
self.dirname = dirpath
|
||||||
self.filePath = None
|
self.filePath = None
|
||||||
@ -1437,9 +1429,8 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
self.canvas.verified = tYoloParseReader.verified
|
self.canvas.verified = tYoloParseReader.verified
|
||||||
|
|
||||||
def togglePaintLabelsOption(self):
|
def togglePaintLabelsOption(self):
|
||||||
paintLabelsOptionChecked = self.paintLabelsOption.isChecked()
|
|
||||||
for shape in self.canvas.shapes:
|
for shape in self.canvas.shapes:
|
||||||
shape.paintLabel = paintLabelsOptionChecked
|
shape.paintLabel = self.displayLabelOption.isChecked()
|
||||||
|
|
||||||
def toogleDrawSquare(self):
|
def toogleDrawSquare(self):
|
||||||
self.canvas.setDrawingShapeToSquare(self.drawSquaresOption.isChecked())
|
self.canvas.setDrawingShapeToSquare(self.drawSquaresOption.isChecked())
|
||||||
|
|||||||
28
libs/hashableQListWidgetItem.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
from PyQt5.QtGui import *
|
||||||
|
from PyQt5.QtCore import *
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
except ImportError:
|
||||||
|
# needed for py3+qt4
|
||||||
|
# Ref:
|
||||||
|
# http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html
|
||||||
|
# http://stackoverflow.com/questions/21217399/pyqt4-qtcore-qvariant-object-instead-of-a-string
|
||||||
|
if sys.version_info.major >= 3:
|
||||||
|
import sip
|
||||||
|
sip.setapi('QVariant', 2)
|
||||||
|
from PyQt4.QtGui import *
|
||||||
|
from PyQt4.QtCore import *
|
||||||
|
|
||||||
|
# PyQt5: TypeError: unhashable type: 'QListWidgetItem'
|
||||||
|
|
||||||
|
|
||||||
|
class HashableQListWidgetItem(QListWidgetItem):
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
super(HashableQListWidgetItem, self).__init__(*args)
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(id(self))
|
||||||
@ -75,7 +75,7 @@ def fmtShortcut(text):
|
|||||||
|
|
||||||
|
|
||||||
def generateColorByText(text):
|
def generateColorByText(text):
|
||||||
s = str(ustr(text))
|
s = ustr(text)
|
||||||
hashCode = int(hashlib.sha256(s.encode('utf-8')).hexdigest(), 16)
|
hashCode = int(hashlib.sha256(s.encode('utf-8')).hexdigest(), 16)
|
||||||
r = int((hashCode / 255) % 255)
|
r = int((hashCode / 255) % 255)
|
||||||
g = int((hashCode / 65025) % 255)
|
g = int((hashCode / 65025) % 255)
|
||||||
|
|||||||
63
libs/stringBundle.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import resources
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from libs.ustr import ustr
|
||||||
|
try:
|
||||||
|
from PyQt5.QtCore import *
|
||||||
|
except ImportError:
|
||||||
|
if sys.version_info.major >= 3:
|
||||||
|
import sip
|
||||||
|
sip.setapi('QVariant', 2)
|
||||||
|
from PyQt4.QtCore import *
|
||||||
|
|
||||||
|
|
||||||
|
class StringBundle:
|
||||||
|
|
||||||
|
__create_key = object()
|
||||||
|
|
||||||
|
def __init__(self, create_key, localeStr):
|
||||||
|
assert(create_key == StringBundle.__create_key), "StringBundle must be created using StringBundle.getBundle"
|
||||||
|
self.idToMessage = {}
|
||||||
|
paths = self.__createLookupFallbackList(localeStr)
|
||||||
|
for path in paths:
|
||||||
|
self.__loadBundle(path)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getBundle(cls, localeStr=os.getenv('LANG')):
|
||||||
|
return StringBundle(cls.__create_key, localeStr)
|
||||||
|
|
||||||
|
def getString(self, stringId):
|
||||||
|
assert(stringId in self.idToMessage), "Missing string id : " + stringId
|
||||||
|
return self.idToMessage[stringId]
|
||||||
|
|
||||||
|
def __createLookupFallbackList(self, localeStr):
|
||||||
|
resultPaths = []
|
||||||
|
basePath = ":/strings"
|
||||||
|
resultPaths.append(basePath)
|
||||||
|
# Don't follow standard BCP47. Simple fallback
|
||||||
|
tags = re.split('[^a-zA-Z]', localeStr)
|
||||||
|
for tag in tags:
|
||||||
|
lastPath = resultPaths[-1]
|
||||||
|
resultPaths.append(lastPath + '-' + tag)
|
||||||
|
|
||||||
|
return resultPaths
|
||||||
|
|
||||||
|
def __loadBundle(self, path):
|
||||||
|
PROP_SEPERATOR = '='
|
||||||
|
f = QFile(path)
|
||||||
|
if f.exists():
|
||||||
|
if f.open(QIODevice.ReadOnly | QFile.Text):
|
||||||
|
text = QTextStream(f)
|
||||||
|
text.setCodec("UTF-8")
|
||||||
|
|
||||||
|
while not text.atEnd():
|
||||||
|
line = ustr(text.readLine())
|
||||||
|
key_value = line.split(PROP_SEPERATOR)
|
||||||
|
key = key_value[0].strip()
|
||||||
|
value = PROP_SEPERATOR.join(key_value[1:]).strip().strip('"')
|
||||||
|
self.idToMessage[key] = value
|
||||||
|
|
||||||
|
f.close()
|
||||||
@ -9,7 +9,7 @@ def ustr(x):
|
|||||||
if type(x) == str:
|
if type(x) == str:
|
||||||
return x.decode(DEFAULT_ENCODING)
|
return x.decode(DEFAULT_ENCODING)
|
||||||
if type(x) == QString:
|
if type(x) == QString:
|
||||||
return unicode(x, DEFAULT_ENCODING)
|
return unicode(x)
|
||||||
return x
|
return x
|
||||||
else:
|
else:
|
||||||
return x
|
return x
|
||||||
|
|||||||
@ -1,35 +1,37 @@
|
|||||||
<!DOCTYPE RCC><RCC version="1.0">
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
<qresource>
|
<qresource>
|
||||||
|
|
||||||
<file alias="help">icons/help.png</file>
|
<file alias="help">resources/icons/help.png</file>
|
||||||
<file alias="app">icons/app.png</file>
|
<file alias="app">resources/icons/app.png</file>
|
||||||
<file alias="expert">icons/expert2.png</file>
|
<file alias="expert">resources/icons/expert2.png</file>
|
||||||
<file alias="done">icons/done.png</file>
|
<file alias="done">resources/icons/done.png</file>
|
||||||
<file alias="file">icons/file.png</file>
|
<file alias="file">resources/icons/file.png</file>
|
||||||
<file alias="labels">icons/labels.png</file>
|
<file alias="labels">resources/icons/labels.png</file>
|
||||||
<file alias="new">icons/objects.png</file>
|
<file alias="new">resources/icons/objects.png</file>
|
||||||
<file alias="close">icons/close.png</file>
|
<file alias="close">resources/icons/close.png</file>
|
||||||
<file alias="fit-width">icons/fit-width.png</file>
|
<file alias="fit-width">resources/icons/fit-width.png</file>
|
||||||
<file alias="fit-window">icons/fit-window.png</file>
|
<file alias="fit-window">resources/icons/fit-window.png</file>
|
||||||
<file alias="undo">icons/undo.png</file>
|
<file alias="undo">resources/icons/undo.png</file>
|
||||||
<file alias="hide">icons/eye.png</file>
|
<file alias="hide">resources/icons/eye.png</file>
|
||||||
<file alias="quit">icons/quit.png</file>
|
<file alias="quit">resources/icons/quit.png</file>
|
||||||
<file alias="copy">icons/copy.png</file>
|
<file alias="copy">resources/icons/copy.png</file>
|
||||||
<file alias="edit">icons/edit.png</file>
|
<file alias="edit">resources/icons/edit.png</file>
|
||||||
<file alias="open">icons/open.png</file>
|
<file alias="open">resources/icons/open.png</file>
|
||||||
<file alias="save">icons/save.png</file>
|
<file alias="save">resources/icons/save.png</file>
|
||||||
<file alias="format_voc">icons/format_voc.png</file>
|
<file alias="format_voc">resources/icons/format_voc.png</file>
|
||||||
<file alias="format_yolo">icons/format_yolo.png</file>
|
<file alias="format_yolo">resources/icons/format_yolo.png</file>
|
||||||
<file alias="save-as">icons/save-as.png</file>
|
<file alias="save-as">resources/icons/save-as.png</file>
|
||||||
<file alias="color">icons/color.png</file>
|
<file alias="color">resources/icons/color.png</file>
|
||||||
<file alias="color_line">icons/color_line.png</file>
|
<file alias="color_line">resources/icons/color_line.png</file>
|
||||||
<file alias="zoom">icons/zoom.png</file>
|
<file alias="zoom">resources/icons/zoom.png</file>
|
||||||
<file alias="zoom-in">icons/zoom-in.png</file>
|
<file alias="zoom-in">resources/icons/zoom-in.png</file>
|
||||||
<file alias="zoom-out">icons/zoom-out.png</file>
|
<file alias="zoom-out">resources/icons/zoom-out.png</file>
|
||||||
<file alias="delete">icons/cancel.png</file>
|
<file alias="delete">resources/icons/cancel.png</file>
|
||||||
<file alias="next">icons/next.png</file>
|
<file alias="next">resources/icons/next.png</file>
|
||||||
<file alias="prev">icons/prev.png</file>
|
<file alias="prev">resources/icons/prev.png</file>
|
||||||
<file alias="resetall">icons/resetall.png</file>
|
<file alias="resetall">resources/icons/resetall.png</file>
|
||||||
<file alias="verify">icons/verify.png</file>
|
<file alias="verify">resources/icons/verify.png</file>
|
||||||
|
<file alias="strings">resources/strings/strings.properties</file>
|
||||||
|
<file alias="strings-zh-TW">resources/strings/strings-zh-TW.properties</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 646 B After Width: | Height: | Size: 646 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 278 B After Width: | Height: | Size: 278 B |
|
Before Width: | Height: | Size: 335 B After Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 765 B After Width: | Height: | Size: 765 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 786 B |
|
Before Width: | Height: | Size: 675 B After Width: | Height: | Size: 675 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 977 B After Width: | Height: | Size: 977 B |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
65
resources/strings/strings-zh-TW.properties
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
saveAsDetail=將標籤保存到其他文件
|
||||||
|
changeSaveDir=改變存放目錄
|
||||||
|
openFile=開啟檔案
|
||||||
|
shapeLineColorDetail=更改線條顏色
|
||||||
|
resetAll=重置
|
||||||
|
crtBox=創建區塊
|
||||||
|
crtBoxDetail=畫一個區塊
|
||||||
|
dupBoxDetail=複製區塊
|
||||||
|
verifyImg=驗證圖像
|
||||||
|
zoominDetail=放大
|
||||||
|
verifyImgDetail=驗證圖像
|
||||||
|
saveDetail=將標籤存到
|
||||||
|
openFileDetail=打開圖像
|
||||||
|
fitWidthDetail=調整到窗口寬度
|
||||||
|
tutorial=YouTube教學
|
||||||
|
editLabel=編輯標籤
|
||||||
|
openAnnotationDetail=打開標籤文件
|
||||||
|
quit=結束
|
||||||
|
shapeFillColorDetail=更改填充顏色
|
||||||
|
closeCurDetail=關閉目前檔案
|
||||||
|
closeCur=關閉
|
||||||
|
fitWin=調整到跟窗口一樣大小
|
||||||
|
delBox=刪除選取區塊
|
||||||
|
boxLineColorDetail=選擇框線顏色
|
||||||
|
originalsize=原始大小
|
||||||
|
resetAllDetail=重設所有設定
|
||||||
|
zoomoutDetail=畫面放大
|
||||||
|
save=儲存
|
||||||
|
saveAs=另存為
|
||||||
|
fitWinDetail=縮放到窗口一樣
|
||||||
|
openDir=開啟目錄
|
||||||
|
showHide=顯示/隱藏標籤
|
||||||
|
changeSaveFormat=更改儲存格式
|
||||||
|
shapeFillColor=填充顏色
|
||||||
|
quitApp=離開本程式
|
||||||
|
dupBox=複製區塊
|
||||||
|
delBoxDetail=刪除區塊
|
||||||
|
zoomin=放大畫面
|
||||||
|
info=資訊
|
||||||
|
openAnnotation=開啟標籤
|
||||||
|
prevImgDetail=上一個圖像
|
||||||
|
fitWidth=縮放到跟畫面一樣寬
|
||||||
|
zoomout=縮小畫面
|
||||||
|
changeSavedAnnotationDir=更改預設標籤存的目錄
|
||||||
|
nextImgDetail=下一個圖像
|
||||||
|
originalsizeDetail=放大到原始大小
|
||||||
|
prevImg=上一個圖像
|
||||||
|
tutorialDetail=顯示示範內容
|
||||||
|
shapeLineColor=形狀線條顏色
|
||||||
|
boxLineColor=日期分隔線顏色
|
||||||
|
editLabelDetail=修改所選區塊的標籤
|
||||||
|
nextImg=下一張圖片
|
||||||
|
useDefaultLabel=使用預設標籤
|
||||||
|
useDifficult=有難度的
|
||||||
|
boxLabelText=區塊的標籤
|
||||||
|
labels=標籤
|
||||||
|
autoSaveMode=自動儲存模式
|
||||||
|
singleClsMode=單一類別模式
|
||||||
|
displayLabel=顯示類別
|
||||||
|
fileList=檔案清單
|
||||||
|
files=檔案
|
||||||
|
advancedMode=進階模式
|
||||||
|
advancedModeDetail=切到進階模式
|
||||||
|
showAllBoxDetail=顯示所有區塊
|
||||||
|
hideAllBoxDetail=隱藏所有區塊
|
||||||
65
resources/strings/strings.properties
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
openFile=Open
|
||||||
|
openFileDetail=Open image or label file
|
||||||
|
quit=Quit
|
||||||
|
quitApp=Quit application
|
||||||
|
openDir=Open Dir
|
||||||
|
changeSavedAnnotationDir=Change default saved Annotation dir
|
||||||
|
openAnnotation=Open Annotation
|
||||||
|
openAnnotationDetail=Open an annotation file
|
||||||
|
changeSaveDir=Change Save Dir
|
||||||
|
nextImg=Next Image
|
||||||
|
nextImgDetail=Open the next Image
|
||||||
|
prevImg=Prev Image
|
||||||
|
prevImgDetail=Open the previous Image
|
||||||
|
verifyImg=Verify Image
|
||||||
|
verifyImgDetail=Verify Image
|
||||||
|
save=Save
|
||||||
|
saveDetail=Save the labels to a file
|
||||||
|
changeSaveFormat=Change save format
|
||||||
|
saveAs=Save As
|
||||||
|
saveAsDetail=Save the labels to a different file
|
||||||
|
closeCur=Close
|
||||||
|
closeCurDetail=Close the current file
|
||||||
|
resetAll=Reset All
|
||||||
|
resetAllDetail=Reset All
|
||||||
|
boxLineColor=Box Line Color
|
||||||
|
boxLineColorDetail=Choose Box line color
|
||||||
|
crtBox=Create\nRectBox
|
||||||
|
crtBoxDetail=Draw a new box
|
||||||
|
delBox=Delete\nRectBox
|
||||||
|
delBoxDetail=Remove the box
|
||||||
|
dupBox=Duplicate\nRectBox
|
||||||
|
dupBoxDetail=Create a duplicate of the selected box
|
||||||
|
tutorial=Tutorial
|
||||||
|
tutorialDetail=Show demo
|
||||||
|
info=Information
|
||||||
|
zoomin=Zoom In
|
||||||
|
zoominDetail=Increase zoom level
|
||||||
|
zoomout=Zoom Out
|
||||||
|
zoomoutDetail=Decrease zoom level
|
||||||
|
originalsize=Original size
|
||||||
|
originalsizeDetail=Zoom to original size
|
||||||
|
fitWin=Fit Window
|
||||||
|
fitWinDetail=Zoom follows window size
|
||||||
|
fitWidth=Fit Widith
|
||||||
|
fitWidthDetail=Zoom follows window width
|
||||||
|
editLabel=Edit Label
|
||||||
|
editLabelDetail=Modify the label of the selected Box
|
||||||
|
shapeLineColor=Shape Line Color
|
||||||
|
shapeLineColorDetail=Change the line color for this specific shape
|
||||||
|
shapeFillColor=Shape Fill Color
|
||||||
|
shapeFillColorDetail=Change the fill color for this specific shape
|
||||||
|
showHide=Show/Hide Label Panel
|
||||||
|
useDefaultLabel=Use default labtel
|
||||||
|
useDifficult=difficult
|
||||||
|
boxLabelText=Box Labels
|
||||||
|
labels=Labels
|
||||||
|
autoSaveMode=Auto Save mode
|
||||||
|
singleClsMode=Single Class Mode
|
||||||
|
displayLabel=Display Labels
|
||||||
|
fileList=File List
|
||||||
|
files=Files
|
||||||
|
advancedMode=Advanced Mode
|
||||||
|
advancedModeDetail=Swtich to advanced mode
|
||||||
|
showAllBoxDetail=Show all bounding boxes
|
||||||
|
hideAllBoxDetail=Hide all bounding boxes
|
||||||
2
setup.py
@ -30,7 +30,7 @@ required_packages.append('labelImg')
|
|||||||
APP = ['labelImg.py']
|
APP = ['labelImg.py']
|
||||||
OPTIONS = {
|
OPTIONS = {
|
||||||
'argv_emulation': True,
|
'argv_emulation': True,
|
||||||
'iconfile': 'icons/app.icns'
|
'iconfile': 'resources/icons/app.icns'
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
|||||||
15
tests/test_lib.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from libs.lib import struct, newAction, newIcon, addActions, fmtShortcut, generateColorByText
|
||||||
|
|
||||||
|
class TestLib(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_generateColorByGivingUniceText_noError(self):
|
||||||
|
res = generateColorByText(u'\u958B\u555F\u76EE\u9304')
|
||||||
|
self.assertTrue(res.green() >= 0)
|
||||||
|
self.assertTrue(res.red() >= 0)
|
||||||
|
self.assertTrue(res.blue() >= 0)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
17
tests/test_stringBundle.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from stringBundle import StringBundle
|
||||||
|
|
||||||
|
class TestStringBundle(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_loadDefaultBundle_withoutError(self):
|
||||||
|
strBundle = StringBundle.getBundle('en')
|
||||||
|
self.assertEqual(strBundle.getString("openDir"), 'Open Dir', 'Fail to load the default bundle')
|
||||||
|
|
||||||
|
def test_fallback_withoutError(self):
|
||||||
|
strBundle = StringBundle.getBundle('zh-TW')
|
||||||
|
self.assertEqual(strBundle.getString("openDir"), u'\u958B\u555F\u76EE\u9304', 'Fail to load the zh-TW bundle')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||