def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None): super(MainWindow, self).__init__() self.setWindowTitle(__appname__) # Load setting in the main thread self.settings = Settings() self.settings.load() settings = self.settings self.defaultSaveDir = None # Whether we need to save or not. self.dirty = False # For loading all image under a directory self.mImgList = [] self.dirname = None # Main widgets and related state. # self.labelDialog = LabelDialog(parent=self, listItem=self.labelHist) # File and Notes self.noteArea = QPlainTextEdit() self.fileListWidget = QListWidget() self.fileListWidget.itemDoubleClicked.connect( self.fileitemDoubleClicked) self.fileNoteLayout = QVBoxLayout() self.fileNoteLayout.addWidget(self.fileListWidget) self.fileNoteLayout.addWidget(self.noteArea) self.fileNoteArea = QWidget() self.fileNoteArea.setLayout(self.fileNoteLayout) # File and Notes to Dock self.fileNoteDock = QDockWidget(u'Files and Notes', self) self.fileNoteDock.setObjectName(u'file_note') self.fileNoteDock.setWidget(self.fileNoteArea) self.addDockWidget(Qt.LeftDockWidgetArea, self.fileNoteDock) #First Search self.firstText = QLineEdit() self.firsrSearchResultArea = QListWidget() self.firsrSearchResultArea.itemDoubleClicked.connect( self.fileitemDoubleClicked) self.firstSearchLayout = QVBoxLayout() self.firstSearchLayout.addWidget(self.firstText) self.firstSearchLayout.addWidget(self.firsrSearchResultArea) self.firstSearchArea = QWidget() self.firstSearchArea.setLayout(self.firstSearchLayout) #Locode Search self.locodeText = QLineEdit() self.locodeDataLayout = QFormLayout() self.storeKw = QLineEdit() self.locodeDataLayout.addRow('Store KeyWord', self.storeKw) self.mallKw = QLineEdit() self.locodeDataLayout.addRow('Mall KeyWord', self.mallKw) self.gstNo = QLineEdit() self.locodeDataLayout.addRow('GST NO', self.gstNo) self.locodeSearchLayout = QVBoxLayout() self.locodeDataArea = QWidget() self.locodeDataArea.setLayout(self.locodeDataLayout) self.locodeSearchLayout.addWidget(self.locodeText) self.locodeSearchLayout.addWidget(self.locodeDataArea) self.locodeSearchArea = QWidget() self.locodeSearchArea.setLayout(self.locodeSearchLayout) # FirstchSearch and LocodeSearch to Doct self.inputAreaLayout = QHBoxLayout() self.inputAreaLayout.addWidget(self.firstSearchArea) self.inputAreaLayout.addWidget(self.locodeSearchArea) self.inputArea = QWidget() self.inputArea.setLayout(self.inputAreaLayout) self.inputDock = QDockWidget(u'Input Area', self) self.inputDock.setObjectName(u'input_area') self.inputDock.setWidget(self.inputArea) self.addDockWidget(Qt.RightDockWidgetArea, self.inputDock) #Canvas self.zoomWidget = ZoomWidget() self.canvas = Canvas(parent=self) self.canvas.zoomRequest.connect(self.zoomRequest) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.scrollArea = scroll self.canvas.scrollRequest.connect(self.scrollRequest) self.setCentralWidget(scroll) # Actions action = partial(newAction, self) quit = action('&Quit', self.close, 'Ctrl+Q', 'quit', u'Quit application') opendir = action('&Open Dir', self.openDirDialog, 'Ctrl+o', 'open', u'Open Dir') changeSavedir = action('&Change Save Dir', self.changeSavedirDialog, 'Ctrl+r', 'open', u'Change default saved Annotation dir') openNextImg = action('&Next Image', self.openNextImg, 'd', 'next', u'Open Next') openPrevImg = action('&Prev Image', self.openPrevImg, 'a', 'prev', u'Open Prev') saveAs = action('&Save As', self.saveFileAs, 'Ctrl+s', 'save-as', u'Save labels to a different file', enabled=False) zoom = QWidgetAction(self) zoom.setDefaultWidget(self.zoomWidget) self.zoomWidget.setWhatsThis( u"Zoom in or out of the image. Also accessible with" " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), fmtShortcut("Ctrl+Wheel"))) self.zoomWidget.setEnabled(False) fitWidth = action('Fit &Width', self.setFitWidth, 'Ctrl+Shift+F', 'fit-width', u'Zoom follows window width', checkable=True, enabled=False) # Group zoom controls into a list for easier toggling. zoomActions = (self.zoomWidget, fitWidth) self.zoomMode = self.MANUAL_ZOOM self.scalers = { self.FIT_WIDTH: self.scaleFitWidth, # Set to one to scale to 100% when loading files. self.MANUAL_ZOOM: lambda: 1, } # Store actions for further handling. self.actions = struct(saveAs=saveAs, zoom=zoom, fitWidth=fitWidth, zoomActions=zoomActions, fileMenuActions=(open, saveAs, quit)) self.menus = struct(file=self.menu('&File'), edit=self.menu('&Edit'), view=self.menu('&View')) addActions(self.menus.file, (opendir, changeSavedir, saveAs, quit)) addActions(self.menus.view, (fitWidth, openPrevImg, openNextImg)) self.statusBar().showMessage('%s started.' % __appname__) self.statusBar().show() # Application state. self.image = QImage() self.filePath = ustr(defaultFilename) self.recentFiles = [] self.maxRecent = 7 self.lineColor = None self.fillColor = None self.zoom_level = 100 self.fit_window = False # Add Chris self.difficult = False size = settings.get(SETTING_WIN_SIZE, QSize(600, 500)) position = settings.get(SETTING_WIN_POSE, QPoint(0, 0)) self.resize(size) self.move(position) saveDir = ustr(settings.get(SETTING_SAVE_DIR, None)) self.lastOpenDir = ustr(settings.get(SETTING_LAST_OPEN_DIR, None)) if saveDir is not None and os.path.exists(saveDir): self.defaultSaveDir = saveDir self.statusBar().showMessage( '%s started. Annotation will be saved to %s' % (__appname__, self.defaultSaveDir)) self.statusBar().show() self.restoreState(settings.get(SETTING_WIN_STATE, QByteArray())) print self.filePath # Since loading the file may take some time, make sure it runs in the background. if self.filePath and os.path.isdir(self.filePath): self.queueEvent(partial(self.importDirImages, self.filePath or "")) elif self.filePath: self.queueEvent(partial(self.loadFile, self.filePath or "")) # Callbacks: self.zoomWidget.valueChanged.connect(self.paintCanvas) # Display cursor coordinates at the right of status bar self.labelCoordinates = QLabel('') self.statusBar().addPermanentWidget(self.labelCoordinates) # Open Dir if deafult file if self.filePath and os.path.isdir(self.filePath): self.openDirDialog(dirpath=self.filePath)
def __init__(self): QWidget.__init__(self) # self.setFixedSize(800, 600) # self.descisionDlg = ouput(self) self.setWindowTitle("Label Master") self.labelCoordinates = QLabel('') self.statusBar().addPermanentWidget(self.labelCoordinates) # intit self.cvMat = None self.qImage = None self.dirty = False self.saveFolder = None self.filePath = None self.lastOpenDir = None self.mImgList = [] self.prevLabel = "Enter object label" self.bLoopImplement = True self.bAutoImplement = False self.bSaveOutput = False self.bShowResult = True self.bSelectionChanged = False self.pool = Pool(5) self.output = [] self.bEndThreads = [] self.t0 = 0 # self.stringBundle = StringBundle.getBundle() # getStr = lambda strId: self.stringBundle.getString(strId) self.labelDialog = LabelDialog(listItem=listLabel) self.colorDialog = ColorDialog(parent=self) self.lineColor = None self.textColor = None self.itemsToShapes = {} self.shapesToItems = {} self._noSelectionSlot = [] self._beginner = True self.statusBar().showMessage('%s' % __appname__) # self.statusBar().show() #============ menu========= self.menus = struct(file=self.menu('&File'), edit=self.menu('&Edit'), view=self.menu('&View'), help=self.menu('&Help'), labelList=QMenu(), fileLog=QMenu()) #================init UI ============== action = partial(newAction, self) #=======toolBar========== openFile = action("Open", self.open, OPEN_FILE, "res/open.png", "Open image file") openDir = action("Open Dir", self.openDirDialog, OPEN_DIR, "res/openDir.png", "Open image folder") createShape = action("Create rect box", self.createShape, CREATE, "res/draw.png", "Start draw rectangle") createPolygon = action("Create polygon", self.createPolygon, POLYGON, "res/polygon.png", "Start draw polygon") copy = action('copy', self.copySelectedShape, COPY, 'res/copy.png', 'dupBoxDetail', enabled=False) saveFile = action("Save", self.save, SAVE, "res/save.png", "Save parameters") editLabel = action("Edit label", self.editLabel, EDIT, "res/edit.png", "Editting label", enabled=False) deleteShape = action("Delete shape", self.deleteSelectedShape, DLETE, "res/delete.png", "Delete shape selected", enabled=False) implement = action("Implement", self.implement, IMPLEMENT, "res/event.png", "Implement", enabled=False) lineColor = action("Line color", lambda: self.boxColor("line"), LINE_COLOR, "res/lineColor.png", "Box line color", enabled=True) textColor = action("Text color", lambda: self.boxColor("text"), TEXT_COLOR, "res/textColor.png", "Box text color", enabled=True) font = action("Font", self.boxFont, TEXT_FONT, "res/font.png", "Box font text", enabled=True) nextImage = action("Next Image", self.openNextImg, NEXT, "res/next.png", "Next image", enabled=True) backImage = action("Back Image", self.openPrevImg, BACK, "res/back.png", "Back image", enabled=True) zoomIn = action('zoomin', partial(self.addZoom, 10), ZOOM_IN, 'res/zoom-in.png', 'zoominDetail', enabled=False) zoomOut = action('zoomout', partial(self.addZoom, -10), ZOOM_OUT, 'res/zoom-out.png', 'zoomoutDetail', enabled=False) zoomOrg = action('originalsize', partial(self.setZoom, 100), ZOOM_ORG, 'res/zoom.png', 'originalsizeDetail', enabled=False) fitWindow = action('fitWin', self.setFitWindow, FIT_WINDOW, 'res/fit-window.png', 'fitWinDetail', checkable=True, enabled=False) fitWidth = action('fitWidth', self.setFitWidth, FIT_WIDTH, 'res/fit-width.png', 'fitWidthDetail', checkable=True, enabled=False) clearAll = action('clearAll', self.clearList, CLEAR_ALL, 'res/clear-all.png', 'Clear all list items', checkable=True, enabled=True) showCamera = action('camera', self.showCamera, SHOW_CAMERA, 'res/camera2.png', 'Camera', checkable=True, enabled=True) actionMenuFile = [openFile, openDir, saveFile] addActions(self.menus.file, actionMenuFile) actionMenuEdit = [ createShape, implement, editLabel, copy, lineColor, textColor, font, deleteShape ] addActions(self.menus.edit, actionMenuEdit) actionToolbar = (openFile, openDir, saveFile, createShape, createPolygon, editLabel, implement, nextImage, backImage) self.toolbar("Tools", actions=actionToolbar) self.zoomWidget = ZoomWidget() zoom = QWidgetAction(self) zoom.setDefaultWidget(self.zoomWidget) self.zoomWidget.setWhatsThis( u"Zoom in or out of the image. Also accessible with" " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), fmtShortcut("Ctrl+Wheel"))) self.zoomWidget.setEnabled(False) # Group zoom controls into a list for easier toggling. beginner = (implement, editLabel, copy, deleteShape) self.actions = struct(openFile=openFile, openDir=openDir, saveFile=saveFile, createShape=createShape, createPolygon=createPolygon, editLabel=editLabel, deleteShape=deleteShape, copy=copy, implement=implement, lineColor=lineColor, textColor=textColor, font=font, nextImage=nextImage, backImage=backImage, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, fitWidth=fitWidth, fitWindow=fitWindow, beginner=beginner, clearAll=clearAll) self.zoomWidget.valueChanged.connect(self.paintCanvas) self.zoomMode = self.MANUAL_ZOOM self.scalers = { self.FIT_WINDOW: self.scaleFitWindow, self.FIT_WIDTH: self.scaleFitWidth, # Set to one to scale to 100% when loading files. self.MANUAL_ZOOM: lambda: 1, } listLayout = QVBoxLayout() listLayout.setContentsMargins(0, 0, 0, 0) # Create a widget for using default label self.useDefaultLabelCheckbox = QCheckBox('useDefaultLabel') self.useDefaultLabelCheckbox.setChecked(False) self.defaultLabelTextLine = QLineEdit() self.autoImplement = QCheckBox('autoImplement') self.autoImplement.setChecked(False) self.saveOutput = QCheckBox('saveOutput') self.saveOutput.setChecked(False) self.updateOuput = QCheckBox('showOutput') self.updateOuput.setChecked(True) self.autoImplement.stateChanged.connect(self.stateChanged) self.saveOutput.stateChanged.connect(self.stateChanged) self.updateOuput.stateChanged.connect(self.stateChanged) useDefaultLabelQHBoxLayout = QVBoxLayout() useDefaultLabelQHBoxLayout.addWidget(self.useDefaultLabelCheckbox) useDefaultLabelQHBoxLayout.addWidget(self.defaultLabelTextLine) useDefaultLabelQHBoxLayout.addWidget(self.saveOutput) useDefaultLabelQHBoxLayout.addWidget(self.updateOuput) useDefaultLabelQHBoxLayout.addWidget(self.autoImplement) useDefaultLabelContainer = QWidget() useDefaultLabelContainer.setLayout(useDefaultLabelQHBoxLayout) # Create a widget for edit and diffc buttonp self.editButton = QToolButton() self.editButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.editButton.setDefaultAction(editLabel) self.implementButton = QToolButton() self.implementButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.implementButton.setDefaultAction(implement) buttonLayout = QHBoxLayout() buttonLayout.setContentsMargins(0, 0, 0, 0) # Add some of widgets to listLayout buttonLayout.addWidget(self.editButton) buttonLayout.addWidget(self.implementButton) listLayout.addLayout(buttonLayout) listLayout.addWidget(useDefaultLabelContainer) # Create and add a dock widget for showing current label items self.labelList = QListWidget() addActions(self.menus.labelList, (editLabel, deleteShape)) self.labelList.setContextMenuPolicy(Qt.CustomContextMenu) self.labelList.customContextMenuRequested.connect( self.popLabelListMenu) self.labelList.itemActivated.connect(self.labelSelectionChanged) self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged) self.labelList.itemDoubleClicked.connect(self.editLabel) # Connect to itemChanged to detect checkbox changes. self.labelList.itemChanged.connect(self.labelItemChanged) listLayout.addWidget(self.labelList) labelListContainer = QWidget() labelListContainer.setLayout(listLayout) self.fileLogWidget = QListWidget() addActions(self.menus.fileLog, [clearAll]) self.fileLogWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.fileLogWidget.customContextMenuRequested.connect( self.popfileLogMenu) self.fileLogWidget.itemDoubleClicked.connect( self.fileitemDoubleClicked) # self.fileLogWidget.itemChanged.connect(self.fileLogRowChanged) fileLogLayout = QVBoxLayout() fileLogLayout.setContentsMargins(0, 0, 0, 0) fileLogLayout.addWidget(self.fileLogWidget) fileLogContainer = QWidget() fileLogContainer.setLayout(fileLogLayout) self.dock = QDockWidget('boxLabelText', self) self.dock.setObjectName('labels') self.dock.setWidget(labelListContainer) self.filedock = QDockWidget('fileLog', self) self.filedock.setObjectName('files') self.filedock.setWidget(fileLogContainer) self.parameterdock = QDockWidget('paramsVision', self) self.parameterdock.setObjectName('params') self.paramerterWidget = ParamerterDialog(self) # self.paramerterWidget.ln_kThresh.textChanged.connect(self.textChanged) self.parameterdock.setWidget(self.paramerterWidget) # self.cameradock = QDockWidget('camera', self) # self.cameradock.setObjectName('cameara') # self.cameraDlg = cameraDialog(self) # self.cameradock.setWidget(self.cameraDlg) self.addDockWidget(Qt.RightDockWidgetArea, self.dock) self.dockFeatures = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable # self.dock.setFeatures(self.dock.features() ^ self.dockFeatures) self.dock.setFeatures(self.dockFeatures) self.addDockWidget(Qt.RightDockWidgetArea, self.filedock) self.filedock.setFeatures(self.dockFeatures) self.addDockWidget(Qt.RightDockWidgetArea, self.parameterdock) self.parameterdock.setFeatures(self.dockFeatures) # self.addDockWidget(Qt.RightDockWidgetArea, self.cameradock) # self.cameradock.setFeatures(self.dockFeatures) toggleDock = self.dock.toggleViewAction() toggleDock.setText('boxLabel') toggleDock.setShortcut(TOGGLE_LABEL_LIST) toggleFileDock = self.filedock.toggleViewAction() toggleFileDock.setText('logFile') toggleFileDock.setShortcut(TOGGLE_LOG_FILE) toggleParaDock = self.parameterdock.toggleViewAction() toggleParaDock.setText('parameter') toggleParaDock.setShortcut(TOGGLE_PARAMETER) # toggleCamDock = self.cameradock.toggleViewAction() # toggleCamDock.setText('camera') # toggleCamDock.setShortcut(TOGGLE_SHOW_CAMERA) # self.dock.hide() self.filedock.hide() self.parameterdock.hide() # self.cameradock.hide() addActions(self.menus.view, [toggleDock, toggleFileDock, toggleParaDock, showCamera]) # ==============Canvas================ self.canvas = Canvas(self) # load params self.loadParams() # contextMenu addActions(self.canvas.menus[0], self.actions.beginner) #================= qImage = QImage(640, 480, QImage.Format_RGBA8888) self.canvas.loadPixmap(QPixmap.fromImage(qImage)) scroll = QScrollArea() scroll.setWidget(self.canvas) # scroll.setWidget(self.listWidget) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.scrollArea = scroll #signal Canvas self.canvas.scrollRequest.connect(self.scrollRequest) self.canvas.newShape.connect(self.newShape) self.canvas.shapeMoved.connect(self.setDirty) self.canvas.selectionChanged.connect(self.shapeSelectionChanged) self.canvas.zoomRequest.connect(self.zoomRequest) self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive) self.setCentralWidget(scroll) self.fitState() # # ============================== palette = self.palette() role = self.backgroundRole() palette.setColor(role, QColor(200, 232, 232, 255)) self.setPalette(palette) palette = self.canvas.palette() role = self.canvas.backgroundRole() palette.setColor(role, QColor(200, 232, 232, 255)) self.canvas.setPalette(palette) #==start thead implement self.myThread(target=self.loopImplement, args=())
def __init__(self): super(MainWindow, self).__init__() self.setWindowTitle(__appname__) self.settings = Settings() self.settings.load() settings = self.settings # init annotation dir self.annotDir = None # init image dir, wait to be set by user in self.loadImagefolder self.imageDir = None self.zoomWidget = ZoomWidget() scroll = QScrollArea() self.canvas = Canvas() self.setCentralWidget(self.canvas) # add scroll widget scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.setCentralWidget(scroll) self.canvas.resize(self.canvas.sizeHint()) # add and populate menubar bar = self.menuBar() file = bar.addMenu("File") loadDir = QAction("Open Image Folder", self) loadAnnotDir = QAction("Open Annotation Folder", self) save = QAction("Save Annotation", self) save.setShortcut('Ctrl+S') quit = QAction("Close Annotator", self) file.addAction(loadDir) file.addAction(loadAnnotDir) file.addAction(save) file.addAction(quit) # set actions loadDir.triggered.connect(self.loadImageFolder) loadAnnotDir.triggered.connect(self.loadAnnotFolder) save.triggered.connect(self.save) # load.triggered.connect(self.canvas.load) quit.triggered.connect(self.quitApp) self.loadedFiles = [] # add navigation sidebar self.items = QDockWidget("Annotations", self) self.annotList = QListWidget() self.annotList.itemActivated.connect(self.updateActivatedAnnotation) self.items.setWidget(self.annotList) self.items.setFloating(False) self.addDockWidget(Qt.RightDockWidgetArea, self.items) size = settings.get(SETTING_WIN_SIZE, QSize(640, 480)) position = settings.get(SETTING_WIN_POSE, QPoint(0, 0)) self.resize(size) self.move(position) self.queueEvent(self.loadImage)
def __init__(self, defaultFilename=None, defaaultPrefdefClassFile=None, defaultSaveDir=None): super(MainWindow, self).__init__() self.setWindowTitle(__appname__) #Load setting in the main thread self.settings = Settings() self.settings.load() settings = self.settings #load string bundle for i18n self.stringBundle = StringBundle.getBundle() getStr = lambda strId: self.stringBundle.getString(strId) #save as pascal voc xml self.defaultSaveDir = defaultSaveDir self.labelFileFormat = settings.get(SETTING_LABEL_FILE_FORMAT, LabelFileFormat.PASCAL_VOC) #for loading all image under a directory self.mImgList = [] self.dirname = None self.labelHist = [] self.lastOpenDir = None #NEED TO DO #whether we need to save or not self.dirty = False self._noSelectionSlot = False self._beginner = True self.screencastViewer = self.getAvailableScreencastViewer() self.screencast = "https://youtu.be/p0nR2YsCY_U" #Load predefined classes to the list self.loadPredefinedClasses(defaaultPrefdefClassFile) #main widgets and related state self.labelDialog = LabelDialog(parent=self, listItem=self.labelHist) self.itemsToShapes = {} self.shapesToItems = {} self.prevLabelText = '' listLayout = QVBoxLayout() listLayout.setContentsMargins(0,0,0,0) self.useDefaultLableCheckbox = QCheckBox(getStr('useDefaultLabel')) self.useDefaultLableCheckbox.setChecked(False) self.defaultLabelTextLine = QLineEdit() useDefaultLabelQHBoxLayout = QHBoxLayout() useDefaultLabelQHBoxLayout.addWidget(self.useDefaultLableCheckbox) useDefaultLabelQHBoxLayout.addWidget(self.defaultLabelTextLine) useDefaultLabelContainer = QWidget() useDefaultLabelContainer.setLayout((useDefaultLabelQHBoxLayout)) self.diffcButton = QCheckBox(getStr('useDifficult')) self.diffcButton.setChecked(False) self.diffcButton.stateChanged.connect(self.btnstate) self.editButton = QToolButton() self.editButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) listLayout.addWidget(self.editButton) listLayout.addWidget(self.diffcButton) listLayout.addWidget(useDefaultLabelContainer) self.comboBox = ComboBox(self) listLayout.addWidget(self.comboBox) # Create and add a widget for showing current label items self.labelList = QListWidget() labelListContainer = QWidget() labelListContainer.setLayout(listLayout) self.labelList.itemActivated.connect(self.labelSelectionChanged) self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged) self.labelList.itemDoubleClicked.connect(self.editLabel) # Connect to itemChanged to detect checkbox changes. self.labelList.itemChanged.connect(self.labelItemChanged) listLayout.addWidget(self.labelList) self.dock = QDockWidget(getStr('boxLabelText'), self) self.dock.setObjectName(getStr('labels')) self.dock.setWidget(labelListContainer) self.fileListWidget = QListWidget() self.fileListWidget.itemDoubleClicked.connect(self.fileitemDoubleClicked) filelistLayout = QVBoxLayout() filelistLayout.setContentsMargins(0, 0, 0, 0) filelistLayout.addWidget(self.fileListWidget) fileListContainer = QWidget() fileListContainer.setLayout(filelistLayout) self.filedock = QDockWidget(getStr('fileList'), self) self.filedock.setObjectName(getStr('files')) self.filedock.setWidget(fileListContainer) self.zoomWidget = ZoomWidget() self.colorDialog = ColorDialog(parent=self) self.canvas = Canvas(parent=self) self.canvas.zoomRequest.connect(self.zoomRequest) self.canvas.setDrawingShapeToSquare(settings.get(SETTING_DRAW_SQUARE, False)) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.scrollArea = scroll self.canvas.scrollRequest.connect(self.scrollRequest) self.canvas.newShape.connect(self.newShape) self.canvas.shapeMoved.connect(self.setDirty) self.canvas.selectionChanged.connect(self.shapeSelectionChanged) self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive) self.setCentralWidget(scroll) self.addDockWidget(Qt.RightDockWidgetArea, self.dock) self.addDockWidget(Qt.RightDockWidgetArea, self.filedock) self.filedock.setFeatures(QDockWidget.DockWidgetFloatable) self.dockFeatures = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable self.dock.setFeatures(self.dock.features() ^ self.dockFeatures)
def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None): super(MainWindow, self).__init__() self.setWindowTitle(__appname__) self.defaultSaveDir = None self.usingPascalVocFormat = True self.mImgList = [] self.dirname = None self.labelHist = [] self.lastOpenDir = None self.dirty = False self._noSelectionSlot = False self._beginner = True self.screencastViewer = "firefox" self.screencast = "https://www.youtube.com/?gl=UA&hl=ru" self.loadPredefinedClasses(defaultPrefdefClassFile) self.labelDialog = LabelDialog(parent=self, listItem=self.labelHist) self.itemsToShapes = {} self.shapesToItems = {} self.prevLabelText = '' listLayout = QVBoxLayout() listLayout.setContentsMargins(0, 0, 0, 0) self.useDefaultLabelCheckbox = QCheckBox(u'Default label') self.useDefaultLabelCheckbox.setChecked(True) self.defaultLabelTextLine = QLineEdit('Object') useDefaultLabelQHBoxLayout = QHBoxLayout() useDefaultLabelQHBoxLayout.addWidget(self.useDefaultLabelCheckbox) useDefaultLabelQHBoxLayout.addWidget(self.defaultLabelTextLine) useDefaultLabelContainer = QWidget() useDefaultLabelContainer.setLayout(useDefaultLabelQHBoxLayout) self.editButton = QToolButton() self.editButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) listLayout.addWidget(self.editButton) listLayout.addWidget(useDefaultLabelContainer) self.labelList = QListWidget() labelListContainer = QWidget() labelListContainer.setLayout(listLayout) self.labelList.itemActivated.connect(self.labelSelectionChanged) self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged) self.labelList.itemDoubleClicked.connect(self.editLabel) self.labelList.itemChanged.connect(self.labelItemChanged) listLayout.addWidget(self.labelList) self.dock = QDockWidget(u'Label List', self) self.dock.setObjectName(u'Labels') self.dock.setWidget(labelListContainer) self.fileListWidget = QListWidget() self.fileListWidget.itemDoubleClicked.connect( self.fileitemDoubleClicked) filelistLayout = QVBoxLayout() filelistLayout.setContentsMargins(0, 0, 0, 0) filelistLayout.addWidget(self.fileListWidget) fileListContainer = QWidget() fileListContainer.setLayout(filelistLayout) self.filedock = QDockWidget(u'File List', self) self.filedock.setObjectName(u'Files') self.filedock.setWidget(fileListContainer) self.zoomWidget = ZoomWidget() self.colorDialog = ColorDialog(parent=self) self.canvas = Canvas() self.canvas.zoomRequest.connect(self.zoomRequest) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.scrollArea = scroll self.canvas.scrollRequest.connect(self.scrollRequest) self.canvas.newShape.connect(self.newShape) self.canvas.shapeMoved.connect(self.setDirty) self.canvas.selectionChanged.connect(self.shapeSelectionChanged) self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive) self.setCentralWidget(scroll) self.addDockWidget(Qt.RightDockWidgetArea, self.dock) self.addDockWidget(Qt.RightDockWidgetArea, self.filedock) self.dockFeatures = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable self.dock.setFeatures(self.dock.features() ^ self.dockFeatures) action = partial(newAction, self) open = action('&Open Image', self.openFile, 'I', 'open', u'Open image file') opendir = action('&Open Folder', self.openDir, 'F', 'open', u'Open directory') openNextImg = action('&Next Image', self.openNextImg, 'D', 'next', u'Open next image') openPrevImg = action('&Previous Image', self.openPrevImg, 'A', 'prev', u'Open previous image') save = action('&Save Label', self.saveFile, 'S', 'save', u'Save labels to file', enabled=False) createMode = action('Create Label', self.setCreateMode, 'W', 'new', u'Create new label', enabled=False) editMode = action('&Edit Label', self.setEditMode, 'E', 'edit', u'Move and edit label', enabled=False) delete = action('Delete label', self.deleteSelectedShape, 'Delete', 'delete', u'Delete label', enabled=False) advancedMode = action('&Advanced Mode', self.toggleAdvancedMode, 'Ctrl+Shift+A', 'expert', u'Switch to advanced mode', checkable=True) help = action('&Tutorial', self.tutorial, 'T', 'help', u'Show demo video') zoom = QWidgetAction(self) zoom.setDefaultWidget(self.zoomWidget) self.zoomWidget.setWhatsThis( u"Zoom in or out of the image. Also accessible with" " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), fmtShortcut("Ctrl+Wheel"))) self.zoomWidget.setEnabled(False) zoomIn = action('Zoom &In', partial(self.addZoom, 10), 'Ctrl++', 'zoom-in', u'Increase zoom level', enabled=False) zoomOut = action('&Zoom Out', partial(self.addZoom, -10), 'Ctrl+-', 'zoom-out', u'Decrease zoom level', enabled=False) zoomOrg = action('&Original size', partial(self.setZoom, 100), 'Ctrl+=', 'zoom', u'Zoom to original size', enabled=False) fitWindow = action('&Fit Window', self.setFitWindow, 'Ctrl+F', 'fit-window', u'Zoom follows window size', checkable=True, enabled=False) fitWidth = action('Fit &Width', self.setFitWidth, 'Ctrl+Shift+F', 'fit-width', u'Zoom follows window width', checkable=True, enabled=False) zoomActions = (self.zoomWidget, zoomIn, zoomOut, zoomOrg, fitWindow, fitWidth) self.zoomMode = self.MANUAL_ZOOM self.scalers = { self.FIT_WINDOW: self.scaleFitWindow, self.FIT_WIDTH: self.scaleFitWidth, self.MANUAL_ZOOM: lambda: 1, } edit = action('&Edit Label', self.editLabel, 'Ctrl+E', 'edit', u'Modify the label of the selected Box', enabled=False) self.editButton.setDefaultAction(edit) shapeLineColor = action( 'Shape &Line Color', self.chshapeLineColor, icon='color_line', tip=u'Change the line color for this specific shape', enabled=False) shapeFillColor = action( 'Shape &Fill Color', self.chshapeFillColor, icon='color', tip=u'Change the fill color for this specific shape', enabled=False) labels = self.dock.toggleViewAction() labels.setText('Label Panel') labels.setShortcut('Ctrl+Shift+L') files = self.filedock.toggleViewAction() files.setText('File Panel') files.setShortcut('Ctrl+Shift+F') labelMenu = QMenu() addActions(labelMenu, (edit, delete)) self.labelList.setContextMenuPolicy(Qt.CustomContextMenu) self.labelList.customContextMenuRequested.connect( self.popLabelListMenu) self.actions = struct(save=save, open=open, create=createMode, delete=delete, edit=edit, createMode=createMode, editMode=editMode, advancedMode=advancedMode, shapeLineColor=shapeLineColor, shapeFillColor=shapeFillColor, zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, fitWindow=fitWindow, fitWidth=fitWidth, zoomActions=zoomActions, fileMenuActions=(open, opendir, save), beginner=(), advanced=(), editMenu=(edit, delete), beginnerContext=(edit, delete), advancedContext=(save, createMode, editMode), onLoadActive=(createMode, editMode)) self.menus = struct(file=self.menu('&File'), edit=self.menu('&Edit'), view=self.menu('&View'), help=self.menu('&Help'), recentFiles=QMenu('Open &Recent'), labelList=labelMenu) self.autoSaving = QAction("Auto Saving", self) self.autoSaving.setCheckable(True) self.singleClassMode = QAction("Single Class Mode", self) self.singleClassMode.setShortcut("Ctrl+Shift+S") self.singleClassMode.setCheckable(True) self.lastLabel = None addActions(self.menus.file, (open, opendir, openNextImg, openPrevImg)) addActions(self.menus.help, (help, )) addActions(self.menus.view, (labels, files, zoomIn, zoomOut)) self.menus.file.aboutToShow.connect(self.updateFileMenu) addActions(self.canvas.menus[0], self.actions.beginnerContext) addActions(self.canvas.menus[1], (action('&Copy here', self.copyShape), action('&Move here', self.moveShape))) self.tools = self.toolbar('Tools') self.actions.advanced = (None, open, opendir, None, openNextImg, openPrevImg, None, save, createMode, editMode, None, zoomIn, zoomOut, None) self.statusBar().showMessage('%s started.' % __appname__) self.statusBar().show() self.image = QImage() self.filePath = ustr(defaultFilename) self.recentFiles = [] self.maxRecent = 7 self.lineColor = None self.fillColor = None self.zoom_level = 100 self.fit_window = False self.difficult = False self.settings = Settings() self.settings.load() settings = self.settings if settings.get(SETTING_RECENT_FILES): if have_qstring(): recentFileQStringList = settings.get(SETTING_RECENT_FILES) self.recentFiles = [ustr(i) for i in recentFileQStringList] else: self.recentFiles = recentFileQStringList = settings.get( SETTING_RECENT_FILES) size = settings.get(SETTING_WIN_SIZE, QSize(300, 500)) position = settings.get(SETTING_WIN_POSE, QPoint(0, 0)) self.resize(size) self.move(position) saveDir = ustr(settings.get(SETTING_SAVE_DIR, None)) self.lastOpenDir = ustr(settings.get(SETTING_LAST_OPEN_DIR, None)) if saveDir is not None and os.path.exists(saveDir): self.defaultSaveDir = saveDir self.statusBar().showMessage( '%s started. Annotation will be saved to %s' % (__appname__, self.defaultSaveDir)) self.statusBar().show() self.restoreState(settings.get(SETTING_WIN_STATE, QByteArray())) self.lineColor = QColor( settings.get(SETTING_LINE_COLOR, Shape.line_color)) self.fillColor = QColor( settings.get(SETTING_FILL_COLOR, Shape.fill_color)) Shape.line_color = self.lineColor Shape.fill_color = self.fillColor Shape.difficult = self.difficult def xbool(x): if isinstance(x, QVariant): return x.toBool() return bool(x) if xbool(settings.get(SETTING_ADVANCE_MODE, False)): self.actions.advancedMode.setChecked(True) self.toggleAdvancedMode() self.updateFileMenu() self.queueEvent(partial(self.loadFile, self.filePath or "")) self.zoomWidget.valueChanged.connect(self.paintCanvas) self.populateModeActions()
def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSaveDir=None): super(MainWindow, self).__init__() self.setupUi(self) # For loading all image under a directory self.mImgList = [] self.dirname = None self.labelHist = [] self.lastOpenDir = None self.filePath = ustr(defaultFilename) # Load setting in the main thread self.settings = Settings() self.settings.load() settings = self.settings # Whether we need to save or not. self.dirty = False self.statusBar().showMessage('%s started.' % __appname__) self.statusBar().show() # Load string bundle for i18n self.stringBundle = StringBundle.getBundle() getStr = lambda strId: self.stringBundle.getString(strId) # 作用? # Save as Pascal voc xml self.defaultSaveDir = None # defaultSaveDir self.labelFileFormat = settings.get(SETTING_LABEL_FILE_FORMAT, LabelFileFormat.PASCAL_VOC) # Auto saving : Enable auto saving if pressing next self.autoSaving = QAction(getStr('autoSaveMode'), self) self.autoSaving.setCheckable(True) self.autoSaving.setChecked(settings.get(SETTING_AUTO_SAVE, False)) # 未加入setting self.canvas = Canvas(parent=self) # self.canvas.zoomRequest.connect(self.zoomRequest) self.canvas.setDrawingShapeToSquare( settings.get(SETTING_DRAW_SQUARE, False)) self.listView.itemDoubleClicked.connect( self.fileitemDoubleClicked) # 双击 self.open.triggered.connect(self.openFile) # Actions action = partial(newAction, self) quit = action(getStr('quit'), self.close, 'Ctrl+Q', 'quit', getStr('quitApp')) open = action(getStr('openFile'), self.openFile, 'Ctrl+O', 'open', getStr('openFileDetail')) opendir = action(getStr('openDir'), self.openDirDialog, 'Ctrl+u', 'open', getStr('openDir')) copyPrevBounding = action(getStr('copyPrevBounding'), self.copyPreviousBoundingBoxes, 'Ctrl+v', 'paste', getStr('copyPrevBounding')) changeSavedir = action(getStr('changeSaveDir'), self.changeSavedirDialog, 'Ctrl+r', 'open', getStr('changeSavedAnnotationDir')) # openAnnotation = action(getStr('openAnnotation'), self.openAnnotationDialog, # 'Ctrl+Shift+O', 'open', getStr('openAnnotationDetail')) openNextImg = action(getStr('nextImg'), self.openNextImg, 'd', 'next', getStr('nextImgDetail')) openPrevImg = action(getStr('prevImg'), self.openPrevImg, 'a', 'prev', getStr('prevImgDetail')) # verify = action(getStr('verifyImg'), self.verifyImg, # 'space', 'verify', getStr('verifyImgDetail')) save = action(getStr('save'), self.saveFile, 'Ctrl+S', 'save', getStr('saveDetail'), enabled=False) isUsingPascalVoc = self.labelFileFormat == LabelFileFormat.PASCAL_VOC # save_format = action('&PascalVOC' if isUsingPascalVoc else '&YOLO', # self.change_format, 'Ctrl+', # 'format_voc' if isUsingPascalVoc else 'format_yolo', # getStr('changeSaveFormat'), enabled=True) saveAs = action(getStr('saveAs'), self.saveFileAs, 'Ctrl+Shift+S', 'save-as', getStr('saveAsDetail'), enabled=False) close = action(getStr('closeCur'), self.closeFile, 'Ctrl+W', 'close', getStr('closeCurDetail')) deleteImg = action(getStr('deleteImg'), self.deleteImg, 'Ctrl+D', 'close', getStr('deleteImgDetail')) resetAll = action(getStr('resetAll'), self.resetAll, None, 'resetall', getStr('resetAllDetail')) # color1 = action(getStr('boxLineColor'), self.chooseColor1, # 'Ctrl+L', 'color_line', getStr('boxLineColorDetail')) # createMode = action(getStr('crtBox'), self.setCreateMode, # 'w', 'new', getStr('crtBoxDetail'), enabled=False) # editMode = action('&Edit\nRectBox', self.setEditMode, # 'Ctrl+J', 'edit', u'Move and edit Boxs', enabled=False) # # create = action(getStr('crtBox'), self.createShape, # 'w', 'new', getStr('crtBoxDetail'), enabled=False) # delete = action(getStr('delBox'), self.deleteSelectedShape, # 'Delete', 'delete', getStr('delBoxDetail'), enabled=False) # copy = action(getStr('dupBox'), self.copySelectedShape, # 'Ctrl+D', 'copy', getStr('dupBoxDetail'), # enabled=False) # advancedMode = action(getStr('advancedMode'), self.toggleAdvancedMode, # 'Ctrl+Shift+A', 'expert', getStr('advancedModeDetail'), # checkable=True) # hideAll = action('&Hide\nRectBox', partial(self.togglePolygons, False), # 'Ctrl+H', 'hide', getStr('hideAllBoxDetail'), # enabled=False) # showAll = action('&Show\nRectBox', 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')) self.zoomWidget = ZoomWidget() zoom = QWidgetAction(self) zoom.setDefaultWidget(self.zoomWidget) self.zoomWidget.setWhatsThis( u"Zoom in or out of the image. Also accessible with" " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), fmtShortcut("Ctrl+Wheel"))) self.zoomWidget.setEnabled(False) # zoomIn = action(getStr('zoomin'), partial(self.addZoom, 10), # 'Ctrl++', 'zoom-in', getStr('zoominDetail'), enabled=False) # zoomOut = action(getStr('zoomout'), partial(self.addZoom, -10), # 'Ctrl+-', 'zoom-out', getStr('zoomoutDetail'), enabled=False) # zoomOrg = action(getStr('originalsize'), partial(self.setZoom, 100), # 'Ctrl+=', 'zoom', getStr('originalsizeDetail'), enabled=False) # fitWindow = action(getStr('fitWin'), self.setFitWindow, # 'Ctrl+F', 'fit-window', getStr('fitWinDetail'), # checkable=True, enabled=False) # fitWidth = action(getStr('fitWidth'), self.setFitWidth, # 'Ctrl+Shift+F', 'fit-width', getStr('fitWidthDetail'), # checkable=True, enabled=False) # # Group zoom controls into a list for easier toggling. # zoomActions = (self.zoomWidget, zoomIn, zoomOut, # zoomOrg, fitWindow, fitWidth) # self.zoomMode = self.MANUAL_ZOOM # self.scalers = { # self.FIT_WINDOW: self.scaleFitWindow, # self.FIT_WIDTH: self.scaleFitWidth, # # Set to one to scale to 100% when loading files. # self.MANUAL_ZOOM: lambda: 1, # } # edit = action(getStr('editLabel'), self.editLabel, # 'Ctrl+E', 'edit', getStr('editLabelDetail'), # enabled=False) # self.editButton.setDefaultAction(edit) # shapeLineColor = action(getStr('shapeLineColor'), self.chshapeLineColor, # icon='color_line', tip=getStr('shapeLineColorDetail'), # enabled=False) # shapeFillColor = action(getStr('shapeFillColor'), self.chshapeFillColor, # icon='color', tip=getStr('shapeFillColorDetail'), # enabled=False) # 文件夹 # Store actions for further handling. self.actions = struct( save=save, saveAs=saveAs, open=open, close=close, #save_format=save_format, resetAll=resetAll, deleteImg=deleteImg, #lineColor=color1, create=create, delete=delete, edit=edit, copy=copy, #createMode=createMode, editMode=editMode, advancedMode=advancedMode, # shapeLineColor=shapeLineColor, shapeFillColor=shapeFillColor, # zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, # fitWindow=fitWindow, fitWidth=fitWidth, # zoomActions=zoomActions, fileMenuActions=(open, opendir, save, saveAs, close, resetAll, quit), beginner=(), advanced=(), # editMenu=(edit, copy, delete, # None, color1, self.drawSquaresOption), # beginnerContext=(create, edit, copy, delete), # advancedContext=(createMode, editMode, edit, copy, # delete, shapeLineColor, shapeFillColor), onLoadActive=(close), #, create, createMode, editMode), onShapesPresent=(saveAs)) #, hideAll, showAll)) # 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.tools = self.toolbar('Tools') self.actions.beginner = ( open, opendir, changeSavedir, openNextImg, openPrevImg, save, None, #create, copy, verify, save_format, #delete, None, ) # zoomIn, zoom, zoomOut, fitWindow, fitWidth) self.actions.advanced = ( open, opendir, changeSavedir, openNextImg, openPrevImg, save, None, #save_format, #createMode, editMode, None, ) # hideAll, showAll) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() }
def __init__(self, defaultFilename=None, defaultPrefdefClassFile=None, defaultSaveDir=None): super(MainWindow, self).__init__() self.setWindowTitle(__appname__) self.settings = Settings() self.settings.load() settings = self.settings self.stringBundle = StringBundle.getBundle() getStr = lambda strId: self.stringBundle.getString(strId) self.defaultSaveDir = defaultSaveDir self.mImgList = [] self.dirname = None self.labelHist = [] self.lastOpenDir = None self.dirty = False self.countEnable = 0 self._noSelectionSlot = False self._beginner = True self.loadPredefinedClasses(defaultPrefdefClassFile) self.defaultPrefdefClassFile = defaultPrefdefClassFile self.labelDialog = LabelDialog(parent=self, listItem=self.labelHist) self.itemsToShapes = {} self.shapesToItems = {} self.prevLabelText = '' listLayout = QVBoxLayout() listLayout.setContentsMargins(0, 0, 0, 0) self.defaultLabelTextLine = QLineEdit() self.labelList = QListWidget() self.logContainer = QListWidget() labelListContainer = QWidget() labelListContainer.setLayout(listLayout) self.labelList.itemClicked.connect(self.labelSelectionChanged) listLayout.addWidget(self.labelList) self.logContainer.itemChanged.connect(self.pointListChanged) self.logContainer.itemClicked.connect(self.pointSelectionChange) self.dock = QDockWidget("Log", self) self.dock.setObjectName(getStr('labels')) self.dock.setWidget(self.logContainer) self.logDock = QDockWidget(getStr('boxLabelText'), self) self.logDock.setObjectName("Log") self.logDock.setWidget(labelListContainer) self.zoomWidget = ZoomWidget() self.canvas = Canvas(parent=self) self.canvas.zoomRequest.connect(self.zoomRequest) self.canvas.setDrawingShapeToSquare(settings.get(SETTING_DRAW_SQUARE, False)) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.scrollArea = scroll self.canvas.scrollRequest.connect(self.scrollRequest) self.canvas.newShape.connect(self.newShape) self.canvas.shapeMoved.connect(self.setDirty) self.canvas.selectionChanged.connect(self.shapeSelectionChanged) self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive) self.setCentralWidget(scroll) self.addDockWidget(Qt.RightDockWidgetArea, self.logDock) self.addDockWidget(Qt.RightDockWidgetArea, self.dock) self.dockFeatures = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable self.logDock.setFeatures(self.logDock.features() ^ self.dockFeatures) self.dock.setFeatures(self.dock.features() ^ self.dockFeatures) action = partial(newAction, self) quit = action(getStr('quit'), self.close, '', 'quit', getStr('quitApp')) open = action(getStr('openFile'), self.openFile, '', 'open', getStr('openFileDetail')) save = action(getStr('save'), self.saveFile, '', 'save', getStr('saveDetail'), enabled=False) count = action('Count', self.countCell, '', 'color_line', 'count', enabled=False) self.partition = action("Auto Partition", self.createFixedPartition, '', 'verify', "Partition", enabled=False) self.selectNone = action('Select None', self.selectFun, '', 'done', 'select', enabled=False) openNextImg = action("Next Image", self.openNextImg, '', 'next', "next image", enabled=False) create = action("Create RectBox", self.createShape, '', 'new', getStr('crtBoxDetail'), enabled=False) delete = action("Delete RectBox", self.deleteSelectedShape, 'Delete', 'delete', getStr('delBoxDetail'), enabled=False) copy = action("Duplicate RectBox", self.copySelectedShape, '', 'copy', getStr('dupBoxDetail'), enabled=False) zoom = QWidgetAction(self) zoom.setDefaultWidget(self.zoomWidget) self.zoomWidget.setWhatsThis( u"Zoom in or out of the image. Also accessible with" " %s and %s from the canvas." % (fmtShortcut("Ctrl+[-+]"), fmtShortcut("Ctrl+Wheel"))) self.zoomWidget.setEnabled(False) help = action('Help',self.helpDialog,None,'help') about = action('About',self.aboutDialog,None,'help') zoomIn = action(getStr('zoomin'), partial(self.addZoom, 10), '', 'zoom-in', getStr('zoominDetail'), enabled=False) zoomOut = action(getStr('zoomout'), partial(self.addZoom, -10), '', 'zoom-out', getStr('zoomoutDetail'), enabled=False) zoomOrg = action(getStr('originalsize'), partial(self.setZoom, 100), '', 'zoom', getStr('originalsizeDetail'), enabled=False) fitWindow = action(getStr('fitWin'), self.setFitWindow, '', 'fit-window', getStr('fitWinDetail'), checkable=True, enabled=False) fitWidth = action(getStr('fitWidth'), self.setFitWidth, '', 'fit-width', getStr('fitWidthDetail'), checkable=True, enabled=False) zoomActions = (self.zoomWidget, zoomIn, zoomOut, zoomOrg, fitWindow, fitWidth) self.zoomMode = self.MANUAL_ZOOM self.scalers = { self.FIT_WINDOW: self.scaleFitWindow, self.FIT_WIDTH: self.scaleFitWidth, self.MANUAL_ZOOM: lambda: 1, } labelMenu = QMenu() addActions(labelMenu, (delete,)) self.labelList.setContextMenuPolicy(Qt.CustomContextMenu) self.labelList.customContextMenuRequested.connect( self.popLabelListMenu) self.sporeCountOption = QAction('Spore count', self) self.sporeCountOption.setCheckable(True) self.sporeCountOption.setDisabled(True) self.sporeCountOption.triggered.connect(self.sporeCountFun) self.rbcCountOption = QAction('RBC count', self) self.rbcCountOption.setCheckable(True) self.rbcCountOption.setDisabled(True) self.rbcCountOption.triggered.connect(self.rbcCountFun) self.wbcCountOption = QAction('WBC count', self) self.wbcCountOption.setCheckable(True) self.wbcCountOption.setDisabled(True) self.wbcCountOption.triggered.connect(self.wbcCountFun) self.bacteriaCountOption = QAction('Bacteria count', self) self.bacteriaCountOption.setCheckable(True) self.bacteriaCountOption.setDisabled(True) self.bacteriaCountOption.triggered.connect(self.bacteriaCountFun) self.labelImage = QAction('Label Image', self) self.labelImage.setDisabled(True) self.labelImage.triggered.connect(self.labelImageFun) self.modifyLabel = QAction('Modify Label', self) self.modifyLabel.setDisabled(False) self.modifyLabel.triggered.connect(self.modifyLabelFun) self.createModel = QAction('Create Model', self) self.createModel.setDisabled(True) self.createModel.triggered.connect(self.createModelFun) self.useModel = QAction('Use Existing Model', self) self.useModel.setDisabled(True) self.useModel.triggered.connect(self.useModelFun) self.actions = struct(save=save, open=open, count=(count,), selectNone=self.selectNone, partition=self.partition, create=create, delete=delete, copy=copy, zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, fitWindow=fitWindow, fitWidth=fitWidth, zoomActions=zoomActions, beginner=(), advanced=(), menuMenu=(self.sporeCountOption, self.rbcCountOption, self.wbcCountOption, self.bacteriaCountOption), toolMenu=(self.labelImage, self.modifyLabel), modelMenu=(self.createModel, self.useModel), beginnerContext=(create, copy, delete), advancedContext=(copy, delete), onLoadActive=(create,), onNullImage=(self.labelImage, self.sporeCountOption, self.rbcCountOption, self.bacteriaCountOption, self.createModel, self.useModel), onLabelSelect=(openNextImg, ), resetDeActive=(count, copy, delete, save, create, openNextImg, self.selectNone, self.partition)) self.menus = struct( file=self.menu('&File'), menu=self.menu('&Menu'), tool=self.menu('&Tools'), model=self.menu('&Models'), help=self.menu('&Help')) self.lastLabel = None addActions(self.menus.file, (open, save, quit)) addActions(self.menus.help,(help,about)) self.menus.file.aboutToShow.connect(self.updateFileMenu) addActions(self.canvas.menus[0], self.actions.beginnerContext) addActions(self.canvas.menus[1], ( action('&Copy here', self.copyShape), action('&Move here', self.moveShape))) self.tools = self.toolbar('Tools') self.actions.beginner = ( open, count, self.partition, self.selectNone, save, None, openNextImg, create, copy, delete, None, zoomIn, zoom, zoomOut, fitWindow, fitWidth) self.actions.advanced = (open, save, count, self.partition, self.selectNone, None) self.statusBar().showMessage('%s started.' % __appname__) self.statusBar().show() self.image = QImage() self.filePath = defaultFilename self.recentFiles = [] self.maxRecent = 7 self.lineColor = None self.fillColor = None self.zoom_level = 100 self.fit_window = False self.difficult = False if settings.get(SETTING_RECENT_FILES): if have_qstring(): recentFileQStringList = settings.get(SETTING_RECENT_FILES) self.recentFiles = [i for i in recentFileQStringList] else: self.recentFiles = recentFileQStringList = settings.get(SETTING_RECENT_FILES) size = settings.get(SETTING_WIN_SIZE, QSize(600, 500)) position = QPoint(0, 0) saved_position = settings.get(SETTING_WIN_POSE, position) # Fix the multiple monitors issue for i in range(QApplication.desktop().screenCount()): if QApplication.desktop().availableGeometry(i).contains(saved_position): position = saved_position break self.resize(size) self.move(position) saveDir = settings.get(SETTING_SAVE_DIR, None) self.lastOpenDir = settings.get(SETTING_LAST_OPEN_DIR, None) if self.defaultSaveDir is None and saveDir is not None and os.path.exists(saveDir): self.defaultSaveDir = saveDir self.statusBar().showMessage('%s started. Annotation will be saved to %s' % (__appname__, self.defaultSaveDir)) self.statusBar().show() self.restoreState(settings.get(SETTING_WIN_STATE, QByteArray())) Shape.line_color = self.lineColor = QColor(settings.get(SETTING_LINE_COLOR, DEFAULT_LINE_COLOR)) Shape.fill_color = self.fillColor = QColor(settings.get(SETTING_FILL_COLOR, DEFAULT_FILL_COLOR)) self.canvas.setDrawingColor(self.lineColor) Shape.difficult = self.difficult self.updateFileMenu() self.zoomWidget.valueChanged.connect(self.paintCanvas) self.populateModeActions() self.labelCoordinates = QLabel('') self.statusBar().addPermanentWidget(self.labelCoordinates)
def __init__(self, defaultFilename=None, defaaultPrefdefClassFile=None, defaultSaveDir=None): super(MainWindow, self).__init__() self.setWindowTitle(__appname__) #Load setting in the main thread self.settings = Settings() self.settings.load() settings = self.settings #load string bundle for i18n self.stringBundle = StringBundle.getBundle() getStr = lambda strId: self.stringBundle.getString(strId) #save as pascal voc xml self.defaultSaveDir = defaultSaveDir self.labelFileFormat = settings.get(SETTING_LABEL_FILE_FORMAT, LabelFileFormat.PASCAL_VOC) #for loading all image under a directory self.mImgList = [] self.dirname = None self.labelHist = [] self.lastOpenDir = None #NEED TO DO #whether we need to save or not self.dirty = False self._noSelectionSlot = False self._beginner = True self.screencastViewer = self.getAvailableScreencastViewer() self.screencast = "https://youtu.be/p0nR2YsCY_U" #Load predefined classes to the list self.loadPredefinedClasses(defaaultPrefdefClassFile) #main widgets and related state self.labelDialog = LabelDialog(parent=self, listItem=self.labelHist) self.itemsToShapes = {} self.shapesToItems = {} self.prevLabelText = '' filelistLayout = QVBoxLayout() filelistLayout.setContentsMargins(0, 0, 0, 0) self.fileList = QListWidget() self.fileList.itemDoubleClicked.connect(self.fileitemDoubleClicked) filelistLayout.addWidget(self.fileList) fileListContainer = QWidget() fileListContainer.setLayout(filelistLayout) self.filedock = QDockWidget(getStr('fileList'), self) self.filedock.setObjectName(getStr('files')) self.filedock.setWidget(fileListContainer) self.addDockWidget(Qt.LeftDockWidgetArea, self.filedock) self.zoomWidget = ZoomWidget() self.colorDialog = ColorDialog(parent=self) self.canvas = Canvas(parent=self) self.canvas.zoomRequest.connect(self.zoomRequest) self.canvas.setDrawingShapeToSquare( settings.get(SETTING_DRAW_SQUARE, False)) scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.scrollArea = scroll self.canvas.scrollRequest.connect(self.scrollRequest) self.canvas.newShape.connect(self.newShape) self.canvas.shapeMoved.connect(self.setDirty) self.canvas.selectionChanged.connect(self.shapeSelectionChanged) self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive) self.setCentralWidget(scroll) rightListLayout = QVBoxLayout() self.addNewBboxBtn = QPushButton(getStr('addNewBbox')) self.addNewBboxBtn.setEnabled(True) self.addNewBboxBtn.clicked.connnect(self.createShape) self.reLabelBtn = QPushButton(getStr('reLabel')) self.reLabelBtn.setEnabled(True) self.reLabelBtn.clicked.connect(self.reLabel) rightUpLayout = QHBoxLayout() rightUpLayout.addWidget(self.addNewBboxBtn) rightUpLayout.addWidget(self.reLabelBtn)
def __init__(self, appname='defaultName', defaultFilename=nonePath, defaultPredefClassFile=nonePath, defaultImageFolder=nonePath, defaultLabelFolder=nonePath): super().__init__() self.__appname = appname self.setWindowTitle(appname) # Load string bundle for i18n self.__stringBundle = StringBundle.getBundle() def getStr(strId): return self.__stringBundle.getString(strId) # Load setting in the main thread self.settings = Settings() self.settings.load() settings = self.settings # Unsaved Status Flag self.__dirty = False # For loading all image under a directory self.__mImgList = [] self.__foldername = nonePath self.__labelHist = [] # Match Shapes and Labels self.__itemsToShapes = {} self.__shapesToItems = {} self.__prevLabelText = '' self.__noSelectionSlot = False # Application state. self.__selectedClass = None # File and path informations self.__image = QImage() self.__filePath = defaultFilename self.__imageFolder = defaultImageFolder self.__labelFolder = defaultLabelFolder self.__lastOpenFolder = nonePath self.__loadPredefinedClasses(defaultPredefClassFile) self.__recentFiles = [] self.__maxRecent = 7 # Application state self.__lineColor = None self.__fillColor = None # Save as Format Flags self.__usePascalVocFormat = True self.__useYoloFormat = False self.__useBoxSupFormat = False self.__useBoxSupMaskFormat = False self.__mask = False # ##############################WDIGETS############################## # # Create ZoomWidget self.zoomWidget = ZoomWidget() # ____________________ __________ _____ # ___ ____/__(_)__ /_______ /__(_)________ /_ # __ /_ __ /__ /_ _ \_ /__ /__ ___/ __/ # _ __/ _ / _ / / __/ / _ / _(__ )/ /_ # /_/ /_/ /_/ \___//_/ /_/ /____/ \__/ # Create FileListWidget listLayout = QVBoxLayout() listLayout.setContentsMargins(0, 0, 0, 0) # Create and add a widget for showing current label items self.labelList = QListWidget() labelListContainer = QWidget() labelListContainer.setLayout(listLayout) self.labelList.itemActivated.connect(self.labelSelectionChanged) self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged) # self.labelList.itemDoubleClicked.connect(self.editLabel) # Connect to itemChanged to detect checkbox changes. self.labelList.itemChanged.connect(self.labelItemChanged) listLayout.addWidget(self.labelList) self.boxDock = QDockWidget(getStr('boxLabelText'), self) self.boxDock.setObjectName(getStr('labels')) self.boxDock.setWidget(labelListContainer) self.__fileListWidget = QListWidget() self.fileListWidget.itemDoubleClicked.\ connect(self.fileitemDoubleClicked) filelistLayout = QVBoxLayout() filelistLayout.setContentsMargins(0, 0, 0, 0) filelistLayout.addWidget(self.fileListWidget) fileListContainer = QWidget() fileListContainer.setLayout(filelistLayout) self.fileDock = QDockWidget(getStr('fileList'), self) self.fileDock.setObjectName(getStr('files')) self.fileDock.setWidget(fileListContainer) # Create Canvas Widget self.__canvas = Canvas(parent=self) self.canvas.setEnabled(False) # Create Central Widget scroll = QScrollArea() scroll.setWidget(self.canvas) scroll.setWidgetResizable(True) self.scrollBars = { Qt.Vertical: scroll.verticalScrollBar(), Qt.Horizontal: scroll.horizontalScrollBar() } self.scrollArea = scroll # ____________ ______ # __ ___/__(_)______ _____________ ___ /_______ # _____ \__ /__ __ `/_ __ \ __ `/_ /__ ___/ # ____/ /_ / _ /_/ /_ / / / /_/ /_ / _(__ ) # /____/ /_/ _\__, / /_/ /_/\__,_/ /_/ /____/ self.canvas.newShape.connect(self.newShape) self.canvas.shapeMoved.connect(self.shapeMoved) self.canvas.selectionChanged.connect(self.shapeSelectionChanged) self.canvas.finishedDrawing.connect(self.finishedDrawing) self.setCentralWidget(scroll) self.addDockWidget(Qt.RightDockWidgetArea, self.boxDock) self.addDockWidget(Qt.RightDockWidgetArea, self.fileDock) self.fileDock.setFeatures(QDockWidget.DockWidgetFloatable) self.dockFeatures = QDockWidget.DockWidgetClosable \ | QDockWidget.DockWidgetFloatable self.boxDock.setFeatures(self.boxDock.features() ^ self.dockFeatures) # _______ __________ # ___ |_______ /___(_)____________________ # __ /| | ___/ __/_ /_ __ \_ __ \_ ___/ # _ ___ / /__ / /_ _ / / /_/ / / / /(__ ) # /_/ |_\___/ \__/ /_/ \____//_/ /_//____/ # Load Actions # Manage File system quit = self.get_quit() open = self.get_open() openfolder = self.get_openfolder() start = self.get_startlabel() delete = self.get_delete() save = self.get_save() changesavefolder = self.get_changesavefolder() autosaving = self.get_autosaving() saveformat = self.get_saveformat() openNextImg = self.get_openNextImg() openPrevImg = self.get_openPrevImg() # Load Settings autosaving.setChecked(settings.get(SETTING_AUTO_SAVE, False)) if settings.get(SETTING_RECENT_FILES): self.recentFiles = settings.get(SETTING_RECENT_FILES) # Manage Window Zoom zoom = self.get_zoom() zoomIn = self.get_zoomin() zoomOut = self.get_zoomout() zoomOrg = self.get_zoomorg() fitWindow = self.get_fitwindow() fitWidth = self.get_fitwidth() # Formats voc = self.get_voc() yolo = self.get_yolo() boxsup = self.get_boxsup() boxsupMask = self.get_boxsupMask() # Store actions for further handling. self.__actions = struct(open=open, openfolder=openfolder, quit=quit, zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg, start=start, fitWindow=fitWindow, fitWidth=fitWidth, autosaving=autosaving, save=save, saveformat=saveformat, changesavefolder=changesavefolder, openNextImg=openNextImg, openPrevImg=openPrevImg, voc=voc, yolo=yolo, boxsup=boxsup, boxsupMask=boxsupMask, fileMenuActions=(open, openfolder, quit), beginner=(), advanced=(), classes=(), editMenu=(start, delete), beginnerContext=(), advancedContext=(), onLoadActive=(start, delete), onShapesPresent=(), zoomActions=(self.zoomWidget, zoomIn, zoomOut, zoomOrg, fitWindow, fitWidth)) # Store class Actions self.classes = struct(activeClass=None) self.create_classes() # Create Menus self.menus = struct(file=self.menu('&File'), edit=self.menu('&Edit'), view=self.menu('&View'), help=self.menu('&Help'), recentFiles=QMenu('Open &Recent'), formats=QMenu('Change &Formats')) # Fill Menus addActions(self.menus.file, ( open, openfolder, changesavefolder, self.menus.recentFiles, save, self.menus.formats, autosaving, openNextImg, openPrevImg, quit, )) addActions(self.menus.edit, (start, delete)) addActions(self.menus.view, (zoomIn, zoomOut, zoomOrg, None, fitWindow, fitWidth)) addActions(self.menus.formats, (voc, yolo, boxsup, boxsupMask)) # self.autoSaving, # self.singleClassMode, # self.displayLabelOption, # labels, advancedMode, None, # hideAll, showAll, None, # zoomIn, zoomOut, zoomOrg, None, # addActions(self.menus.help, (help, showInfo)) self.menus.file.aboutToShow.connect(self.updateFileMenu) # Create Toolbars self.tools = self.toolbar('Tools', position='left') self.classtools = self.toolbar('Classes', position='top') self.actions.beginner = (open, openfolder, changesavefolder, saveformat, None, start, None, zoomIn, zoom, zoomOrg, zoomOut, fitWindow, fitWidth, None, quit) self.actions.classes = self.get_classes() addActions(self.tools, self.actions.beginner) addActions(self.classtools, self.actions.classes) self.statusBar().showMessage('%s started.' % appname) self.statusBar().show() self.zoomMode = self.MANUAL_ZOOM self.scalers = { self.FIT_WINDOW: self.scaleFitWindow, self.FIT_WIDTH: self.scaleFitWidth, # Set to one to scale to 100% when loading files. self.MANUAL_ZOOM: lambda: 1, } # Display cursor coordinates at the right of status bar self.labelCoordinates = QLabel('') self.statusBar().addPermanentWidget(self.labelCoordinates) # Resize and Position Application size = settings.get(SETTING_WIN_SIZE, QSize(820, 800)) position = QPoint(0, 0) saved_position = settings.get(SETTING_WIN_POSE, position) for i in range(QApplication.desktop().screenCount()): desktop = QApplication.desktop().availableGeometry(i) if desktop.contains(saved_position): position = saved_position break self.resize(size) self.move(position) # Load Default Save settings LabelDir = settings.get(SETTING_LABEL_DIR, nonePath) if LabelDir is None: LabelDir = nonePath # TODO make nonePath pickable TemplastOpenFolder = settings.get(SETTING_LAST_OPEN_FOLDER, nonePath) if TemplastOpenFolder is None: self.lastOpenFolder = nonePath # TODO make nonePath picklable else: self.lastOpenFolder = TemplastOpenFolder if self.labelFolder is nonePath and LabelDir is not nonePath and \ LabelDir.exists(): self.labelFolder = LabelDir self.statusBar().showMessage( '%s started. Annotation will be saved to %s' % (self.appname, self.labelFolder)) self.statusBar().show() self.restoreState(settings.get(SETTING_WIN_STATE, QByteArray())) Shape.line_color = self.lineColor = QColor( settings.get(SETTING_LINE_COLOR, DEFAULT_LINE_COLOR)) Shape.fill_color = self.fillColor = QColor( settings.get(SETTING_FILL_COLOR, DEFAULT_FILL_COLOR)) self.canvas.setDrawingColor(self.lineColor) self.zoomWidget.valueChanged.connect(self.paintCanvas)