feature: draw square bounding boxes
This commit is contained in:
parent
5abf660222
commit
4e278bb511
26
labelImg.py
26
labelImg.py
@ -184,6 +184,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
|
|
||||||
self.canvas = Canvas(parent=self)
|
self.canvas = Canvas(parent=self)
|
||||||
self.canvas.zoomRequest.connect(self.zoomRequest)
|
self.canvas.zoomRequest.connect(self.zoomRequest)
|
||||||
|
self.canvas.setDrawingShapeToSquare(settings.get(SETTING_DRAW_SQUARE, False))
|
||||||
|
|
||||||
scroll = QScrollArea()
|
scroll = QScrollArea()
|
||||||
scroll.setWidget(self.canvas)
|
scroll.setWidget(self.canvas)
|
||||||
@ -332,6 +333,13 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
self.labelList.customContextMenuRequested.connect(
|
self.labelList.customContextMenuRequested.connect(
|
||||||
self.popLabelListMenu)
|
self.popLabelListMenu)
|
||||||
|
|
||||||
|
# Draw squares/rectangles
|
||||||
|
self.drawSquaresOption = QAction('Draw Squares', self)
|
||||||
|
self.drawSquaresOption.setShortcut('Ctrl+Shift+R')
|
||||||
|
self.drawSquaresOption.setCheckable(True)
|
||||||
|
self.drawSquaresOption.setChecked(settings.get(SETTING_DRAW_SQUARE, False))
|
||||||
|
self.drawSquaresOption.triggered.connect(self.toogleDrawSquare)
|
||||||
|
|
||||||
# Store actions for further handling.
|
# Store actions for further handling.
|
||||||
self.actions = struct(save=save, save_format=save_format, saveAs=saveAs, open=open, close=close, resetAll = resetAll,
|
self.actions = struct(save=save, save_format=save_format, saveAs=saveAs, open=open, close=close, resetAll = resetAll,
|
||||||
lineColor=color1, create=create, delete=delete, edit=edit, copy=copy,
|
lineColor=color1, create=create, delete=delete, edit=edit, copy=copy,
|
||||||
@ -344,7 +352,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
open, opendir, save, saveAs, close, resetAll, quit),
|
open, opendir, save, saveAs, close, resetAll, quit),
|
||||||
beginner=(), advanced=(),
|
beginner=(), advanced=(),
|
||||||
editMenu=(edit, copy, delete,
|
editMenu=(edit, copy, delete,
|
||||||
None, color1),
|
None, color1, self.drawSquaresOption),
|
||||||
beginnerContext=(create, edit, copy, delete),
|
beginnerContext=(create, edit, copy, delete),
|
||||||
advancedContext=(createMode, editMode, edit, copy,
|
advancedContext=(createMode, editMode, edit, copy,
|
||||||
delete, shapeLineColor, shapeFillColor),
|
delete, shapeLineColor, shapeFillColor),
|
||||||
@ -480,6 +488,15 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
if self.filePath and os.path.isdir(self.filePath):
|
if self.filePath and os.path.isdir(self.filePath):
|
||||||
self.openDirDialog(dirpath=self.filePath)
|
self.openDirDialog(dirpath=self.filePath)
|
||||||
|
|
||||||
|
def keyReleaseEvent(self, event):
|
||||||
|
if event.key() == Qt.Key_Control:
|
||||||
|
self.canvas.setDrawingShapeToSquare(False)
|
||||||
|
|
||||||
|
def keyPressEvent(self, event):
|
||||||
|
if event.key() == Qt.Key_Control:
|
||||||
|
# Draw rectangle if Ctrl is pressed
|
||||||
|
self.canvas.setDrawingShapeToSquare(True)
|
||||||
|
|
||||||
## Support Functions ##
|
## Support Functions ##
|
||||||
def set_format(self, save_format):
|
def set_format(self, save_format):
|
||||||
if save_format == FORMAT_PASCALVOC:
|
if save_format == FORMAT_PASCALVOC:
|
||||||
@ -1099,6 +1116,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
settings[SETTING_AUTO_SAVE] = self.autoSaving.isChecked()
|
settings[SETTING_AUTO_SAVE] = self.autoSaving.isChecked()
|
||||||
settings[SETTING_SINGLE_CLASS] = self.singleClassMode.isChecked()
|
settings[SETTING_SINGLE_CLASS] = self.singleClassMode.isChecked()
|
||||||
settings[SETTING_PAINT_LABEL] = self.paintLabelsOption.isChecked()
|
settings[SETTING_PAINT_LABEL] = self.paintLabelsOption.isChecked()
|
||||||
|
settings[SETTING_DRAW_SQUARE] = self.drawSquaresOption.isChecked()
|
||||||
settings.save()
|
settings.save()
|
||||||
## User Dialogs ##
|
## User Dialogs ##
|
||||||
|
|
||||||
@ -1171,6 +1189,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
if not self.mayContinue() or not dirpath:
|
if not self.mayContinue() or not dirpath:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
self.lastOpenDir = dirpath
|
self.lastOpenDir = dirpath
|
||||||
self.dirname = dirpath
|
self.dirname = dirpath
|
||||||
self.filePath = None
|
self.filePath = None
|
||||||
@ -1183,7 +1202,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
|
|
||||||
def verifyImg(self, _value=False):
|
def verifyImg(self, _value=False):
|
||||||
# Proceding next image without dialog if having any label
|
# Proceding next image without dialog if having any label
|
||||||
if self.filePath is not None:
|
if self.filePath is not None:
|
||||||
try:
|
try:
|
||||||
self.labelFile.toggleVerify()
|
self.labelFile.toggleVerify()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@ -1416,6 +1435,9 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||||||
for shape in self.canvas.shapes:
|
for shape in self.canvas.shapes:
|
||||||
shape.paintLabel = paintLabelsOptionChecked
|
shape.paintLabel = paintLabelsOptionChecked
|
||||||
|
|
||||||
|
def toogleDrawSquare(self):
|
||||||
|
self.canvas.setDrawingShapeToSquare(self.drawSquaresOption.isChecked())
|
||||||
|
|
||||||
def inverted(color):
|
def inverted(color):
|
||||||
return QColor(*[255 - v for v in color.getRgb()])
|
return QColor(*[255 - v for v in color.getRgb()])
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,7 @@ class Canvas(QWidget):
|
|||||||
self.setMouseTracking(True)
|
self.setMouseTracking(True)
|
||||||
self.setFocusPolicy(Qt.WheelFocus)
|
self.setFocusPolicy(Qt.WheelFocus)
|
||||||
self.verified = False
|
self.verified = False
|
||||||
|
self.drawSquare = False
|
||||||
|
|
||||||
def setDrawingColor(self, qColor):
|
def setDrawingColor(self, qColor):
|
||||||
self.drawingLineColor = qColor
|
self.drawingLineColor = qColor
|
||||||
@ -126,7 +127,18 @@ class Canvas(QWidget):
|
|||||||
color = self.current.line_color
|
color = self.current.line_color
|
||||||
self.overrideCursor(CURSOR_POINT)
|
self.overrideCursor(CURSOR_POINT)
|
||||||
self.current.highlightVertex(0, Shape.NEAR_VERTEX)
|
self.current.highlightVertex(0, Shape.NEAR_VERTEX)
|
||||||
self.line[1] = pos
|
|
||||||
|
if self.drawSquare:
|
||||||
|
initPos = self.current[0]
|
||||||
|
minX = initPos.x()
|
||||||
|
minY = initPos.y()
|
||||||
|
min_size = min(abs(pos.x() - minX), abs(pos.y() - minY))
|
||||||
|
directionX = -1 if pos.x() - minX < 0 else 1
|
||||||
|
directionY = -1 if pos.y() - minY < 0 else 1
|
||||||
|
self.line[1] = QPointF(minX + directionX * min_size, minY + directionY * min_size)
|
||||||
|
else:
|
||||||
|
self.line[1] = pos
|
||||||
|
|
||||||
self.line.line_color = color
|
self.line.line_color = color
|
||||||
self.prevPoint = QPointF()
|
self.prevPoint = QPointF()
|
||||||
self.current.highlightClear()
|
self.current.highlightClear()
|
||||||
@ -320,7 +332,18 @@ class Canvas(QWidget):
|
|||||||
if self.outOfPixmap(pos):
|
if self.outOfPixmap(pos):
|
||||||
pos = self.intersectionPoint(point, pos)
|
pos = self.intersectionPoint(point, pos)
|
||||||
|
|
||||||
shiftPos = pos - point
|
if self.drawSquare:
|
||||||
|
opposite_point_index = (index + 2) % 4
|
||||||
|
opposite_point = shape[opposite_point_index]
|
||||||
|
|
||||||
|
min_size = min(abs(pos.x() - opposite_point.x()), abs(pos.y() - opposite_point.y()))
|
||||||
|
directionX = -1 if pos.x() - opposite_point.x() < 0 else 1
|
||||||
|
directionY = -1 if pos.y() - opposite_point.y() < 0 else 1
|
||||||
|
shiftPos = QPointF(opposite_point.x() + directionX * min_size - point.x(),
|
||||||
|
opposite_point.y() + directionY * min_size - point.y())
|
||||||
|
else:
|
||||||
|
shiftPos = pos - point
|
||||||
|
|
||||||
shape.moveVertexBy(index, shiftPos)
|
shape.moveVertexBy(index, shiftPos)
|
||||||
|
|
||||||
lindex = (index + 1) % 4
|
lindex = (index + 1) % 4
|
||||||
@ -678,3 +701,6 @@ class Canvas(QWidget):
|
|||||||
self.restoreCursor()
|
self.restoreCursor()
|
||||||
self.pixmap = None
|
self.pixmap = None
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
def setDrawingShapeToSquare(self, status):
|
||||||
|
self.drawSquare = status
|
||||||
|
|||||||
@ -14,3 +14,4 @@ SETTING_AUTO_SAVE = 'autosave'
|
|||||||
SETTING_SINGLE_CLASS = 'singleclass'
|
SETTING_SINGLE_CLASS = 'singleclass'
|
||||||
FORMAT_PASCALVOC='PascalVOC'
|
FORMAT_PASCALVOC='PascalVOC'
|
||||||
FORMAT_YOLO='YOLO'
|
FORMAT_YOLO='YOLO'
|
||||||
|
SETTING_DRAW_SQUARE = 'draw/square'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user