jebin2 commited on
Commit
4e78057
·
1 Parent(s): efc9b5d

dyn annota mode

Browse files
comic_panel_extractor/static/annotator.html CHANGED
@@ -655,6 +655,12 @@
655
  this.edgeResizeTolerance = 8;
656
  this.showEdgeHandles = true;
657
 
 
 
 
 
 
 
658
  this.init();
659
  }
660
 
@@ -851,6 +857,7 @@
851
  if (index === this.selectedBoxIndex) {
852
  strokeColor = '#0066ff';
853
  fillColor = 'rgba(0, 102, 255, 0.3)';
 
854
  } else if (!annotation.saved) {
855
  strokeColor = '#ff0000';
856
  fillColor = 'rgba(255, 0, 0, 0.2)';
@@ -1160,9 +1167,12 @@
1160
  this.lastMouseY = pos.y;
1161
  const handle = this.getResizeHandle(pos.x, pos.y);
1162
 
1163
- if (this.annotationMode === 'segmentation') {
1164
- // Check if clicking on an edge handle of selected polygon
1165
- if (this.selectedBoxIndex >= 0) {
 
 
 
1166
  const edgeHandleIndex = this.getEdgeHandleAtPosition(pos.x, pos.y);
1167
  if (edgeHandleIndex >= 0) {
1168
  this.isDraggingEdge = true;
@@ -1179,58 +1189,56 @@
1179
  return;
1180
  }
1181
 
1182
- // Check if clicking on an edge to add a point
1183
  const edgeIndex = this.getPolygonEdgeAtPosition(pos.x, pos.y);
1184
  if (edgeIndex >= 0 && e.ctrlKey) {
1185
  this.addPolygonPoint(this.selectedBoxIndex, edgeIndex, pos.x, pos.y);
1186
  this.drawCanvas();
1187
  return;
1188
  }
1189
- }
 
 
 
 
 
 
 
1190
 
1191
- // Check if clicking on a polygon
1192
- const clickedPolygonIndex = this.getPolygonAtPosition(pos.x, pos.y);
1193
- if (clickedPolygonIndex >= 0) {
1194
- this.selectedBoxIndex = clickedPolygonIndex;
1195
- this.isDragging = true;
1196
- this.dragStartX = pos.x;
1197
- this.dragStartY = pos.y;
1198
- this.canvas.style.cursor = handle.cursor;
1199
- this.updateSelectedBoxInfo();
1200
- this.drawCanvas();
1201
- return;
1202
  }
 
1203
 
1204
- // Start new polygon if not drawing one
1205
- if (!this.isDrawingPolygon) {
1206
- this.selectedBoxIndex = -1;
1207
- this.isDrawingPolygon = true;
1208
- this.polygonPoints = [pos];
1209
- this.currentPolygon = {
1210
- points: [...this.polygonPoints],
1211
- classId: parseInt(document.getElementById('classId').value) || 0,
1212
- saved: false
1213
- };
1214
- } else {
1215
- // Add point to current polygon
1216
- this.polygonPoints.push(pos);
1217
- this.currentPolygon.points = [...this.polygonPoints];
1218
- }
1219
  this.drawCanvas();
1220
  return;
1221
  }
1222
 
1223
- // Original bbox logic remains the same...
1224
- if (this.selectedBoxIndex >= 0) {
1225
- if (handle) {
1226
- this.isResizing = true;
1227
- this.resizeHandle = handle;
1228
- this.canvas.style.cursor = handle.cursor;
1229
- return;
1230
- }
 
 
 
 
 
1231
  }
1232
 
1233
- const clickedBoxIndex = this.getBoxAtPosition(pos.x, pos.y);
1234
  if (clickedBoxIndex >= 0) {
1235
  this.selectedBoxIndex = clickedBoxIndex;
1236
  this.isDragging = true;
@@ -1242,12 +1250,92 @@
1242
  return;
1243
  }
1244
 
 
1245
  this.selectedBoxIndex = -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1246
  this.startX = pos.x;
1247
  this.startY = pos.y;
1248
  this.isDrawing = true;
1249
  this.currentBox = { left: this.startX, top: this.startY, width: 0, height: 0 };
1250
- this.updateSelectedBoxInfo();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1251
  }
