-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdebugging_canvas_operations.py
More file actions
174 lines (145 loc) · 6.35 KB
/
debugging_canvas_operations.py
File metadata and controls
174 lines (145 loc) · 6.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import cv2
import numpy as np
from PyQt5.QtWidgets import QLabel
from PyQt5.QtGui import QPixmap, QImage, QPainter, QPen, QColor
from PyQt5.QtCore import Qt, QPoint
class AnnotationCanvas(QLabel):
def __init__(self):
super().__init__()
self.setScaledContents(True)
self.annotations = []
self.current_image = None
self.layers = {}
self.current_layer = "default"
self.layers[self.current_layer] = []
def load_image(self, image_path):
image = cv2.imread(image_path)
if image is None:
raise ValueError(f"Could not read image from path: {image_path}")
if len(image.shape) == 2:
h, w = image.shape
qt_image = QImage(image.data, w, h, w, QImage.Format_Grayscale8)
elif len(image.shape) == 3 and image.shape[2] == 3:
h, w, ch = image.shape
bytes_per_line = ch * w
qt_image = QImage(image.data, w, h, bytes_per_line, QImage.Format_BGR888)
else:
raise ValueError("Unsupported image format. Expected grayscale or BGR color format.")
self.current_image = qt_image
pixmap = QPixmap.fromImage(self.current_image)
self.setPixmap(pixmap)
self.adjustSize()
def paintEvent(self, event):
super().paintEvent(event)
if not self.current_image:
return
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
for layer, annotations in self.layers.items():
if layer == self.current_layer: # Only draw the current layer
for annotation in annotations:
try:
self.draw_annotation(painter, annotation)
except ValueError as e:
print(f"Error drawing annotation: {e}")
def draw_annotation(self, painter, annotation):
if "type" not in annotation or "coords" not in annotation:
raise ValueError("Annotation must have 'type' and 'coords' keys.")
annotation_type = annotation["type"]
coords = annotation["coords"]
if annotation_type == "bbox":
self._draw_bbox(painter, coords)
elif annotation_type == "ellipse":
self._draw_ellipse(painter, coords)
elif annotation_type == "cuboid":
self._draw_cuboid(painter, coords)
elif annotation_type == "polygon":
self._draw_polygon(painter, coords)
elif annotation_type == "keypoints":
self._draw_keypoints(painter, coords)
else:
raise ValueError(f"Unsupported annotation type: {annotation_type}")
def _draw_bbox(self, painter, coords):
x, y, w, h = coords
pen = QPen(QColor(0, 255, 0), 2)
painter.setPen(pen)
painter.drawRect(x, y, w, h)
def _draw_ellipse(self, painter, coords):
x, y, w, h = coords
pen = QPen(QColor(255, 0, 0), 2)
painter.setPen(pen)
painter.drawEllipse(x, y, w, h)
def _draw_cuboid(self, painter, coords):
# Example implementation for 3D cuboid drawing
# For simplicity, treating it as a 2D projection
points = [QPoint(*coord) for coord in coords]
pen = QPen(QColor(0, 0, 255), 2)
painter.setPen(pen)
for i in range(len(points)):
painter.drawLine(points[i], points[(i + 1) % len(points)])
def _draw_polygon(self, painter, coords):
points = [QPoint(pt[0], pt[1]) for pt in coords]
pen = QPen(QColor(255, 0, 0), 2)
painter.setPen(pen)
painter.drawPolygon(*points)
def _draw_keypoints(self, painter, coords):
pen = QPen(QColor(0, 0, 255), 2)
painter.setPen(pen)
for pt in coords:
painter.drawEllipse(pt[0] - 2, pt[1] - 2, 4, 4)
def set_annotations(self, annotations):
if not isinstance(annotations, list):
raise ValueError("Annotations must be a list.")
self.layers[self.current_layer] = annotations
self.update()
def get_annotations(self):
return self.layers[self.current_layer]
def add_layer(self, layer_name):
if layer_name in self.layers:
raise ValueError(f"Layer {layer_name} already exists.")
self.layers[layer_name] = []
def switch_layer(self, layer_name):
if layer_name not in self.layers:
raise ValueError(f"Layer {layer_name} does not exist.")
self.current_layer = layer_name
self.update()
def save_template(self, template_name):
# Save current annotations as a template
return {template_name: self.layers[self.current_layer]}
def apply_template(self, template):
# Apply a saved template to the current layer
self.layers[self.current_layer].extend(template)
self.update()
def group_annotations(self, annotation_indices):
# Group selected annotations (example implementation)
grouped_annotations = [self.layers[self.current_layer][i] for i in annotation_indices]
group = {"type": "group", "annotations": grouped_annotations}
self.layers[self.current_layer] = [
anno for i, anno in enumerate(self.layers[self.current_layer]) if i not in annotation_indices
]
self.layers[self.current_layer].append(group)
self.update()
# New Methods for Advanced Annotations
def _draw_polyline(self, painter, coords):
pen = QPen(QColor(0, 255, 255), 2)
painter.setPen(pen)
points = [QPoint(pt[0], pt[1]) for pt in coords]
painter.drawPolyline(*points)
def _draw_segmentation_mask(self, painter, mask):
overlay = QPixmap(self.size())
overlay.fill(Qt.transparent)
mask_painter = QPainter(overlay)
mask_painter.setOpacity(0.5)
mask_painter.fillRect(self.rect(), QColor(0, 255, 0, 127))
mask_painter.end()
painter.drawPixmap(self.rect(), overlay)
def toggle_layer_visibility(self, layer_name):
self.layers[layer_name]['visible'] = not self.layers[layer_name]['visible']
self.update()
def lock_layer(self, layer_name, lock_status=True):
self.layers[layer_name]['locked'] = lock_status
def reorder_layer(self, layer_name, new_index):
keys = list(self.layers.keys())
keys.remove(layer_name)
keys.insert(new_index, layer_name)
self.layers = {key: self.layers[key] for key in keys}