Fixing bounding box drawing
This commit is contained in:
@@ -90,6 +90,10 @@ class AnnotationTab(QWidget):
|
||||
self.annotation_tools.polyline_pen_width_changed.connect(
|
||||
self.annotation_canvas.set_polyline_pen_width
|
||||
)
|
||||
# Show / hide bounding boxes
|
||||
self.annotation_tools.show_bboxes_changed.connect(
|
||||
self.annotation_canvas.set_show_bboxes
|
||||
)
|
||||
# RDP simplification controls
|
||||
self.annotation_tools.simplify_on_finish_changed.connect(
|
||||
self._on_simplify_on_finish_changed
|
||||
|
||||
@@ -146,12 +146,17 @@ class AnnotationCanvasWidget(QWidget):
|
||||
self.polyline_enabled = False
|
||||
self.polyline_pen_color = QColor(255, 0, 0, 128) # Default red with 50% alpha
|
||||
self.polyline_pen_width = 3
|
||||
self.show_bboxes: bool = True # Control visibility of bounding boxes
|
||||
|
||||
# Current stroke and stored polylines (in image coordinates, pixel units)
|
||||
self.current_stroke: List[Tuple[float, float]] = []
|
||||
self.polylines: List[List[Tuple[float, float]]] = []
|
||||
self.stroke_meta: List[Dict[str, Any]] = [] # per-polyline style (color, width)
|
||||
|
||||
# Stored bounding boxes in normalized coordinates (x_min, y_min, x_max, y_max)
|
||||
self.bboxes: List[List[float]] = []
|
||||
self.bbox_meta: List[Dict[str, Any]] = [] # per-bbox style (color, width)
|
||||
|
||||
# Legacy collection of strokes in normalized coordinates (kept for API compatibility)
|
||||
self.all_strokes: List[dict] = []
|
||||
|
||||
@@ -219,6 +224,8 @@ class AnnotationCanvasWidget(QWidget):
|
||||
self.current_stroke = []
|
||||
self.polylines = []
|
||||
self.stroke_meta = []
|
||||
self.bboxes = []
|
||||
self.bbox_meta = []
|
||||
self.is_drawing = False
|
||||
if self.annotation_pixmap:
|
||||
self.annotation_pixmap.fill(Qt.transparent)
|
||||
@@ -406,7 +413,7 @@ class AnnotationCanvasWidget(QWidget):
|
||||
self._redraw_annotations()
|
||||
|
||||
def _redraw_annotations(self):
|
||||
"""Redraw all stored polylines onto the annotation pixmap."""
|
||||
"""Redraw all stored polylines and (optionally) bounding boxes onto the annotation pixmap."""
|
||||
if self.annotation_pixmap is None:
|
||||
return
|
||||
|
||||
@@ -414,6 +421,8 @@ class AnnotationCanvasWidget(QWidget):
|
||||
self.annotation_pixmap.fill(Qt.transparent)
|
||||
|
||||
painter = QPainter(self.annotation_pixmap)
|
||||
|
||||
# Draw polylines
|
||||
for polyline, meta in zip(self.polylines, self.stroke_meta):
|
||||
pen_color: QColor = meta.get("color", self.polyline_pen_color)
|
||||
width: int = meta.get("width", self.polyline_pen_width)
|
||||
@@ -427,6 +436,37 @@ class AnnotationCanvasWidget(QWidget):
|
||||
painter.setPen(pen)
|
||||
for (x1, y1), (x2, y2) in zip(polyline[:-1], polyline[1:]):
|
||||
painter.drawLine(int(x1), int(y1), int(x2), int(y2))
|
||||
|
||||
# Draw bounding boxes (dashed) if enabled
|
||||
if self.show_bboxes and self.original_pixmap is not None and self.bboxes:
|
||||
img_width = float(self.original_pixmap.width())
|
||||
img_height = float(self.original_pixmap.height())
|
||||
|
||||
for bbox, meta in zip(self.bboxes, self.bbox_meta):
|
||||
if len(bbox) != 4:
|
||||
continue
|
||||
|
||||
x_min_norm, y_min_norm, x_max_norm, y_max_norm = bbox
|
||||
x_min = int(x_min_norm * img_width)
|
||||
y_min = int(y_min_norm * img_height)
|
||||
x_max = int(x_max_norm * img_width)
|
||||
y_max = int(y_max_norm * img_height)
|
||||
|
||||
rect_width = x_max - x_min
|
||||
rect_height = y_max - y_min
|
||||
|
||||
pen_color: QColor = meta.get("color", QColor(255, 0, 0, 128))
|
||||
width: int = meta.get("width", self.polyline_pen_width)
|
||||
pen = QPen(
|
||||
pen_color,
|
||||
width,
|
||||
Qt.DashLine,
|
||||
Qt.SquareCap,
|
||||
Qt.MiterJoin,
|
||||
)
|
||||
painter.setPen(pen)
|
||||
painter.drawRect(x_min, y_min, rect_width, rect_height)
|
||||
|
||||
painter.end()
|
||||
|
||||
self._update_display()
|
||||
@@ -647,7 +687,7 @@ class AnnotationCanvasWidget(QWidget):
|
||||
Draw a bounding box from database coordinates onto the annotation canvas.
|
||||
|
||||
Args:
|
||||
bbox: Bounding box as [y_min_norm, x_min_norm, y_max_norm, x_max_norm]
|
||||
bbox: Bounding box as [x_min_norm, y_min_norm, x_max_norm, y_max_norm]
|
||||
in normalized coordinates (0-1)
|
||||
color: Color hex string (e.g., '#FF0000')
|
||||
width: Line width in pixels
|
||||
@@ -662,8 +702,7 @@ class AnnotationCanvasWidget(QWidget):
|
||||
)
|
||||
return
|
||||
|
||||
# Convert normalized coordinates to image coordinates
|
||||
# bbox format: [y_min_norm, x_min_norm, y_max_norm, x_max_norm]
|
||||
# Convert normalized coordinates to image coordinates (for logging/debug)
|
||||
img_width = self.original_pixmap.width()
|
||||
img_height = self.original_pixmap.height()
|
||||
|
||||
@@ -677,29 +716,35 @@ class AnnotationCanvasWidget(QWidget):
|
||||
logger.debug(f" Image size: {img_width}x{img_height}")
|
||||
logger.debug(f" Pixel coords: ({x_min}, {y_min}) to ({x_max}, {y_max})")
|
||||
|
||||
# Draw bounding box on annotation pixmap
|
||||
painter = QPainter(self.annotation_pixmap)
|
||||
# Store bounding box (normalized) and its style; actual drawing happens
|
||||
# in _redraw_annotations() together with all polylines.
|
||||
pen_color = QColor(color)
|
||||
pen_color.setAlpha(128) # Add semi-transparency
|
||||
pen = QPen(pen_color, width, Qt.SolidLine, Qt.SquareCap, Qt.MiterJoin)
|
||||
painter.setPen(pen)
|
||||
|
||||
# Draw rectangle
|
||||
rect_width = x_max - x_min
|
||||
rect_height = y_max - y_min
|
||||
painter.drawRect(x_min, y_min, rect_width, rect_height)
|
||||
|
||||
painter.end()
|
||||
self.bboxes.append(
|
||||
[float(x_min_norm), float(y_min_norm), float(x_max_norm), float(y_max_norm)]
|
||||
)
|
||||
self.bbox_meta.append({"color": pen_color, "width": int(width)})
|
||||
|
||||
# Store in all_strokes for consistency
|
||||
self.all_strokes.append(
|
||||
{"bbox": bbox, "color": color, "alpha": 128, "width": width}
|
||||
)
|
||||
|
||||
# Update display
|
||||
self._update_display()
|
||||
# Redraw overlay (polylines + all bounding boxes)
|
||||
self._redraw_annotations()
|
||||
logger.debug(f"Drew saved bounding box in color {color}")
|
||||
|
||||
def set_show_bboxes(self, show: bool):
|
||||
"""
|
||||
Enable or disable drawing of bounding boxes.
|
||||
|
||||
Args:
|
||||
show: If True, draw bounding boxes; if False, hide them.
|
||||
"""
|
||||
self.show_bboxes = bool(show)
|
||||
logger.debug(f"Set show_bboxes to {self.show_bboxes}")
|
||||
self._redraw_annotations()
|
||||
|
||||
def keyPressEvent(self, event: QKeyEvent):
|
||||
"""Handle keyboard events for zooming."""
|
||||
if event.key() in (Qt.Key_Plus, Qt.Key_Equal):
|
||||
|
||||
@@ -53,6 +53,8 @@ class AnnotationToolsWidget(QWidget):
|
||||
polyline_pen_width_changed = Signal(int)
|
||||
simplify_on_finish_changed = Signal(bool)
|
||||
simplify_epsilon_changed = Signal(float)
|
||||
# Toggle visibility of bounding boxes on the canvas
|
||||
show_bboxes_changed = Signal(bool)
|
||||
class_selected = Signal(dict)
|
||||
class_color_changed = Signal()
|
||||
clear_annotations_requested = Signal()
|
||||
@@ -170,6 +172,12 @@ class AnnotationToolsWidget(QWidget):
|
||||
actions_group = QGroupBox("Actions")
|
||||
actions_layout = QVBoxLayout()
|
||||
|
||||
# Show / hide bounding boxes
|
||||
self.show_bboxes_checkbox = QCheckBox("Show bounding boxes")
|
||||
self.show_bboxes_checkbox.setChecked(True)
|
||||
self.show_bboxes_checkbox.stateChanged.connect(self._on_show_bboxes_toggle)
|
||||
actions_layout.addWidget(self.show_bboxes_checkbox)
|
||||
|
||||
self.clear_btn = QPushButton("Clear All Annotations")
|
||||
self.clear_btn.clicked.connect(self._on_clear_annotations)
|
||||
actions_layout.addWidget(self.clear_btn)
|
||||
@@ -219,12 +227,12 @@ class AnnotationToolsWidget(QWidget):
|
||||
self.polyline_enabled = checked
|
||||
|
||||
if checked:
|
||||
self.polyline_toggle_btn.setText("Start Drawing Polyline")
|
||||
self.polyline_toggle_btn.setText("Stop Drawing Polyline")
|
||||
self.polyline_toggle_btn.setStyleSheet(
|
||||
"QPushButton { background-color: #4CAF50; }"
|
||||
)
|
||||
else:
|
||||
self.polyline_toggle_btn.setText("Stop drawing Polyline")
|
||||
self.polyline_toggle_btn.setText("Start Drawing Polyline")
|
||||
self.polyline_toggle_btn.setStyleSheet("")
|
||||
|
||||
self.polyline_enabled_changed.emit(self.polyline_enabled)
|
||||
@@ -247,6 +255,12 @@ class AnnotationToolsWidget(QWidget):
|
||||
self.simplify_epsilon_changed.emit(epsilon)
|
||||
logger.debug(f"Simplification epsilon changed to {epsilon}")
|
||||
|
||||
def _on_show_bboxes_toggle(self, state: int):
|
||||
"""Handle 'Show bounding boxes' checkbox toggle."""
|
||||
show = bool(state)
|
||||
self.show_bboxes_changed.emit(show)
|
||||
logger.debug(f"Show bounding boxes set to {show}")
|
||||
|
||||
def _on_color_picker(self):
|
||||
"""Open color picker dialog and update the selected object's class color."""
|
||||
if not self.current_class:
|
||||
|
||||
Reference in New Issue
Block a user