1252
 
1253
  onDoubleClick(e) {
@@ -1283,23 +1371,51 @@
1283
 
1284
  const pos = this.getMousePos(e);
1285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1286
  if (this.annotationMode === 'segmentation') {
1287
  if (this.isDraggingEdge && this.selectedBoxIndex >= 0) {
1288
- // Resize edge
1289
  this.resizePolygonEdge(this.selectedBoxIndex, this.draggingEdgeIndex, pos.x, pos.y);
1290
  this.drawCanvas();
1291
  return;
1292
  }
1293
 
1294
  if (this.isDraggingPoint && this.selectedBoxIndex >= 0) {
1295
- // Move individual point
1296
  this.movePolygonPoint(this.selectedBoxIndex, this.draggingPointIndex, pos.x, pos.y);
1297
  this.drawCanvas();
1298
  return;
1299
  }
1300
 
1301
  if (this.isDragging && this.selectedBoxIndex >= 0) {
1302
- // Move entire polygon
1303
  const deltaX = pos.x - this.lastMouseX;
1304
  const deltaY = pos.y - this.lastMouseY;
1305
  this.movePolygon(this.selectedBoxIndex, deltaX, deltaY);
@@ -1310,7 +1426,6 @@
1310
  }
1311
 
1312
  if (this.isDrawingPolygon) {
1313
- // Update current polygon preview
1314
  if (this.currentPolygon) {
1315
  this.currentPolygon.points = [...this.polygonPoints, pos];
1316
  this.drawCanvas();
@@ -1318,7 +1433,6 @@
1318
  return;
1319
  }
1320
 
1321
- // Update cursor based on what's under mouse
1322
  this.updatePolygonCursor(pos.x, pos.y);
1323
  return;
1324
  }
@@ -1343,7 +1457,17 @@
1343
  }
1344
  }
