Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

add rectangle select freature #1490

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions labelme/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,14 @@ def __init__(
self.tr("Start drawing rectangles"),
enabled=False,
)
rectangleSelectMode = action(
self.tr("Rectangle Select"),
lambda: self.toggleDrawMode(False, createMode="selrectangle"),
shortcuts["rectangle_select"],
"objects",
self.tr("Start selecting rectangles"),
enabled=False,
)
createCircleMode = action(
self.tr("Create Circle"),
lambda: self.toggleDrawMode(False, createMode="circle"),
Expand Down Expand Up @@ -643,6 +651,7 @@ def __init__(
createMode=createMode,
editMode=editMode,
createRectangleMode=createRectangleMode,
rectangleSelectMode=rectangleSelectMode,
createCircleMode=createCircleMode,
createLineMode=createLineMode,
createPointMode=createPointMode,
Expand Down Expand Up @@ -681,6 +690,7 @@ def __init__(
menu=(
createMode,
createRectangleMode,
rectangleSelectMode,
createCircleMode,
createLineMode,
createPointMode,
Expand Down Expand Up @@ -976,6 +986,7 @@ def setClean(self):
self.actions.createLineStripMode.setEnabled(True)
self.actions.createAiPolygonMode.setEnabled(True)
self.actions.createAiMaskMode.setEnabled(True)
self.actions.createRectangleMode.setEnabled(True)
title = __appname__
if self.filename is not None:
title = "{} - {}".format(title, self.filename)
Expand Down Expand Up @@ -1107,6 +1118,7 @@ def toggleDrawMode(self, edit=True, createMode="polygon"):
draw_actions = {
"polygon": self.actions.createMode,
"rectangle": self.actions.createRectangleMode,
"selrectangle": self.actions.rectangleSelectMode,
"circle": self.actions.createCircleMode,
"point": self.actions.createPointMode,
"line": self.actions.createLineMode,
Expand All @@ -1123,6 +1135,7 @@ def toggleDrawMode(self, edit=True, createMode="polygon"):
else:
for draw_mode, draw_action in draw_actions.items():
draw_action.setEnabled(createMode != draw_mode)
self.actions.rectangleSelectMode.setEnabled(True)
self.actions.editMode.setEnabled(not edit)

def setEditMode(self):
Expand Down
2 changes: 2 additions & 0 deletions labelme/config/default_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ canvas:
linestrip: false
ai_polygon: false
ai_mask: false
selrectangle: false

shortcuts:
close: Ctrl+W
Expand Down Expand Up @@ -118,6 +119,7 @@ shortcuts:
edit_label: Ctrl+E
toggle_keep_prev_mode: Ctrl+P
remove_selected_point: [Meta+H, Backspace]
rectangle_select: null

show_all_polygons: null
hide_all_polygons: null
Expand Down
6 changes: 5 additions & 1 deletion labelme/shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def shape_type(self, value):
"linestrip",
"points",
"mask",
"selrectangle"
]:
raise ValueError("Unexpected shape_type: {}".format(value))
self._shape_type = value
Expand Down Expand Up @@ -217,7 +218,7 @@ def paint(self, painter):
vrtx_path = QtGui.QPainterPath()
negative_vrtx_path = QtGui.QPainterPath()

if self.shape_type in ["rectangle", "mask"]:
if self.shape_type in ["rectangle", "mask","selrectangle"]:
assert len(self.points) in [1, 2]
if len(self.points) == 2:
rectangle = QtCore.QRectF(
Expand All @@ -228,6 +229,9 @@ def paint(self, painter):
if self.shape_type == "rectangle":
for i in range(len(self.points)):
self.drawVertex(vrtx_path, i)
if self.shape_type == "selrectangle":
for i in range(len(self.points)):
self.drawVertex(vrtx_path, i)
elif self.shape_type == "circle":
assert len(self.points) in [1, 2]
if len(self.points) == 2:
Expand Down
47 changes: 41 additions & 6 deletions labelme/widgets/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ def __init__(self, *args, **kwargs):
"linestrip": False,
"ai_polygon": False,
"ai_mask": False,
"selrectangle": False
},
)
super(Canvas, self).__init__(*args, **kwargs)
Expand Down Expand Up @@ -124,6 +125,7 @@ def createMode(self, value):
"linestrip",
"ai_polygon",
"ai_mask",
"selrectangle"
]:
raise ValueError("Unsupported createMode: %s" % value)
self._createMode = value
Expand Down Expand Up @@ -282,6 +284,10 @@ def mouseMoveEvent(self, ev):
self.line.points = [self.current[0], pos]
self.line.point_labels = [1, 1]
self.line.close()
elif self.createMode == "selrectangle":
self.line.points = [self.current[0], pos]
self.line.point_labels = [1, 1]
self.line.close()
elif self.createMode == "circle":
self.line.points = [self.current[0], pos]
self.line.point_labels = [1, 1]
Expand Down Expand Up @@ -418,7 +424,7 @@ def mousePressEvent(self, ev):
self.line[0] = self.current[-1]
if self.current.isClosed():
self.finalise()
elif self.createMode in ["rectangle", "circle", "line"]:
elif self.createMode in ["rectangle", "circle", "line","selrectangle"]:
assert len(self.current.points) == 1
self.current.points = self.line.points
self.finalise()
Expand Down Expand Up @@ -835,11 +841,40 @@ def finalise(self):
)
self.current.close()

self.shapes.append(self.current)
self.storeShapes()
self.current = None
self.setHiding(False)
self.newShape.emit()
# self.shapes.append(self.current)
# self.storeShapes()
# self.current = None
# self.setHiding(False)
# self.newShape.emit()
if self.createMode != "selrectangle": # do not store shape,because it is not a real shape
self.shapes.append(self.current)
self.storeShapes()
self.current = None
self.setHiding(False)
self.newShape.emit()
else:

x1 = self.current.points[0].x()
y1 = self.current.points[0].y()
x2 = self.current.points[1].x()
y2 = self.current.points[1].y()
xMax = max([x1, x2])
yMax = max([y1, y2])
xMin = min([x1, x2])
yMin = min([y1, y2])

for shape in self.shapes:
if shape is None: continue
for pnt in shape.points:
if xMax >= pnt.x() >= xMin and yMax >= pnt.y() >= yMin:
shape.selected = True
self.selectedShapes.append(shape)
break

self.current = None # clear current shape
self.selectionChanged.emit(self.selectedShapes)
self.setEditing(True)

self.update()

def closeEnough(self, p1, p2):
Expand Down