diff --git a/PPOCRLabel/PPOCRLabel.py b/PPOCRLabel/PPOCRLabel.py index 3ee5eb60450be0c806316f70dea9b8d4c5f31503..05ac0a90b2101c891d320d0c1befb9bff3825930 100644 --- a/PPOCRLabel/PPOCRLabel.py +++ b/PPOCRLabel/PPOCRLabel.py @@ -11,64 +11,45 @@ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -#!/usr/bin/env python +# !/usr/bin/env python # -*- coding: utf-8 -*- # pyrcc5 -o libs/resources.py resources.qrc import argparse import ast import codecs +import json import os.path import platform import subprocess import sys from functools import partial -from collections import defaultdict -import json -import cv2 - +try: + from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5.QtGui import * + from PyQt5.QtCore import * + from PyQt5.QtWidgets import * +except ImportError: + print("Please install pyqt5...") __dir__ = os.path.dirname(os.path.abspath(__file__)) -import numpy as np - - sys.path.append(__dir__) sys.path.append(os.path.abspath(os.path.join(__dir__, '../..'))) sys.path.append(os.path.abspath(os.path.join(__dir__, '../PaddleOCR'))) sys.path.append("..") from paddleocr import PaddleOCR - -try: - from PyQt5 import QtCore, QtGui, QtWidgets - 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 * - -from combobox import ComboBox from libs.constants import * from libs.utils import * from libs.settings import Settings -from libs.shape import Shape, DEFAULT_LINE_COLOR, DEFAULT_FILL_COLOR,DEFAULT_LOCK_COLOR +from libs.shape import Shape, DEFAULT_LINE_COLOR, DEFAULT_FILL_COLOR, DEFAULT_LOCK_COLOR from libs.stringBundle import StringBundle from libs.canvas import Canvas from libs.zoomWidget import ZoomWidget from libs.autoDialog import AutoDialog from libs.labelDialog import LabelDialog from libs.colorDialog import ColorDialog -from libs.toolBar import ToolBar from libs.ustr import ustr from libs.hashableQListWidgetItem import HashableQListWidgetItem from libs.editinlist import EditInList @@ -76,29 +57,15 @@ from libs.editinlist import EditInList __appname__ = 'PPOCRLabel' -class WindowMixin(object): - - def menu(self, title, actions=None): - menu = self.menuBar().addMenu(title) - if actions: - addActions(menu, actions) - return menu - - def toolbar(self, title, actions=None): - toolbar = ToolBar(title) - toolbar.setObjectName(u'%sToolBar' % title) - # toolbar.setOrientation(Qt.Vertical) - toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) - if actions: - addActions(toolbar, actions) - self.addToolBar(Qt.LeftToolBarArea, toolbar) - return toolbar - - -class MainWindow(QMainWindow, WindowMixin): +class MainWindow(QMainWindow): FIT_WINDOW, FIT_WIDTH, MANUAL_ZOOM = list(range(3)) - def __init__(self, lang="ch", gpu=False, defaultFilename=None, defaultPrefdefClassFile=None, defaultSaveDir=None): + def __init__(self, + lang="ch", + gpu=False, + default_filename=None, + default_predicted_class_file=None, + default_save_dir=None): super(MainWindow, self).__init__() self.setWindowTitle(__appname__) self.setWindowState(Qt.WindowMaximized) # set window max @@ -112,11 +79,17 @@ class MainWindow(QMainWindow, WindowMixin): # Load string bundle for i18n if lang not in ['ch', 'en']: lang = 'en' - self.stringBundle = StringBundle.getBundle(localeStr='zh-CN' if lang=='ch' else 'en') # 'en' + self.stringBundle = StringBundle.getBundle(localeStr='zh-CN' if lang == 'ch' else 'en') # 'en' getStr = lambda strId: self.stringBundle.getString(strId) - self.defaultSaveDir = defaultSaveDir - self.ocr = PaddleOCR(use_pdserving=False, use_angle_cls=True, det=True, cls=True, use_gpu=gpu, lang=lang, show_log=False) + self.defaultSaveDir = default_save_dir + self.ocr = PaddleOCR(use_pdserving=False, + use_angle_cls=True, + det=True, + cls=True, + use_gpu=gpu, + lang=lang, + show_log=False) if os.path.exists('./data/paddle.png'): result = self.ocr.ocr('./data/paddle.png', cls=True, det=True) @@ -134,7 +107,6 @@ class MainWindow(QMainWindow, WindowMixin): self.labelFile = None self.currIndex = 0 - # Whether we need to save or not. self.dirty = False @@ -144,7 +116,7 @@ class MainWindow(QMainWindow, WindowMixin): self.screencast = "https://github.com/PaddlePaddle/PaddleOCR" # Load predefined classes to the list - self.loadPredefinedClasses(defaultPrefdefClassFile) + self.loadPredefinedClasses(default_predicted_class_file) # Main widgets and related state. self.labelDialog = LabelDialog(parent=self, listItem=self.labelHist) @@ -160,7 +132,7 @@ class MainWindow(QMainWindow, WindowMixin): self.PPreader = None self.autoSaveNum = 5 - ################# file list ############### + # ================== File List ================== self.fileListWidget = QListWidget() self.fileListWidget.itemClicked.connect(self.fileitemDoubleClicked) self.fileListWidget.setIconSize(QSize(25, 25)) @@ -181,12 +153,12 @@ class MainWindow(QMainWindow, WindowMixin): fileListContainer = QWidget() fileListContainer.setLayout(filelistLayout) self.fileListName = getStr('fileList') - self.filedock = QDockWidget(self.fileListName, self) - self.filedock.setObjectName(getStr('files')) - self.filedock.setWidget(fileListContainer) - self.addDockWidget(Qt.LeftDockWidgetArea, self.filedock) + self.file_dock = QDockWidget(self.fileListName, self) + self.file_dock.setObjectName(getStr('files')) + self.file_dock.setWidget(fileListContainer) + self.addDockWidget(Qt.LeftDockWidgetArea, self.file_dock) - ######## Right area ########## + # ================== Right Area ================== listLayout = QVBoxLayout() listLayout.setContentsMargins(0, 0, 0, 0) @@ -202,7 +174,6 @@ class MainWindow(QMainWindow, WindowMixin): self.DelButton = QToolButton() self.DelButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) - lefttoptoolbox = QHBoxLayout() lefttoptoolbox.addWidget(self.newButton) lefttoptoolbox.addWidget(self.reRecogButton) @@ -210,26 +181,25 @@ class MainWindow(QMainWindow, WindowMixin): lefttoptoolboxcontainer.setLayout(lefttoptoolbox) listLayout.addWidget(lefttoptoolboxcontainer) - - ################## label list #################### + # ================== Label List ================== # Create and add a widget for showing current label items self.labelList = EditInList() labelListContainer = QWidget() labelListContainer.setLayout(listLayout) - #self.labelList.itemActivated.connect(self.labelSelectionChanged) + # self.labelList.itemActivated.connect(self.labelSelectionChanged) self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged) self.labelList.clicked.connect(self.labelList.item_clicked) # Connect to itemChanged to detect checkbox changes. self.labelList.itemChanged.connect(self.labelItemChanged) - self.labelListDock = QDockWidget(getStr('recognitionResult'),self) + self.labelListDock = QDockWidget(getStr('recognitionResult'), self) self.labelListDock.setWidget(self.labelList) self.labelListDock.setFeatures(QDockWidget.NoDockWidgetFeatures) listLayout.addWidget(self.labelListDock) - ################## detection box #################### + # ================== Detection Box ================== self.BoxList = QListWidget() - #self.BoxList.itemActivated.connect(self.boxSelectionChanged) + # self.BoxList.itemActivated.connect(self.boxSelectionChanged) self.BoxList.itemSelectionChanged.connect(self.boxSelectionChanged) self.BoxList.itemDoubleClicked.connect(self.editBox) # Connect to itemChanged to detect checkbox changes. @@ -239,7 +209,7 @@ class MainWindow(QMainWindow, WindowMixin): self.BoxListDock.setFeatures(QDockWidget.NoDockWidgetFeatures) listLayout.addWidget(self.BoxListDock) - ############ lower right area ############ + # ================== Lower Right Area ================== leftbtmtoolbox = QHBoxLayout() leftbtmtoolbox.addWidget(self.SaveButton) leftbtmtoolbox.addWidget(self.DelButton) @@ -251,8 +221,7 @@ class MainWindow(QMainWindow, WindowMixin): self.dock.setObjectName(getStr('labels')) self.dock.setWidget(labelListContainer) - - ########## zoom bar ######### + # ================== Zoom Bar ================== self.imgsplider = QSlider(Qt.Horizontal) self.imgsplider.valueChanged.connect(self.CanvasSizeChange) self.imgsplider.setMinimum(-150) @@ -278,13 +247,13 @@ class MainWindow(QMainWindow, WindowMixin): self.msgBox = QMessageBox() - ########## thumbnail ######### + # ================== Thumbnail ================== hlayout = QHBoxLayout() m = (0, 0, 0, 0) hlayout.setSpacing(0) hlayout.setContentsMargins(*m) self.preButton = QToolButton() - self.preButton.setIcon(newIcon("prev",40)) + self.preButton.setIcon(newIcon("prev", 40)) self.preButton.setIconSize(QSize(40, 100)) self.preButton.clicked.connect(self.openPrevImg) self.preButton.setStyleSheet('border: none;') @@ -294,7 +263,7 @@ class MainWindow(QMainWindow, WindowMixin): self.iconlist.setFlow(QListView.TopToBottom) self.iconlist.setSpacing(10) self.iconlist.setIconSize(QSize(50, 50)) - self.iconlist.setMovement(False) + self.iconlist.setMovement(QListView.Static) self.iconlist.setResizeMode(QListView.Adjust) self.iconlist.itemClicked.connect(self.iconitemDoubleClicked) self.iconlist.setStyleSheet("background-color:transparent; border: none;") @@ -310,12 +279,11 @@ class MainWindow(QMainWindow, WindowMixin): hlayout.addWidget(self.iconlist) hlayout.addWidget(self.nextButton) - iconListContainer = QWidget() iconListContainer.setLayout(hlayout) iconListContainer.setFixedHeight(100) - ########### Canvas ########### + # ================== Canvas ================== self.canvas = Canvas(parent=self) self.canvas.zoomRequest.connect(self.zoomRequest) self.canvas.setDrawingShapeToSquare(settings.get(SETTING_DRAW_SQUARE, False)) @@ -338,32 +306,17 @@ class MainWindow(QMainWindow, WindowMixin): centerLayout = QVBoxLayout() centerLayout.setContentsMargins(0, 0, 0, 0) centerLayout.addWidget(scroll) - #centerLayout.addWidget(self.icondock) - centerLayout.addWidget(iconListContainer,0,Qt.AlignCenter) - centercontainer = QWidget() - centercontainer.setLayout(centerLayout) - - # self.scrolldock = QDockWidget('WorkSpace',self) - # self.scrolldock.setObjectName('WorkSpace') - # self.scrolldock.setWidget(centercontainer) - # self.scrolldock.setFeatures(QDockWidget.NoDockWidgetFeatures) - # orititle = self.scrolldock.titleBarWidget() - # tmpwidget = QWidget() - # self.scrolldock.setTitleBarWidget(tmpwidget) - # del orititle - self.setCentralWidget(centercontainer) #self.scrolldock - self.addDockWidget(Qt.RightDockWidgetArea, self.dock) - - - # self.filedock.setFeatures(QDockWidget.DockWidgetFloatable) - self.filedock.setFeatures(self.filedock.features() ^ QDockWidget.DockWidgetFloatable) + centerLayout.addWidget(iconListContainer, 0, Qt.AlignCenter) + centerContainer = QWidget() + centerContainer.setLayout(centerLayout) - self.dockFeatures = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable - self.dock.setFeatures(self.dock.features() ^ self.dockFeatures) + self.setCentralWidget(centerContainer) + self.addDockWidget(Qt.RightDockWidgetArea, self.dock) - self.filedock.setFeatures(QDockWidget.NoDockWidgetFeatures) + self.dock.setFeatures(QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable) + self.file_dock.setFeatures(QDockWidget.NoDockWidgetFeatures) - ###### Actions ####### + # ================== Actions ================== action = partial(newAction, self) quit = action(getStr('quit'), self.close, 'Ctrl+Q', 'quit', getStr('quitApp')) @@ -372,13 +325,13 @@ class MainWindow(QMainWindow, WindowMixin): 'Ctrl+u', 'open', getStr('openDir')) open_dataset_dir = action(getStr('openDatasetDir'), self.openDatasetDirDialog, - 'Ctrl+p', 'open', getStr('openDatasetDir'), enabled=False) + 'Ctrl+p', 'open', getStr('openDatasetDir'), enabled=False) save = action(getStr('save'), self.saveFile, 'Ctrl+V', 'verify', getStr('saveDetail'), enabled=False) alcm = action(getStr('choosemodel'), self.autolcm, - 'Ctrl+M', 'next', getStr('tipchoosemodel')) + 'Ctrl+M', 'next', getStr('tipchoosemodel')) deleteImg = action(getStr('deleteImg'), self.deleteImg, 'Ctrl+Shift+D', 'close', getStr('deleteImgDetail'), enabled=True) @@ -398,7 +351,7 @@ class MainWindow(QMainWindow, WindowMixin): delete = action(getStr('delBox'), self.deleteSelectedShape, 'Alt+X', 'delete', getStr('delBoxDetail'), enabled=False) - + copy = action(getStr('dupBox'), self.copySelectedShape, 'Ctrl+C', 'copy', getStr('dupBoxDetail'), enabled=False) @@ -409,7 +362,6 @@ class MainWindow(QMainWindow, WindowMixin): showAll = action(getStr('showBox'), partial(self.togglePolygons, True), 'Ctrl+A', 'hide', getStr('showAllBoxDetail'), enabled=False) - help = action(getStr('tutorial'), self.showTutorialDialog, None, 'help', getStr('tutorialDetail')) showInfo = action(getStr('info'), self.showInfoDialog, None, 'help', getStr('info')) @@ -453,10 +405,10 @@ class MainWindow(QMainWindow, WindowMixin): ######## New actions ####### AutoRec = action(getStr('autoRecognition'), self.autoRecognition, - '', 'Auto', getStr('autoRecognition'), enabled=False) + '', 'Auto', getStr('autoRecognition'), enabled=False) reRec = action(getStr('reRecognition'), self.reRecognition, - 'Ctrl+Shift+R', 'reRec', getStr('reRecognition'), enabled=False) + 'Ctrl+Shift+R', 'reRec', getStr('reRecognition'), enabled=False) singleRere = action(getStr('singleRe'), self.singleRerecognition, 'Ctrl+R', 'reRec', getStr('singleRe'), enabled=False) @@ -465,23 +417,23 @@ class MainWindow(QMainWindow, WindowMixin): 'q', 'new', getStr('creatPolygon'), enabled=True) saveRec = action(getStr('saveRec'), self.saveRecResult, - '', 'save', getStr('saveRec'), enabled=False) + '', 'save', getStr('saveRec'), enabled=False) - saveLabel = action(getStr('saveLabel'), self.saveLabelFile, # - 'Ctrl+S', 'save', getStr('saveLabel'), enabled=False) + saveLabel = action(getStr('saveLabel'), self.saveLabelFile, # + 'Ctrl+S', 'save', getStr('saveLabel'), enabled=False) undoLastPoint = action(getStr("undoLastPoint"), self.canvas.undoLastPoint, 'Ctrl+Z', "undo", getStr("undoLastPoint"), enabled=False) - rotateLeft = action(getStr("rotateLeft"), partial(self.rotateImgAction,1), - 'Ctrl+Alt+L', "rotateLeft", getStr("rotateLeft"), enabled=False) + rotateLeft = action(getStr("rotateLeft"), partial(self.rotateImgAction, 1), + 'Ctrl+Alt+L', "rotateLeft", getStr("rotateLeft"), enabled=False) - rotateRight = action(getStr("rotateRight"), partial(self.rotateImgAction,-1), - 'Ctrl+Alt+R', "rotateRight", getStr("rotateRight"), enabled=False) + rotateRight = action(getStr("rotateRight"), partial(self.rotateImgAction, -1), + 'Ctrl+Alt+R', "rotateRight", getStr("rotateRight"), enabled=False) undo = action(getStr("undo"), self.undoShapeEdit, 'Ctrl+Z', "undo", getStr("undo"), enabled=False) - + lock = action(getStr("lockBox"), self.lockSelectedShape, None, "lock", getStr("lockBoxDetail"), enabled=False) @@ -522,7 +474,6 @@ class MainWindow(QMainWindow, WindowMixin): icon='color', tip=getStr('shapeFillColorDetail'), enabled=False) - # Label list context menu. labelMenu = QMenu() addActions(labelMenu, (edit, delete)) @@ -538,39 +489,36 @@ class MainWindow(QMainWindow, WindowMixin): self.drawSquaresOption.triggered.connect(self.toogleDrawSquare) # Store actions for further handling. - self.actions = struct(save=save, resetAll=resetAll, deleteImg=deleteImg, + self.actions = struct(save=save, resetAll=resetAll, deleteImg=deleteImg, lineColor=color1, create=create, delete=delete, edit=edit, copy=copy, - saveRec=saveRec, singleRere=singleRere,AutoRec=AutoRec,reRec=reRec, + saveRec=saveRec, singleRere=singleRere, AutoRec=AutoRec, reRec=reRec, createMode=createMode, editMode=editMode, shapeLineColor=shapeLineColor, shapeFillColor=shapeFillColor, zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, fitWindow=fitWindow, fitWidth=fitWidth, zoomActions=zoomActions, saveLabel=saveLabel, - undo=undo, undoLastPoint=undoLastPoint,open_dataset_dir=open_dataset_dir, - rotateLeft=rotateLeft,rotateRight=rotateRight,lock=lock, - fileMenuActions=( - opendir, open_dataset_dir, saveLabel, resetAll, quit), + undo=undo, undoLastPoint=undoLastPoint, open_dataset_dir=open_dataset_dir, + rotateLeft=rotateLeft, rotateRight=rotateRight, lock=lock, + fileMenuActions=(opendir, open_dataset_dir, saveLabel, resetAll, quit), beginner=(), advanced=(), - editMenu=(createpoly, edit, copy, delete,singleRere,None, undo, undoLastPoint, - None, rotateLeft, rotateRight, None, color1, self.drawSquaresOption,lock), - beginnerContext=(create, edit, copy, delete, singleRere, rotateLeft, rotateRight,lock), + editMenu=(createpoly, edit, copy, delete, singleRere, None, undo, undoLastPoint, + None, rotateLeft, rotateRight, None, color1, self.drawSquaresOption, lock), + beginnerContext=(create, edit, copy, delete, singleRere, rotateLeft, rotateRight, lock), advancedContext=(createMode, editMode, edit, copy, delete, shapeLineColor, shapeFillColor), - onLoadActive=( - create, createMode, editMode), + onLoadActive=(create, createMode, editMode), onShapesPresent=(hideAll, showAll)) # menus self.menus = struct( - file=self.menu('&'+getStr('mfile')), - edit=self.menu('&'+getStr('medit')), - view=self.menu('&'+getStr('mview')), + file=self.menu('&' + getStr('mfile')), + edit=self.menu('&' + getStr('medit')), + view=self.menu('&' + getStr('mview')), autolabel=self.menu('&PaddleOCR'), - help=self.menu('&'+getStr('mhelp')), + help=self.menu('&' + getStr('mhelp')), recentFiles=QMenu('Open &Recent'), labelList=labelMenu) - self.lastLabel = None # Add option to enable/disable labels being displayed at the top of bounding boxes self.displayLabelOption = QAction(getStr('displayLabel'), self) @@ -591,33 +539,30 @@ class MainWindow(QMainWindow, WindowMixin): self.autoSaveOption.triggered.connect(self.autoSaveFunc) addActions(self.menus.file, - (opendir, open_dataset_dir, None, saveLabel, saveRec, self.autoSaveOption, None, resetAll, deleteImg, quit)) + (opendir, open_dataset_dir, None, saveLabel, saveRec, self.autoSaveOption, None, resetAll, deleteImg, + quit)) - addActions(self.menus.help, (showKeys,showSteps, showInfo)) + addActions(self.menus.help, (showKeys, showSteps, showInfo)) addActions(self.menus.view, ( self.displayLabelOption, self.labelDialogOption, - None, + None, hideAll, showAll, None, zoomIn, zoomOut, zoomOrg, None, fitWindow, fitWidth)) - addActions(self.menus.autolabel, (AutoRec, reRec, alcm, None, help)) # + addActions(self.menus.autolabel, (AutoRec, reRec, alcm, None, help)) self.menus.file.aboutToShow.connect(self.updateFileMenu) # Custom context menu for the canvas widget: addActions(self.canvas.menus[0], self.actions.beginnerContext) - #addActions(self.canvas.menus[1], ( - # action('&Copy here', self.copyShape), - # action('&Move here', self.moveShape))) - self.statusBar().showMessage('%s started.' % __appname__) self.statusBar().show() # Application state. self.image = QImage() - self.filePath = ustr(defaultFilename) + self.filePath = ustr(default_filename) self.lastOpenDir = None self.recentFiles = [] self.maxRecent = 7 @@ -628,7 +573,7 @@ class MainWindow(QMainWindow, WindowMixin): # Add Chris self.difficult = False - ## Fix the compatible issue for qt4 and qt5. Convert the QStringList to python list + # Fix the compatible issue for qt4 and qt5. Convert the QStringList to python list if settings.get(SETTING_RECENT_FILES): if have_qstring(): recentFileQStringList = settings.get(SETTING_RECENT_FILES) @@ -657,7 +602,6 @@ class MainWindow(QMainWindow, WindowMixin): # Add chris Shape.difficult = self.difficult - # ADD: # Populate the File menu dynamically. self.updateFileMenu() @@ -681,6 +625,12 @@ class MainWindow(QMainWindow, WindowMixin): if self.filePath and os.path.isdir(self.filePath): self.openDirDialog(dirpath=self.filePath, silent=True) + def menu(self, title, actions=None): + menu = self.menuBar().addMenu(title) + if actions: + addActions(menu, actions) + return menu + def keyReleaseEvent(self, event): if event.key() == Qt.Key_Control: self.canvas.setDrawingShapeToSquare(False) @@ -690,11 +640,9 @@ class MainWindow(QMainWindow, WindowMixin): # Draw rectangle if Ctrl is pressed self.canvas.setDrawingShapeToSquare(True) - def noShapes(self): return not self.itemsToShapes - def populateModeActions(self): self.canvas.menus[0].clear() addActions(self.canvas.menus[0], self.actions.beginnerContext) @@ -702,7 +650,6 @@ class MainWindow(QMainWindow, WindowMixin): actions = (self.actions.create,) # if self.beginner() else (self.actions.createMode, self.actions.editMode) addActions(self.menus.edit, actions + self.actions.editMenu) - def setDirty(self): self.dirty = True self.actions.save.setEnabled(True) @@ -816,10 +763,11 @@ class MainWindow(QMainWindow, WindowMixin): def rotateImgWarn(self): if self.lang == 'ch': - self.msgBox.warning (self, "提示", "\n 该图片已经有标注框,旋转操作会打乱标注,建议清除标注框后旋转。") + self.msgBox.warning(self, "提示", "\n 该图片已经有标注框,旋转操作会打乱标注,建议清除标注框后旋转。") else: - self.msgBox.warning (self, "Warn", "\n The picture already has a label box, and rotation will disrupt the label.\ - It is recommended to clear the label box and rotate it.") + self.msgBox.warning(self, "Warn", "\n The picture already has a label box, " + "and rotation will disrupt the label. " + "It is recommended to clear the label box and rotate it.") def rotateImgAction(self, k=1, _value=False): @@ -894,8 +842,7 @@ class MainWindow(QMainWindow, WindowMixin): self.setDirty() self.updateComboBox() - ######## detection box related functions ####### - + # =================== detection box related functions =================== def boxItemChanged(self, item): shape = self.itemsToShapesbox[item] @@ -909,7 +856,7 @@ class MainWindow(QMainWindow, WindowMixin): # shape.line_color = generateColorByText(shape.label) self.setDirty() else: # User probably changed item visibility - self.canvas.setShapeVisible(shape, True)#item.checkState() == Qt.Checked + self.canvas.setShapeVisible(shape, True) # item.checkState() == Qt.Checked def editBox(self): # ADD if not self.canvas.editing(): @@ -959,11 +906,10 @@ class MainWindow(QMainWindow, WindowMixin): def indexTo5Files(self, currIndex): if currIndex < 2: return self.mImgList[:5] - elif currIndex > len(self.mImgList)-3: + elif currIndex > len(self.mImgList) - 3: return self.mImgList[-5:] else: - return self.mImgList[currIndex - 2 : currIndex + 3] - + return self.mImgList[currIndex - 2: currIndex + 3] # Tzutalin 20160906 : Add file list and dock to move faster def fileitemDoubleClicked(self, item=None): @@ -986,7 +932,6 @@ class MainWindow(QMainWindow, WindowMixin): if len(self.mImgList) > 0: self.zoomWidget.setValue(self.zoomWidgetValue + self.imgsplider.value()) - def shapeSelectionChanged(self, selected_shapes): self._noSelectionSlot = True for shape in self.canvas.selectedShapes: @@ -998,7 +943,7 @@ class MainWindow(QMainWindow, WindowMixin): self.shapesToItems[shape].setSelected(True) self.shapesToItemsbox[shape].setSelected(True) - self.labelList.scrollToItem(self.currentItem()) # QAbstractItemView.EnsureVisible + self.labelList.scrollToItem(self.currentItem()) # QAbstractItemView.EnsureVisible self.BoxList.scrollToItem(self.currentBox()) self._noSelectionSlot = False @@ -1051,7 +996,7 @@ class MainWindow(QMainWindow, WindowMixin): def loadLabels(self, shapes): s = [] for label, points, line_color, fill_color, difficult in shapes: - shape = Shape(label=label,line_color=line_color) + shape = Shape(label=label, line_color=line_color) for x, y in points: # Ensure the labels are within the bounds of the image. If not, fix them. @@ -1061,7 +1006,7 @@ class MainWindow(QMainWindow, WindowMixin): shape.addPoint(QPointF(x, y)) shape.difficult = difficult - #shape.locked = False + # shape.locked = False shape.close() s.append(shape) @@ -1074,12 +1019,11 @@ class MainWindow(QMainWindow, WindowMixin): # shape.fill_color = QColor(*fill_color) # else: # shape.fill_color = generateColorByText(label) - + self.addLabel(shape) - + self.updateComboBox() self.canvas.loadShapes(s) - def singleLabel(self, shape): if shape is None: @@ -1115,13 +1059,13 @@ class MainWindow(QMainWindow, WindowMixin): line_color=s.line_color.getRgb(), fill_color=s.fill_color.getRgb(), points=[(int(p.x()), int(p.y())) for p in s.points], # QPonitF - # add chris + # add chris difficult=s.difficult) # bool shapes = [] if mode == 'Auto' else \ [format_shape(shape) for shape in self.canvas.shapes if shape.line_color != DEFAULT_LOCK_COLOR] # Can add differrent annotation formats here - for box in self.result_dic : + for box in self.result_dic: trans_dic = {"label": box[1][0], "points": box[0], 'difficult': False} if trans_dic["label"] == "" and mode == 'Auto': continue @@ -1130,7 +1074,8 @@ class MainWindow(QMainWindow, WindowMixin): try: trans_dic = [] for box in shapes: - trans_dic.append({"transcription": box['label'], "points": box['points'], 'difficult': box['difficult']}) + trans_dic.append( + {"transcription": box['label'], "points": box['points'], 'difficult': box['difficult']}) self.PPlabel[annotationFilePath] = trans_dic if mode == 'Auto': self.Cachelabel[annotationFilePath] = trans_dic @@ -1148,8 +1093,7 @@ class MainWindow(QMainWindow, WindowMixin): for shape in self.canvas.copySelectedShape(): self.addLabel(shape) # fix copy and delete - #self.shapeSelectionChanged(True) - + # self.shapeSelectionChanged(True) def labelSelectionChanged(self): if self._noSelectionSlot: @@ -1163,10 +1107,9 @@ class MainWindow(QMainWindow, WindowMixin): else: self.canvas.deSelectShape() - def boxSelectionChanged(self): if self._noSelectionSlot: - #self.BoxList.scrollToItem(self.currentBox(), QAbstractItemView.PositionAtCenter) + # self.BoxList.scrollToItem(self.currentBox(), QAbstractItemView.PositionAtCenter) return if self.canvas.editing(): selected_shapes = [] @@ -1177,7 +1120,6 @@ class MainWindow(QMainWindow, WindowMixin): else: self.canvas.deSelectShape() - def labelItemChanged(self, item): shape = self.itemsToShapes[item] label = item.text() @@ -1185,7 +1127,7 @@ class MainWindow(QMainWindow, WindowMixin): shape.label = item.text() # shape.line_color = generateColorByText(shape.label) self.setDirty() - elif not ((item.checkState()== Qt.Unchecked) ^ (not shape.difficult)): + elif not ((item.checkState() == Qt.Unchecked) ^ (not shape.difficult)): shape.difficult = True if item.checkState() == Qt.Unchecked else False self.setDirty() else: # User probably changed item visibility @@ -1211,7 +1153,7 @@ class MainWindow(QMainWindow, WindowMixin): if text is not None: self.prevLabelText = self.stringBundle.getString('tempLabel') # generate_color = generateColorByText(text) - shape = self.canvas.setLastLabel(text, None, None)#generate_color, generate_color + shape = self.canvas.setLastLabel(text, None, None) # generate_color, generate_color self.addLabel(shape) if self.beginner(): # Switch to edit mode. self.canvas.setEditing(True) @@ -1324,7 +1266,7 @@ class MainWindow(QMainWindow, WindowMixin): # unicodeFilePath = os.path.abspath(unicodeFilePath) # Tzutalin 20160906 : Add file list and dock to move faster # Highlight the file item - + if unicodeFilePath and self.fileListWidget.count() > 0: if unicodeFilePath in self.mImgList: index = self.mImgList.index(unicodeFilePath) @@ -1334,7 +1276,7 @@ class MainWindow(QMainWindow, WindowMixin): ### self.iconlist.clear() self.additems5(None) - + for i in range(5): item_tooltip = self.iconlist.item(i).toolTip() # print(i,"---",item_tooltip) @@ -1385,7 +1327,7 @@ class MainWindow(QMainWindow, WindowMixin): self.showBoundingBoxFromPPlabel(filePath) self.setWindowTitle(__appname__ + ' ' + filePath) - + # Default : select last item if there is at least one item if self.labelList.count(): self.labelList.setCurrentItem(self.labelList.item(self.labelList.count() - 1)) @@ -1394,9 +1336,8 @@ class MainWindow(QMainWindow, WindowMixin): # show file list image count select_indexes = self.fileListWidget.selectedIndexes() if len(select_indexes) > 0: - self.filedock.setWindowTitle(self.fileListName + f" ({select_indexes[0].row() + 1}" - f"/{self.fileListWidget.count()})") - + self.file_dock.setWindowTitle(self.fileListName + f" ({select_indexes[0].row() + 1}" + f"/{self.fileListWidget.count()})") self.canvas.setFocus(True) return True @@ -1405,24 +1346,23 @@ class MainWindow(QMainWindow, WindowMixin): def showBoundingBoxFromPPlabel(self, filePath): width, height = self.image.width(), self.image.height() imgidx = self.getImglabelidx(filePath) - shapes =[] - #box['ratio'] of the shapes saved in lockedShapes contains the ratio of the + shapes = [] + # box['ratio'] of the shapes saved in lockedShapes contains the ratio of the # four corner coordinates of the shapes to the height and width of the image for box in self.canvas.lockedShapes: if self.canvas.isInTheSameImage: - shapes.append((box['transcription'], [[s[0]*width,s[1]*height]for s in box['ratio']], - DEFAULT_LOCK_COLOR, None, box['difficult'])) + shapes.append((box['transcription'], [[s[0] * width, s[1] * height] for s in box['ratio']], + DEFAULT_LOCK_COLOR, None, box['difficult'])) else: - shapes.append(('锁定框:待检测', [[s[0]*width,s[1]*height]for s in box['ratio']], - DEFAULT_LOCK_COLOR, None, box['difficult'])) + shapes.append(('锁定框:待检测', [[s[0] * width, s[1] * height] for s in box['ratio']], + DEFAULT_LOCK_COLOR, None, box['difficult'])) if imgidx in self.PPlabel.keys(): for box in self.PPlabel[imgidx]: shapes.append((box['transcription'], box['points'], None, None, box['difficult'])) - + self.loadLabels(shapes) self.canvas.verified = False - def validFilestate(self, filePath): if filePath not in self.fileStatedict.keys(): return None @@ -1433,7 +1373,7 @@ class MainWindow(QMainWindow, WindowMixin): def resizeEvent(self, event): if self.canvas and not self.image.isNull() \ - and self.zoomMode != self.MANUAL_ZOOM: + and self.zoomMode != self.MANUAL_ZOOM: self.adjustScale() super(MainWindow, self).resizeEvent(event) @@ -1451,7 +1391,7 @@ class MainWindow(QMainWindow, WindowMixin): """Figure out the size of the pixmap in order to fit the main widget.""" e = 2.0 # So that no scrollbars are generated. w1 = self.centralWidget().width() - e - h1 = self.centralWidget().height() - e -110 + h1 = self.centralWidget().height() - e - 110 a1 = w1 / h1 # Calculate a new scale value based on the pixmap's aspect ratio. w2 = self.canvas.pixmap.width() - 0.0 @@ -1502,7 +1442,7 @@ class MainWindow(QMainWindow, WindowMixin): def loadRecent(self, filename): if self.mayContinue(): - print(filename,"======") + print(filename, "======") self.loadFile(filename) def scanAllImages(self, folderPath): @@ -1517,8 +1457,6 @@ class MainWindow(QMainWindow, WindowMixin): natural_sort(images, key=lambda x: x.lower()) return images - - def openDirDialog(self, _value=False, dirpath=None, silent=False): if not self.mayContinue(): return @@ -1530,15 +1468,15 @@ class MainWindow(QMainWindow, WindowMixin): defaultOpenDirPath = os.path.dirname(self.filePath) if self.filePath else '.' if silent != True: targetDirPath = ustr(QFileDialog.getExistingDirectory(self, - '%s - Open Directory' % __appname__, - defaultOpenDirPath, - QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)) + '%s - Open Directory' % __appname__, + defaultOpenDirPath, + QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)) else: targetDirPath = ustr(defaultOpenDirPath) self.lastOpenDir = targetDirPath self.importDirImages(targetDirPath) - def openDatasetDirDialog(self,): + def openDatasetDirDialog(self): if self.lastOpenDir and os.path.exists(self.lastOpenDir): if platform.system() == 'Windows': os.startfile(self.lastOpenDir) @@ -1550,12 +1488,13 @@ class MainWindow(QMainWindow, WindowMixin): if self.lang == 'ch': self.msgBox.warning(self, "提示", "\n 原文件夹已不存在,请从新选择数据集路径!") else: - self.msgBox.warning(self, "Warn", "\n The original folder no longer exists, please choose the data set path again!") + self.msgBox.warning(self, "Warn", + "\n The original folder no longer exists, please choose the data set path again!") self.actions.open_dataset_dir.setEnabled(False) defaultOpenDirPath = os.path.dirname(self.filePath) if self.filePath else '.' - def importDirImages(self, dirpath, isDelete = False): + def importDirImages(self, dirpath, isDelete=False): if not self.mayContinue() or not dirpath: return if self.defaultSaveDir and self.defaultSaveDir != dirpath: @@ -1563,7 +1502,7 @@ class MainWindow(QMainWindow, WindowMixin): if not isDelete: self.loadFilestate(dirpath) - self.PPlabelpath = dirpath+ '/Label.txt' + self.PPlabelpath = dirpath + '/Label.txt' self.PPlabel = self.loadLabelFile(self.PPlabelpath) self.Cachelabelpath = dirpath + '/Cache.cach' self.Cachelabel = self.loadLabelFile(self.Cachelabelpath) @@ -1572,7 +1511,6 @@ class MainWindow(QMainWindow, WindowMixin): self.lastOpenDir = dirpath self.dirname = dirpath - self.defaultSaveDir = dirpath self.statusBar().showMessage('%s started. Annotation will be saved to %s' % (__appname__, self.defaultSaveDir)) @@ -1607,7 +1545,7 @@ class MainWindow(QMainWindow, WindowMixin): self.actions.rotateRight.setEnabled(True) self.fileListWidget.setCurrentRow(0) # set list index to first - self.filedock.setWindowTitle(self.fileListName + f" (1/{self.fileListWidget.count()})") # show image count + self.file_dock.setWindowTitle(self.fileListName + f" (1/{self.fileListWidget.count()})") # show image count def openPrevImg(self, _value=False): if len(self.mImgList) <= 0: @@ -1643,7 +1581,7 @@ class MainWindow(QMainWindow, WindowMixin): else: self.mImgList5 = self.indexTo5Files(currIndex) if filename: - print('file name in openNext is ',filename) + print('file name in openNext is ', filename) self.loadFile(filename) def updateFileListIcon(self, filename): @@ -1655,30 +1593,6 @@ class MainWindow(QMainWindow, WindowMixin): imgidx = self.getImglabelidx(self.filePath) self._saveFile(imgidx, mode=mode) - - def saveFileAs(self, _value=False): - assert not self.image.isNull(), "cannot save empty image" - self._saveFile(self.saveFileDialog()) - - def saveFileDialog(self, removeExt=True): - caption = '%s - Choose File' % __appname__ - filters = 'File (*%s)' % LabelFile.suffix - openDialogPath = self.currentPath() - dlg = QFileDialog(self, caption, openDialogPath, filters) - dlg.setDefaultSuffix(LabelFile.suffix[1:]) - dlg.setAcceptMode(QFileDialog.AcceptSave) - filenameWithoutExtension = os.path.splitext(self.filePath)[0] - dlg.selectFile(filenameWithoutExtension) - dlg.setOption(QFileDialog.DontUseNativeDialog, False) - if dlg.exec_(): - fullFilePath = ustr(dlg.selectedFiles()[0]) - if removeExt: - return os.path.splitext(fullFilePath)[0] # Return file path without the extension. - else: - return fullFilePath - return '' - - def saveLockedShapes(self): self.canvas.lockedShapes = [] self.canvas.selectedShapes = [] @@ -1691,7 +1605,6 @@ class MainWindow(QMainWindow, WindowMixin): self.canvas.selectedShapes.remove(s) self.canvas.shapes.remove(s) - def _saveFile(self, annotationFilePath, mode='Manual'): if len(self.canvas.lockedShapes) != 0: self.saveLockedShapes() @@ -1701,9 +1614,9 @@ class MainWindow(QMainWindow, WindowMixin): img = cv2.imread(self.filePath) width, height = self.image.width(), self.image.height() for shape in self.canvas.lockedShapes: - box = [[int(p[0]*width), int(p[1]*height)] for p in shape['ratio']] + box = [[int(p[0] * width), int(p[1] * height)] for p in shape['ratio']] assert len(box) == 4 - result = [(shape['transcription'],1)] + result = [(shape['transcription'], 1)] result.insert(0, box) self.result_dic_locked.append(result) self.result_dic += self.result_dic_locked @@ -1717,7 +1630,7 @@ class MainWindow(QMainWindow, WindowMixin): item.setIcon(newIcon('done')) self.fileStatedict[self.filePath] = 1 - if len(self.fileStatedict)%self.autoSaveNum ==0: + if len(self.fileStatedict) % self.autoSaveNum == 0: self.saveFilestate() self.savePPlabel(mode='Auto') @@ -1750,8 +1663,8 @@ class MainWindow(QMainWindow, WindowMixin): if platform.system() == 'Windows': from win32com.shell import shell, shellcon shell.SHFileOperation((0, shellcon.FO_DELETE, deletePath, None, - shellcon.FOF_SILENT | shellcon.FOF_ALLOWUNDO | shellcon.FOF_NOCONFIRMATION, - None, None)) + shellcon.FOF_SILENT | shellcon.FOF_ALLOWUNDO | shellcon.FOF_NOCONFIRMATION, + None, None)) # linux elif platform.system() == 'Linux': cmd = 'trash ' + deletePath @@ -1867,7 +1780,6 @@ class MainWindow(QMainWindow, WindowMixin): else: self.labelHist.append(line) - def togglePaintLabelsOption(self): for shape in self.canvas.shapes: shape.paintLabel = self.displayLabelOption.isChecked() @@ -1896,7 +1808,7 @@ class MainWindow(QMainWindow, WindowMixin): prelen = lentoken // 2 bfilename = prelen * " " + pfilename + (lentoken - prelen) * " " # item = QListWidgetItem(QIcon(pix.scaled(100, 100, Qt.KeepAspectRatio, Qt.SmoothTransformation)),filename[:10]) - item = QListWidgetItem(QIcon(pix.scaled(100, 100, Qt.IgnoreAspectRatio, Qt.FastTransformation)),pfilename) + item = QListWidgetItem(QIcon(pix.scaled(100, 100, Qt.IgnoreAspectRatio, Qt.FastTransformation)), pfilename) # item.setForeground(QBrush(Qt.white)) item.setToolTip(file) self.iconlist.addItem(item) @@ -1908,7 +1820,7 @@ class MainWindow(QMainWindow, WindowMixin): self.iconlist.setMinimumWidth(owidth + 50) def getImglabelidx(self, filePath): - if platform.system()=='Windows': + if platform.system() == 'Windows': spliter = '\\' else: spliter = '/' @@ -1923,14 +1835,13 @@ class MainWindow(QMainWindow, WindowMixin): self.autoDialog = AutoDialog(parent=self, ocr=self.ocr, mImgList=uncheckedList, lenbar=len(uncheckedList)) self.autoDialog.popUp() self.currIndex = len(self.mImgList) - 1 - self.loadFile(self.filePath) # ADD + self.loadFile(self.filePath) # ADD self.haveAutoReced = True self.AutoRecognition.setEnabled(False) self.actions.AutoRec.setEnabled(False) self.setDirty() self.saveCacheLabel() - def reRecognition(self): img = cv2.imread(self.filePath) # org_box = [dic['points'] for dic in self.PPlabel[self.getImglabelidx(self.filePath)]] @@ -1959,18 +1870,18 @@ class MainWindow(QMainWindow, WindowMixin): print('Can not recognise the box') if shape.line_color == DEFAULT_LOCK_COLOR: shape.label = result[0][0] - self.result_dic_locked.append([box,(self.noLabelText,0)]) + self.result_dic_locked.append([box, (self.noLabelText, 0)]) else: - self.result_dic.append([box,(self.noLabelText,0)]) + self.result_dic.append([box, (self.noLabelText, 0)]) try: if self.noLabelText == shape.label or result[1][0] == shape.label: print('label no change') else: rec_flag += 1 except IndexError as e: - print('Can not recognise the box') - if (len(self.result_dic) > 0 and rec_flag > 0)or self.canvas.lockedShapes: - self.canvas.isInTheSameImage = True + print('Can not recognise the box') + if (len(self.result_dic) > 0 and rec_flag > 0) or self.canvas.lockedShapes: + self.canvas.isInTheSameImage = True self.saveFile(mode='Auto') self.loadFile(self.filePath) self.canvas.isInTheSameImage = False @@ -2041,7 +1952,6 @@ class MainWindow(QMainWindow, WindowMixin): self.AutoRecognition.setEnabled(True) self.actions.AutoRec.setEnabled(True) - def modelChoose(self): print(self.comboBox.currentText()) lg_idx = {'Chinese & English': 'ch', 'English': 'en', 'French': 'french', 'German': 'german', @@ -2068,14 +1978,12 @@ class MainWindow(QMainWindow, WindowMixin): self.actions.saveLabel.setEnabled(True) self.actions.saveRec.setEnabled(True) - def saveFilestate(self): with open(self.fileStatepath, 'w', encoding='utf-8') as f: for key in self.fileStatedict: f.write(key + '\t') f.write(str(self.fileStatedict[key]) + '\n') - def loadLabelFile(self, labelpath): labeldict = {} if not os.path.exists(labelpath): @@ -2094,8 +2002,7 @@ class MainWindow(QMainWindow, WindowMixin): labeldict[file] = [] return labeldict - - def savePPlabel(self,mode='Manual'): + def savePPlabel(self, mode='Manual'): savedfile = [self.getImglabelidx(i) for i in self.fileStatedict.keys()] with open(self.PPlabelpath, 'w', encoding='utf-8') as f: for key in self.PPlabel: @@ -2139,17 +2046,19 @@ class MainWindow(QMainWindow, WindowMixin): for i, label in enumerate(self.PPlabel[idx]): if label['difficult']: continue img_crop = get_rotate_crop_image(img, np.array(label['points'], np.float32)) - img_name = os.path.splitext(os.path.basename(idx))[0] + '_crop_'+str(i)+'.jpg' - cv2.imwrite(crop_img_dir+img_name, img_crop) - f.write('crop_img/'+ img_name + '\t') + img_name = os.path.splitext(os.path.basename(idx))[0] + '_crop_' + str(i) + '.jpg' + cv2.imwrite(crop_img_dir + img_name, img_crop) + f.write('crop_img/' + img_name + '\t') f.write(label['transcription'] + '\n') except Exception as e: ques_img.append(key) - print("Can not read image ",e) + print("Can not read image ", e) if ques_img: - QMessageBox.information(self, "Information", "The following images can not be saved, " - "please check the image path and labels.\n" + "".join(str(i)+'\n' for i in ques_img)) - QMessageBox.information(self, "Information", "Cropped images have been saved in "+str(crop_img_dir)) + QMessageBox.information(self, + "Information", + "The following images can not be saved, please check the image path and labels.\n" + + "".join(str(i) + '\n' for i in ques_img)) + QMessageBox.information(self, "Information", "Cropped images have been saved in " + str(crop_img_dir)) def speedChoose(self): if self.labelDialogOption.isChecked(): @@ -2162,14 +2071,14 @@ class MainWindow(QMainWindow, WindowMixin): def autoSaveFunc(self): if self.autoSaveOption.isChecked(): - self.autoSaveNum = 1 # Real auto_Save + self.autoSaveNum = 1 # Real auto_Save try: self.saveLabelFile() except: pass print('The program will automatically save once after confirming an image') else: - self.autoSaveNum = 5 # Used for backup + self.autoSaveNum = 5 # Used for backup print('The program will automatically save once after confirming 5 images (default)') def undoShapeEdit(self): @@ -2186,25 +2095,26 @@ class MainWindow(QMainWindow, WindowMixin): self.labelList.clearSelection() self._noSelectionSlot = False self.canvas.loadShapes(shapes, replace=replace) - print("loadShapes")#1 - - + print("loadShapes") # 1 + def lockSelectedShape(self): - """lock the selsected shapes. + """lock the selected shapes. Add self.selectedShapes to lock self.canvas.lockedShapes, which holds the ratio of the four coordinates of the locked shapes to the width and height of the image """ width, height = self.image.width(), self.image.height() + def format_shape(s): return dict(label=s.label, # str line_color=s.line_color.getRgb(), fill_color=s.fill_color.getRgb(), - ratio=[[int(p.x())/width, int(p.y())/height] for p in s.points], # QPonitF - # add chris + ratio=[[int(p.x()) / width, int(p.y()) / height] for p in s.points], # QPonitF + # add chris difficult=s.difficult) # bool - #lock + + # lock if len(self.canvas.lockedShapes) == 0: for s in self.canvas.selectedShapes: s.line_color = DEFAULT_LOCK_COLOR @@ -2216,7 +2126,7 @@ class MainWindow(QMainWindow, WindowMixin): self.canvas.lockedShapes = trans_dic self.actions.save.setEnabled(True) - #unlock + # unlock else: for s in self.canvas.shapes: s.line_color = DEFAULT_LINE_COLOR @@ -2237,9 +2147,11 @@ def read(filename, default=None): except: return default + def str2bool(v): return v.lower() in ("true", "t", "1") + def get_main_app(argv=[]): """ Standard boilerplate Qt application code. @@ -2249,22 +2161,23 @@ def get_main_app(argv=[]): app.setApplicationName(__appname__) app.setWindowIcon(newIcon("app")) # Tzutalin 201705+: Accept extra agruments to change predefined class file - argparser = argparse.ArgumentParser() - argparser.add_argument("--lang", type=str, default='en', nargs="?") - argparser.add_argument("--gpu", type=str2bool, default=False, nargs="?") - argparser.add_argument("--predefined_classes_file", - default=os.path.join(os.path.dirname(__file__), "data", "predefined_classes.txt"), - nargs="?") - args = argparser.parse_args(argv[1:]) - # Usage : labelImg.py image predefClassFile saveDir - win = MainWindow(lang=args.lang, gpu=args.gpu, - defaultPrefdefClassFile=args.predefined_classes_file) + arg_parser = argparse.ArgumentParser() + arg_parser.add_argument("--lang", type=str, default='en', nargs="?") + arg_parser.add_argument("--gpu", type=str2bool, default=False, nargs="?") + arg_parser.add_argument("--predefined_classes_file", + default=os.path.join(os.path.dirname(__file__), "data", "predefined_classes.txt"), + nargs="?") + args = arg_parser.parse_args(argv[1:]) + + win = MainWindow(lang=args.lang, + gpu=args.gpu, + default_predicted_class_file=args.predefined_classes_file) win.show() return app, win def main(): - '''construct main app and run it''' + """construct main app and run it""" app, _win = get_main_app(sys.argv) return app.exec_() @@ -2276,5 +2189,5 @@ if __name__ == '__main__': output = os.system('pyrcc5 -o libs/resources.py resources.qrc') assert output == 0, "operate the cmd have some problems ,please check whether there is a in the lib " \ "directory resources.py " - import libs.resources + sys.exit(main()) diff --git a/PPOCRLabel/combobox.py b/PPOCRLabel/combobox.py deleted file mode 100644 index 8526b45392902e564364be27948517377217bbeb..0000000000000000000000000000000000000000 --- a/PPOCRLabel/combobox.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) <2015-Present> Tzutalin -# Copyright (C) 2013 MIT, Computer Science and Artificial Intelligence Laboratory. Bryan Russell, Antonio Torralba, -# William T. Freeman. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -# associated documentation files (the "Software"), to deal in the Software without restriction, including without -# limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -# Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -# The above copyright notice and this permission notice shall be included in all copies or substantial portions of -# the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -import sys -try: - from PyQt5.QtWidgets import QWidget, QHBoxLayout, QComboBox -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 QWidget, QHBoxLayout, QComboBox - - -class ComboBox(QWidget): - def __init__(self, parent=None, items=[]): - super(ComboBox, self).__init__(parent) - - layout = QHBoxLayout() - self.cb = QComboBox() - self.items = items - self.cb.addItems(self.items) - - self.cb.currentIndexChanged.connect(parent.comboSelectionChanged) - - layout.addWidget(self.cb) - self.setLayout(layout) - - def update_items(self, items): - self.items = items - - self.cb.clear() - self.cb.addItems(self.items)