1345
 
 
1346
  onMouseUp() {
 
 
 
 
 
 
 
 
 
1347
  if (this.annotationMode === 'segmentation') {
1348
  this.isDraggingEdge = false;
1349
  this.draggingEdgeIndex = -1;
@@ -1394,6 +1518,7 @@
1394
  this.canvas.style.cursor = 'crosshair';
1395
  this.drawCanvas();
1396
  }
 
1397
  updatePolygonCursor(x, y) {
1398
  if (this.selectedBoxIndex >= 0 && this.annotations[this.selectedBoxIndex].type === 'segmentation') {
1399
  const handle = this.getResizeHandle(x, y);
@@ -1414,10 +1539,8 @@
1414
  updateCursor(x, y) {
1415
  if (this.selectedBoxIndex >= 0) {
1416
  const handle = this.getResizeHandle(x, y);
1417
- if (handle) {
1418
- this.canvas.style.cursor = handle.cursor;
1419
- return;
1420
- }
1421
  }
1422
 
1423
  const boxIndex = this.getBoxAtPosition(x, y);
@@ -1481,7 +1604,13 @@
1481
  return handle;
1482
  }
1483
  }
1484
- return { cursor: 'move' };
 
 
 
 
 
 
1485
  }
1486
 
1487
  getPolygonCornerResizeCursor(pointIndex, points) {
 
655
  this.edgeResizeTolerance = 8;
656
  this.showEdgeHandles = true;
657
 
658
+ // Dynamic annotation detection
659
+ this.waitingForDrag = false;
660
+ this.initialClickPos = null;
661
+ this.clickStartTime = 0;
662
+ this.modeIndicatorTimeout = null;
663
+
664
  this.init();
665
  }
666
 
 
857
  if (index === this.selectedBoxIndex) {
858
  strokeColor = '#0066ff';
859
  fillColor = 'rgba(0, 102, 255, 0.3)';
860
+ this.setAnnotationMode(annotation.type);
861
  } else if (!annotation.saved) {
862
  strokeColor = '#ff0000';
863
  fillColor = 'rgba(255, 0, 0, 0.2)';
 
1167
  this.lastMouseY = pos.y;
1168
  const handle = this.getResizeHandle(pos.x, pos.y);
1169
 
1170
+ // Check for existing annotation interactions first (both types)
1171
+ if (this.selectedBoxIndex >= 0) {
1172
+ const annotation = this.annotations[this.selectedBoxIndex];
1173
+
1174
+ if (annotation.type === 'segmentation') {
1175
+ // Handle segmentation interactions
1176
  const edgeHandleIndex = this.getEdgeHandleAtPosition(pos.x, pos.y);
1177
  if (edgeHandleIndex >= 0) {
1178
  this.isDraggingEdge = true;
 
1189
  return;
1190
  }
1191
 
 
1192
  const edgeIndex = this.getPolygonEdgeAtPosition(pos.x, pos.y);
1193
  if (edgeIndex >= 0 && e.ctrlKey) {
1194
  this.addPolygonPoint(this.selectedBoxIndex, edgeIndex, pos.x, pos.y);
1195
  this.drawCanvas();
1196
  return;
1197
  }
1198
+ } else if (annotation.type === 'bbox') {
1199
+ // If clicking on a resize handle
1200
+ if (handle && handle.type !== 'default' && handle.type !== 'interior') {
1201
+ this.isResizing = true;
1202
+ this.resizeHandle = handle;
1203
+ this.canvas.style.cursor = handle.cursor;
1204
+ return;
1205
+ }
1206
 
1207
+ // If clicking inside bbox (for moving)
1208
+ if (handle && handle.type === 'interior') {
1209
+ this.isDragging = true;
1210
+ this.dragStartX = pos.x;
1211
+ this.dragStartY = pos.y;
1212
+ this.canvas.style.cursor = 'move';
1213
+ this.updateSelectedBoxInfo();
1214
+ return;
1215
+ }
 
 
1216
  }
1217
+ }
1218
 
1219
+ // IMPORTANT: Check if already drawing a polygon - add point to current polygon
1220
+ if (this.annotationMode === 'segmentation' && this.isDrawingPolygon) {
1221
+ this.polygonPoints.push(pos);
1222
+ this.currentPolygon.points = [...this.polygonPoints];
 
 
 
 
 
 
 
 
 
 
 
1223
  this.drawCanvas();
1224
  return;
1225
  }
1226
 
1227
+ // Check for clicking on existing annotations
1228
+ const clickedPolygonIndex = this.getPolygonAtPosition(pos.x, pos.y);
1229
+ const clickedBoxIndex = this.getBoxAtPosition(pos.x, pos.y);
1230
+
1231
+ if (clickedPolygonIndex >= 0) {
1232
+ this.selectedBoxIndex = clickedPolygonIndex;
1233
+ this.isDragging = true;
1234
+ this.dragStartX = pos.x;
1235
+ this.dragStartY = pos.y;
1236
+ this.canvas.style.cursor = handle.cursor;
1237
+ this.updateSelectedBoxInfo();
1238
+ this.drawCanvas();
1239
+ return;
1240
  }
1241
 
 
1242
  if (clickedBoxIndex >= 0) {
1243
  this.selectedBoxIndex = clickedBoxIndex;
1244
  this.isDragging = true;
 
1250
  return;
1251
  }
1252
 
1253
+ // No existing annotation clicked - determine new annotation type
1254
  this.selectedBoxIndex = -1;
1255
+ this.updateSelectedBoxInfo();
1256
+
1257
+ // DYNAMIC ANNOTATION TYPE DETECTION (only when not already drawing)
1258
+ if (e.ctrlKey) {
1259
+ // Ctrl+Click always starts segmentation
1260
+ this.startSegmentation(pos);
1261
+ } else if (e.shiftKey) {
1262
+ // Shift+Click always starts bbox
1263
+ this.startBboxDrawing(pos);
1264
+ } else {
1265
+ // Default behavior: start with a click and wait for drag
1266
+ this.waitingForDrag = true;
1267
+ this.initialClickPos = pos;
1268
+ this.clickStartTime = Date.now();
1269
+ }
1270
+ }
1271
+
1272
+
1273
+ startSegmentation(pos) {
1274
+ this.setAnnotationMode('segmentation');
1275
+ this.isDrawingPolygon = true;
1276
+ this.polygonPoints = [pos];
1277
+ this.currentPolygon = {
1278
+ points: [...this.polygonPoints],
1279
+ classId: parseInt(document.getElementById('classId').value) || 0,
1280
+ saved: false
1281
+ };
1282
+ this.drawCanvas();
1283
+ this.showModeIndicator('Segmentation Mode', 'segmentation');
1284
+ }
1285
+
1286
+ startBboxDrawing(pos) {
1287
+ this.setAnnotationMode('bbox');
1288
  this.startX = pos.x;
1289
  this.startY = pos.y;
1290
  this.isDrawing = true;
1291
  this.currentBox = { left: this.startX, top: this.startY, width: 0, height: 0 };
1292
+ this.showModeIndicator('Bounding Box Mode', 'bbox');
1293
+ }
1294
+
1295
+ setAnnotationMode(mode) {
1296
+ this.annotationMode = mode;
1297
+ document.getElementById('annotationMode').value = mode;
1298
+ this.updateCanvasCursor();
1299
+ }
1300
+
1301
+ showModeIndicator(text, type) {
1302
+ // Create or update mode indicator
1303
+ let indicator = document.getElementById('modeIndicator');
1304
+ if (!indicator) {
1305
+ indicator = document.createElement('div');
1306
+ indicator.id = 'modeIndicator';
1307
+ indicator.style.cssText = `
1308
+ position: fixed;
1309
+ top: 120px;
1310
+ right: 20px;
1311
+ z-index: 1001;
1312
+ padding: 8px 16px;
1313
+ border-radius: 6px;
1314
+ font-size: 13px;
1315
+ font-weight: 500;
1316
+ pointer-events: none;
1317
+ transition: opacity 0.3s ease;
1318
+ `;
1319
+ document.body.appendChild(indicator);
1320
+ }
1321
+
1322
+ const colors = {
1323
+ 'segmentation': { bg: '#e6f3ff', color: '#0066cc', border: '#4299e1' },
1324
+ 'bbox': { bg: '#f0fff4', color: '#22543d', border: '#48bb78' }
1325
+ };
1326
+
1327
+ const color = colors[type] || colors.bbox;
1328
+ indicator.style.background = color.bg;
1329
+ indicator.style.color = color.color;
1330
+ indicator.style.border = `1px solid ${color.border}`;
1331
+ indicator.textContent = text;
1332
+ indicator.style.opacity = '1';
1333
+
1334
+ // Auto-hide after 2 seconds
1335
+ clearTimeout(this.modeIndicatorTimeout);
1336
+ this.modeIndicatorTimeout = setTimeout(() => {
1337
+ indicator.style.opacity = '0';
1338
+ }, 2000);
1339
  }
1340
 
1341
  onDoubleClick(e) {
 
1371
 
1372
  const pos = this.getMousePos(e);
1373
 
1374
+ // Handle dynamic annotation type detection
1375
+ if (this.waitingForDrag && this.initialClickPos) {
1376
+ const dragDistance = Math.sqrt(
1377
+ Math.pow(pos.x - this.initialClickPos.x, 2) +
1378
+ Math.pow(pos.y - this.initialClickPos.y, 2)
1379
+ );
1380
+
1381
+ const timeSinceClick = Date.now() - this.clickStartTime;
1382
+
1383
+ // If dragging more than 10 pixels, assume bbox
1384
+ if (dragDistance > 10) {
1385
+ this.waitingForDrag = false;
1386
+ this.startBboxDrawing(this.initialClickPos);
1387
+ // Continue with bbox drawing
1388
+ this.currentBox.width = pos.x - this.startX;
1389
+ this.currentBox.height = pos.y - this.startY;
1390
+ this.drawCanvas();
1391
+ return;
1392
+ }
1393
+
1394
+ // If holding click for more than 500ms without drag, assume segmentation
1395
+ if (timeSinceClick > 500) {
1396
+ this.waitingForDrag = false;
1397
+ this.startSegmentation(this.initialClickPos);
1398
+ return;
1399
+ }
1400
+
1401
+ return; // Still waiting to determine type
1402
+ }
1403
+
1404
+ // Rest of your existing mouse move logic...
1405
  if (this.annotationMode === 'segmentation') {
1406
  if (this.isDraggingEdge && this.selectedBoxIndex >= 0) {
 
1407
  this.resizePolygonEdge(this.selectedBoxIndex, this.draggingEdgeIndex, pos.x, pos.y);
1408
  this.drawCanvas();
1409
  return;
1410
  }
1411
 
1412
  if (this.isDraggingPoint && this.selectedBoxIndex >= 0) {
 
1413
  this.movePolygonPoint(this.selectedBoxIndex, this.draggingPointIndex, pos.x, pos.y);
1414
  this.drawCanvas();
1415
  return;
1416
  }
1417
 
1418
  if (this.isDragging && this.selectedBoxIndex >= 0) {
 
1419
  const deltaX = pos.x - this.lastMouseX;
1420
  const deltaY = pos.y - this.lastMouseY;
1421
  this.movePolygon(this.selectedBoxIndex, deltaX, deltaY);
 
1426
  }
1427
 
1428
  if (this.isDrawingPolygon) {
 
1429
  if (this.currentPolygon) {
1430
  this.currentPolygon.points = [...this.polygonPoints, pos];
1431
  this.drawCanvas();
 
1433
  return;
1434
  }
1435
 
 
1436
  this.updatePolygonCursor(pos.x, pos.y);
1437
  return;
1438
  }
 
1457
  }
1458
  }
1459
 
1460
+
1461
  onMouseUp() {
1462
+ // Handle waiting for drag detection
1463
+ if (this.waitingForDrag) {
1464
+ this.waitingForDrag = false;
1465
+ // Short click without drag - default to segmentation
1466
+ this.startSegmentation(this.initialClickPos);
1467
+ return;
1468
+ }
1469
+
1470
+ // Rest of your existing mouse up logic...
1471
  if (this.annotationMode === 'segmentation') {
1472
  this.isDraggingEdge = false;
1473
  this.draggingEdgeIndex = -1;
 
1518
  this.canvas.style.cursor = 'crosshair';
1519
  this.drawCanvas();
1520
  }
1521
+
1522
  updatePolygonCursor(x, y) {
1523
  if (this.selectedBoxIndex >= 0 && this.annotations[this.selectedBoxIndex].type === 'segmentation') {
1524
  const handle = this.getResizeHandle(x, y);
 
1539
  updateCursor(x, y) {
1540
  if (this.selectedBoxIndex >= 0) {
1541
  const handle = this.getResizeHandle(x, y);
1542
+ this.canvas.style.cursor = handle.cursor;
1543
+ return;
 
 
1544
  }
1545
 
1546
  const boxIndex = this.getBoxAtPosition(x, y);
 
1604
  return handle;
1605
  }
1606
  }
1607
+
1608
+ // FIXED: Return proper object for interior clicks
1609
+ if (x >= box.left && x <= box.left + box.width &&
1610
+ y >= box.top && y <= box.top + box.height) {
1611
+ return { cursor: 'move', type: 'interior' };
1612
+ }
1613
+ return { cursor: 'default', type: 'default' };
1614
  }
1615
 
1616
  getPolygonCornerResizeCursor(pointIndex, points) {