在菜单edit和鼠标右键 增加图片左右旋转功能

This commit is contained in:
Alchemist_W 2021-07-22 13:11:18 +08:00
parent aa12eb2637
commit 4df7ada91d
5 changed files with 7447 additions and 3457 deletions

View File

@ -27,7 +27,12 @@ import json
import cv2 import cv2
__dir__ = os.path.dirname(os.path.abspath(__file__)) __dir__ = os.path.dirname(os.path.abspath(__file__))
import numpy as np
from labelme import LabelFile
sys.path.append(__dir__) sys.path.append(__dir__)
sys.path.append(os.path.abspath(os.path.join(__dir__, '../..'))) sys.path.append(os.path.abspath(os.path.join(__dir__, '../..')))
sys.path.append("..") sys.path.append("..")
@ -78,7 +83,7 @@ class WindowMixin(object):
addActions(menu, actions) addActions(menu, actions)
return menu return menu
def toolbar(self, title, actions=None): def toolbar(self, title, actions=None):
toolbar = ToolBar(title) toolbar = ToolBar(title)
toolbar.setObjectName(u'%sToolBar' % title) toolbar.setObjectName(u'%sToolBar' % title)
# toolbar.setOrientation(Qt.Vertical) # toolbar.setOrientation(Qt.Vertical)
@ -98,7 +103,7 @@ class MainWindow(QMainWindow, WindowMixin):
# Load setting in the main thread # Load setting in the main thread
self.settings = Settings() self.settings = Settings()
self.settings.load() self.settings.load()
settings = self.settings settings = self.settings
self.lang = lang self.lang = lang
# Load string bundle for i18n # Load string bundle for i18n
@ -159,7 +164,7 @@ class MainWindow(QMainWindow, WindowMixin):
filelistLayout = QVBoxLayout() filelistLayout = QVBoxLayout()
filelistLayout.setContentsMargins(0, 0, 0, 0) filelistLayout.setContentsMargins(0, 0, 0, 0)
filelistLayout.addWidget(self.fileListWidget) filelistLayout.addWidget(self.fileListWidget)
self.AutoRecognition = QToolButton() self.AutoRecognition = QToolButton()
self.AutoRecognition.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.AutoRecognition.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
self.AutoRecognition.setIcon(newIcon('Auto')) self.AutoRecognition.setIcon(newIcon('Auto'))
@ -176,7 +181,7 @@ class MainWindow(QMainWindow, WindowMixin):
self.filedock.setObjectName(getStr('files')) self.filedock.setObjectName(getStr('files'))
self.filedock.setWidget(fileListContainer) self.filedock.setWidget(fileListContainer)
self.addDockWidget(Qt.LeftDockWidgetArea, self.filedock) self.addDockWidget(Qt.LeftDockWidgetArea, self.filedock)
######## Right area ########## ######## Right area ##########
listLayout = QVBoxLayout() listLayout = QVBoxLayout()
listLayout.setContentsMargins(0, 0, 0, 0) listLayout.setContentsMargins(0, 0, 0, 0)
@ -250,7 +255,7 @@ class MainWindow(QMainWindow, WindowMixin):
self.imgsplider.setMaximum(150) self.imgsplider.setMaximum(150)
self.imgsplider.setSingleStep(1) self.imgsplider.setSingleStep(1)
self.imgsplider.setTickPosition(QSlider.TicksBelow) self.imgsplider.setTickPosition(QSlider.TicksBelow)
self.imgsplider.setTickInterval(1) self.imgsplider.setTickInterval(1)
op = QGraphicsOpacityEffect() op = QGraphicsOpacityEffect()
op.setOpacity(0.2) op.setOpacity(0.2)
self.imgsplider.setGraphicsEffect(op) self.imgsplider.setGraphicsEffect(op)
@ -266,7 +271,9 @@ class MainWindow(QMainWindow, WindowMixin):
self.zoomWidget = ZoomWidget() self.zoomWidget = ZoomWidget()
self.colorDialog = ColorDialog(parent=self) self.colorDialog = ColorDialog(parent=self)
self.zoomWidgetValue = self.zoomWidget.value() self.zoomWidgetValue = self.zoomWidget.value()
self.msgBox = QMessageBox()
########## thumbnail ######### ########## thumbnail #########
hlayout = QHBoxLayout() hlayout = QHBoxLayout()
m = (0, 0, 0, 0) m = (0, 0, 0, 0)
@ -294,7 +301,7 @@ class MainWindow(QMainWindow, WindowMixin):
self.nextButton.setStyleSheet('border: none;') self.nextButton.setStyleSheet('border: none;')
self.nextButton.clicked.connect(self.openNextImg) self.nextButton.clicked.connect(self.openNextImg)
self.nextButton.setShortcut('d') self.nextButton.setShortcut('d')
hlayout.addWidget(self.preButton) hlayout.addWidget(self.preButton)
hlayout.addWidget(self.iconlist) hlayout.addWidget(self.iconlist)
hlayout.addWidget(self.nextButton) hlayout.addWidget(self.nextButton)
@ -303,7 +310,7 @@ class MainWindow(QMainWindow, WindowMixin):
iconListContainer = QWidget() iconListContainer = QWidget()
iconListContainer.setLayout(hlayout) iconListContainer.setLayout(hlayout)
iconListContainer.setFixedHeight(100) iconListContainer.setFixedHeight(100)
########### Canvas ########### ########### Canvas ###########
self.canvas = Canvas(parent=self) self.canvas = Canvas(parent=self)
self.canvas.zoomRequest.connect(self.zoomRequest) self.canvas.zoomRequest.connect(self.zoomRequest)
@ -442,7 +449,7 @@ class MainWindow(QMainWindow, WindowMixin):
AutoRec = action(getStr('autoRecognition'), self.autoRecognition, AutoRec = action(getStr('autoRecognition'), self.autoRecognition,
'', 'Auto', getStr('autoRecognition'), enabled=False) '', 'Auto', getStr('autoRecognition'), enabled=False)
reRec = action(getStr('reRecognition'), self.reRecognition, 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, singleRere = action(getStr('singleRe'), self.singleRerecognition,
@ -460,6 +467,12 @@ class MainWindow(QMainWindow, WindowMixin):
undoLastPoint = action(getStr("undoLastPoint"), self.canvas.undoLastPoint, undoLastPoint = action(getStr("undoLastPoint"), self.canvas.undoLastPoint,
'Ctrl+Z', "undo", getStr("undoLastPoint"), enabled=False) 'Ctrl+Z', "undo", getStr("undoLastPoint"), enabled=False)
rotateLeft = action(getStr("rotateLeft"), self.rotateLeftImg,
'Ctrl+Alt+L', "rotateLeft", getStr("rotateLeft"), enabled=False)
rotateRight = action(getStr("rotateRight"), self.rotateRightImg,
'Ctrl+Alt+R', "rotateRight", getStr("rotateRight"), enabled=False)
undo = action(getStr("undo"), self.undoShapeEdit, undo = action(getStr("undo"), self.undoShapeEdit,
'Ctrl+Z', "undo", getStr("undo"), enabled=False) 'Ctrl+Z', "undo", getStr("undo"), enabled=False)
@ -524,12 +537,13 @@ class MainWindow(QMainWindow, WindowMixin):
fitWindow=fitWindow, fitWidth=fitWidth, fitWindow=fitWindow, fitWidth=fitWidth,
zoomActions=zoomActions, saveLabel=saveLabel, zoomActions=zoomActions, saveLabel=saveLabel,
undo=undo, undoLastPoint=undoLastPoint,open_dataset_dir=open_dataset_dir, undo=undo, undoLastPoint=undoLastPoint,open_dataset_dir=open_dataset_dir,
rotateLeft=rotateLeft,rotateRight=rotateRight,
fileMenuActions=( fileMenuActions=(
opendir, open_dataset_dir, saveLabel, resetAll, quit), opendir, open_dataset_dir, saveLabel, resetAll, quit),
beginner=(), advanced=(), beginner=(), advanced=(),
editMenu=(createpoly, edit, copy, delete,singleRere,None, undo, undoLastPoint, editMenu=(createpoly, edit, copy, delete,singleRere,None, undo, undoLastPoint,
None, color1, self.drawSquaresOption), None, rotateLeft, rotateRight, None, color1, self.drawSquaresOption),
beginnerContext=(create, edit, copy, delete, singleRere), beginnerContext=(create, edit, copy, delete, singleRere, rotateLeft, rotateRight,),
advancedContext=(createMode, editMode, edit, copy, advancedContext=(createMode, editMode, edit, copy,
delete, shapeLineColor, shapeFillColor), delete, shapeLineColor, shapeFillColor),
onLoadActive=( onLoadActive=(
@ -781,6 +795,49 @@ class MainWindow(QMainWindow, WindowMixin):
self.actions.create.setEnabled(False) self.actions.create.setEnabled(False)
self.actions.undoLastPoint.setEnabled(True) self.actions.undoLastPoint.setEnabled(True)
def rotateLeftImg(self, _value=False):
filename = self.mImgList[self.currIndex]
if os.path.exists(filename):
_value = True
self.actions.rotateLeft.setEnabled(_value)
pix = cv2.imread(filename)
pix = np.rot90(pix, k=1)
cv2.imwrite(filename, pix)
self.canvas.update()
self.loadFile(filename)
else:
_value = False
if self.lang == 'ch':
self.msgBox.warning(self, "提示", "\n 请从图片列表选择一个需要旋转的图片,且确保图片存在!")
else:
self.msgBox.warning(self, "Warn", "\n Please select an image from the list of images to rotate and make sure the image exists!")
self.actions.rotateLeft.setEnabled(_value)
def rotateRightImg(self, _value=False):
filename = self.mImgList[self.currIndex]
if os.path.exists(filename):
_value = True
self.actions.rotateRight.setEnabled(_value)
pix = cv2.imread(filename)
pix = np.rot90(pix, k=-1)
cv2.imwrite(filename, pix)
self.canvas.update()
self.loadFile(filename)
else:
_value = False
if self.lang == 'ch':
self.msgBox.warning(self, "提示", "\n 请从图片列表选择一个需要旋转的图片,且确保图片存在!")
else:
self.msgBox.warning(self, "Warn", "\n Please select an image from the list of images to rotate and make sure the image exists!")
self.actions.rotateRight.setEnabled(_value)
def toggleDrawingSensitive(self, drawing=True): def toggleDrawingSensitive(self, drawing=True):
"""In the middle of drawing, toggling between modes should be disabled.""" """In the middle of drawing, toggling between modes should be disabled."""
self.actions.editMode.setEnabled(not drawing) self.actions.editMode.setEnabled(not drawing)
@ -1277,7 +1334,7 @@ class MainWindow(QMainWindow, WindowMixin):
titem = self.iconlist.item(i) titem = self.iconlist.item(i)
titem.setSelected(True) titem.setSelected(True)
self.iconlist.scrollToItem(titem) self.iconlist.scrollToItem(titem)
break break
else: else:
self.fileListWidget.clear() self.fileListWidget.clear()
self.mImgList.clear() self.mImgList.clear()
@ -1285,7 +1342,7 @@ class MainWindow(QMainWindow, WindowMixin):
# if unicodeFilePath and self.iconList.count() > 0: # if unicodeFilePath and self.iconList.count() > 0:
# if unicodeFilePath in self.mImgList: # if unicodeFilePath in self.mImgList:
if unicodeFilePath and os.path.exists(unicodeFilePath): if unicodeFilePath and os.path.exists(unicodeFilePath):
self.canvas.verified = False self.canvas.verified = False
@ -1316,7 +1373,7 @@ class MainWindow(QMainWindow, WindowMixin):
self.addRecentFile(self.filePath) self.addRecentFile(self.filePath)
self.toggleActions(True) self.toggleActions(True)
self.showBoundingBoxFromPPlabel(filePath) self.showBoundingBoxFromPPlabel(filePath)
self.setWindowTitle(__appname__ + ' ' + filePath) self.setWindowTitle(__appname__ + ' ' + filePath)
# Default : select last item if there is at least one item # Default : select last item if there is at least one item
@ -1328,7 +1385,7 @@ class MainWindow(QMainWindow, WindowMixin):
return True return True
return False return False
def showBoundingBoxFromPPlabel(self, filePath): def showBoundingBoxFromPPlabel(self, filePath):
imgidx = self.getImglabelidx(filePath) imgidx = self.getImglabelidx(filePath)
if imgidx not in self.PPlabel.keys(): if imgidx not in self.PPlabel.keys():
@ -1421,6 +1478,7 @@ class MainWindow(QMainWindow, WindowMixin):
def loadRecent(self, filename): def loadRecent(self, filename):
if self.mayContinue(): if self.mayContinue():
print(filename,"======")
self.loadFile(filename) self.loadFile(filename)
def scanAllImages(self, folderPath): def scanAllImages(self, folderPath):
@ -1456,7 +1514,7 @@ class MainWindow(QMainWindow, WindowMixin):
self.lastOpenDir = targetDirPath self.lastOpenDir = targetDirPath
self.importDirImages(targetDirPath) self.importDirImages(targetDirPath)
def openDatasetDirDialog(self, _value=False): #1458 def openDatasetDirDialog(self,):
if not self.mayContinue(): if not self.mayContinue():
return return
@ -1467,7 +1525,7 @@ class MainWindow(QMainWindow, WindowMixin):
if self.lang == 'ch': if self.lang == 'ch':
self.msgBox.warning(self, "提示", "\n 原文件夹已不存在,请从新选择数据集路径!") self.msgBox.warning(self, "提示", "\n 原文件夹已不存在,请从新选择数据集路径!")
else: 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) self.actions.open_dataset_dir.setEnabled(False)
defaultOpenDirPath = os.path.dirname(self.filePath) if self.filePath else '.' defaultOpenDirPath = os.path.dirname(self.filePath) if self.filePath else '.'
@ -1520,6 +1578,9 @@ class MainWindow(QMainWindow, WindowMixin):
self.actions.AutoRec.setEnabled(True) self.actions.AutoRec.setEnabled(True)
self.actions.reRec.setEnabled(True) self.actions.reRec.setEnabled(True)
self.actions.open_dataset_dir.setEnabled(True) self.actions.open_dataset_dir.setEnabled(True)
self.actions.rotateLeft.setEnabled(True)
self.actions.rotateRight.setEnabled (True)
def openPrevImg(self, _value=False): def openPrevImg(self, _value=False):
@ -1528,7 +1589,7 @@ class MainWindow(QMainWindow, WindowMixin):
if self.filePath is None: if self.filePath is None:
return return
currIndex = self.mImgList.index(self.filePath) currIndex = self.mImgList.index(self.filePath)
self.mImgList5 = self.mImgList[:5] self.mImgList5 = self.mImgList[:5]
if currIndex - 1 >= 0: if currIndex - 1 >= 0:
@ -1558,7 +1619,7 @@ class MainWindow(QMainWindow, WindowMixin):
if filename: if filename:
print('file name in openNext is ',filename) print('file name in openNext is ',filename)
self.loadFile(filename) self.loadFile(filename)
def updateFileListIcon(self, filename): def updateFileListIcon(self, filename):
pass pass
@ -1670,7 +1731,7 @@ class MainWindow(QMainWindow, WindowMixin):
proc.startDetached(os.path.abspath(__file__)) proc.startDetached(os.path.abspath(__file__))
def mayContinue(self): # def mayContinue(self): #
if not self.dirty: if not self.dirty:
return True return True
else: else:
discardChanges = self.discardChangesDialog() discardChanges = self.discardChangesDialog()
@ -2097,7 +2158,7 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
resource_file = './libs/resources.py' resource_file = './libs/resources.py'
if not os.path.exists(resource_file): if not os.path.exists(resource_file):
output = os.system('pyrcc5 -o libs/resources.py resources.qrc') output = os.system('pyrcc5 -o libs/resources.py resources.qrc')

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,8 @@
<file alias="quit">resources/icons/quit.png</file> <file alias="quit">resources/icons/quit.png</file>
<file alias="copy">resources/icons/copy.png</file> <file alias="copy">resources/icons/copy.png</file>
<file alias="edit">resources/icons/edit.png</file> <file alias="edit">resources/icons/edit.png</file>
<file alias="rotateLeft">resources/icons/rotateLeft.png</file>
<file alias="rotateRight">resources/icons/rotateRight.png</file>
<file alias="open">resources/icons/open.png</file> <file alias="open">resources/icons/open.png</file>
<file alias="save">resources/icons/save.png</file> <file alias="save">resources/icons/save.png</file>
<file alias="format_voc">resources/icons/format_voc.png</file> <file alias="format_voc">resources/icons/format_voc.png</file>

View File

@ -86,6 +86,8 @@ detectionBoxposition=检测框位置
recognitionResult=识别结果 recognitionResult=识别结果
creatPolygon=四点标注 creatPolygon=四点标注
drawSquares=正方形标注 drawSquares=正方形标注
rotateLeft=图片左旋转90度
rotateRight=图片右旋转90度
saveRec=保存识别结果 saveRec=保存识别结果
tempLabel=待识别 tempLabel=待识别
nullLabel=无法识别 nullLabel=无法识别

View File

@ -85,6 +85,8 @@ iconList=Icon List
detectionBoxposition=Detection box position detectionBoxposition=Detection box position
recognitionResult=Recognition result recognitionResult=Recognition result
creatPolygon=Create Quadrilateral creatPolygon=Create Quadrilateral
rotateLeft=Left turn 90 degrees
rotateRight=Right turn 90 degrees
drawSquares=Draw Squares drawSquares=Draw Squares
saveRec=Save Recognition Result saveRec=Save Recognition Result
tempLabel=TEMPORARY tempLabel=TEMPORARY