jebin2 commited on
Commit
efc9b5d
Β·
1 Parent(s): 1e9da36

add esc and cnt to poly

Browse files
comic_panel_extractor/static/annotator.html CHANGED
@@ -504,8 +504,8 @@
504
  <div class="section-title">Annotation Mode</div>
505
  <div class="form-field">
506
  <select class="form-select" id="annotationMode">
507
- <option value="bbox">Bounding Box (YOLO)</option>
508
  <option value="segmentation">Segmentation (YOLO-seg)</option>
 
509
  </select>
510
  </div>
511
  <div class="form-field">
@@ -634,7 +634,7 @@
634
  this.currentBox = null;
635
 
636
  // Segmentation state
637
- this.annotationMode = 'bbox'; // 'bbox' or 'segmentation'
638
  this.currentPolygon = null;
639
  this.isDrawingPolygon = false;
640
  this.polygonPoints = [];
@@ -1684,6 +1684,28 @@
1684
 
1685
  // Modified onKeyDown method with new resize functionality
1686
  onKeyDown(e) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1687
  if (!this.currentImage || this.selectedBoxIndex < 0) return;
1688
 
1689
  const resizeDistance = 5; // Fixed resize distance
@@ -1750,6 +1772,25 @@
1750
  break;
1751
  }
1752
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1753
 
1754
  // New method to resize selected box
1755
  resizeSelectedBox(deltaWidth, deltaHeight) {
 
504
  <div class="section-title">Annotation Mode</div>
505
  <div class="form-field">
506
  <select class="form-select" id="annotationMode">
 
507
  <option value="segmentation">Segmentation (YOLO-seg)</option>
508
+ <option value="bbox">Bounding Box (YOLO)</option>
509
  </select>
510
  </div>
511
  <div class="form-field">
 
634
  this.currentBox = null;
635
 
636
  // Segmentation state
637
+ this.annotationMode = 'segmentation'; // 'bbox' or 'segmentation'
638
  this.currentPolygon = null;
639
  this.isDrawingPolygon = false;
640
  this.polygonPoints = [];
 
1684
 
1685
  // Modified onKeyDown method with new resize functionality
1686
  onKeyDown(e) {
1687
+ // Handle escape key for canceling drawing
1688
+ if (e.key === 'Escape') {
1689
+ e.preventDefault();
1690
+
1691
+ // Cancel polygon drawing if in progress
1692
+ if (this.annotationMode === 'segmentation' && this.isDrawingPolygon) {
1693
+ this.cancelPolygonDrawing();
1694
+ return;
1695
+ }
1696
+
1697
+ // Cancel bbox drawing if in progress
1698
+ if (this.annotationMode === 'bbox' && this.isDrawing) {
1699
+ this.cancelBboxDrawing();
1700
+ return;
1701
+ }
1702
+
1703
+ // Clear selection if nothing is being drawn
1704
+ this.selectedBoxIndex = -1;
1705
+ this.updateSelectedBoxInfo();
1706
+ this.drawCanvas();
1707
+ return;
1708
+ }
1709
  if (!this.currentImage || this.selectedBoxIndex < 0) return;
1710
 
1711
  const resizeDistance = 5; // Fixed resize distance
 
1772
  break;
1773
  }
1774
  }
1775
+ cancelPolygonDrawing() {
1776
+ this.isDrawingPolygon = false;
1777
+ this.polygonPoints = [];
1778
+ this.currentPolygon = null;
1779
+ this.selectedBoxIndex = -1;
1780
+ this.updateSelectedBoxInfo();
1781
+ this.drawCanvas();
1782
+ this.showAlert('Polygon drawing canceled', 'info');
1783
+ }
1784
+
1785
+ cancelBboxDrawing() {
1786
+ this.isDrawing = false;
1787
+ this.currentBox = null;
1788
+ this.selectedBoxIndex = -1;
1789
+ this.updateSelectedBoxInfo();
1790
+ this.drawCanvas();
1791
+ this.showAlert('Bounding box drawing canceled', 'info');
1792
+ }
1793
+
1794
 
1795
  // New method to resize selected box
1796
  resizeSelectedBox(deltaWidth, deltaHeight) {
comic_panel_extractor/train.py CHANGED
@@ -8,6 +8,71 @@ import os
8
  from pathlib import Path
9
  import shutil
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  def create_filtered_dataset(original_dataset_path, output_filtered_dataset_path):
12
  """
13
  Create a filtered dataset with only images that have non-empty labels
@@ -56,6 +121,7 @@ def create_filtered_dataset(original_dataset_path, output_filtered_dataset_path)
56
  shutil.copy2(img_file, output_images_dir / img_file.name)
57
  # Copy label
58
  shutil.copy2(label_file, output_labels_dir / label_file.name)
 
59
  copied_count += 1
60
  else:
61
  print(f"Skipping {img_file.name} - empty label file")
 
8
  from pathlib import Path
9
  import shutil
10
 
11
+ def convert_box_to_polygon(label_file: Path):
12
+ """
13
+ Converts YOLO box-format labels (class xc yc w h) to YOLO polygon-format labels
14
+ for segmentation. Creates a 4-point polygon representing the bounding box.
15
+ Overwrites the label file in place if conversion is needed.
16
+ """
17
+ if not label_file.exists():
18
+ return
19
+
20
+ new_lines = []
21
+ changed = False
22
+
23
+ with open(label_file, "r") as f:
24
+ for line in f:
25
+ line = line.strip()
26
+ if not line: # Skip empty lines
27
+ continue
28
+
29
+ parts = line.split()
30
+
31
+ if len(parts) == 5:
32
+ # Box format β†’ convert to polygon
33
+ try:
34
+ cls = int(float(parts[0])) # Class should be integer
35
+ xc, yc, bw, bh = map(float, parts[1:])
36
+
37
+ # Calculate corner points (clockwise from top-left)
38
+ x1 = max(0.0, min(1.0, xc - bw / 2)) # top-left x
39
+ y1 = max(0.0, min(1.0, yc - bh / 2)) # top-left y
40
+ x2 = max(0.0, min(1.0, xc + bw / 2)) # top-right x
41
+ y2 = max(0.0, min(1.0, yc - bh / 2)) # top-right y
42
+ x3 = max(0.0, min(1.0, xc + bw / 2)) # bottom-right x
43
+ y3 = max(0.0, min(1.0, yc + bh / 2)) # bottom-right y
44
+ x4 = max(0.0, min(1.0, xc - bw / 2)) # bottom-left x
45
+ y4 = max(0.0, min(1.0, yc + bh / 2)) # bottom-left y
46
+
47
+ # Format: class x1 y1 x2 y2 x3 y3 x4 y4
48
+ polygon_line = f"{cls} {x1:.6f} {y1:.6f} {x2:.6f} {y2:.6f} {x3:.6f} {y3:.6f} {x4:.6f} {y4:.6f}"
49
+ new_lines.append(polygon_line)
50
+ changed = True
51
+
52
+ except (ValueError, IndexError):
53
+ # If parsing fails, keep original line
54
+ new_lines.append(line)
55
+
56
+ elif len(parts) > 5 and len(parts) % 2 == 1:
57
+ # Already polygon format (odd number of parts: class + pairs of coordinates)
58
+ try:
59
+ cls = int(float(parts[0]))
60
+ coords = [float(x) for x in parts[1:]]
61
+ # Clamp coordinates to [0,1] range
62
+ coords = [max(0.0, min(1.0, coord)) for coord in coords]
63
+ coord_str = " ".join(f"{coord:.6f}" for coord in coords)
64
+ new_lines.append(f"{cls} {coord_str}")
65
+ except (ValueError, IndexError):
66
+ # If parsing fails, keep original line
67
+ new_lines.append(line)
68
+ else:
69
+ # Unknown format, keep as-is
70
+ new_lines.append(line)
71
+
72
+ if changed:
73
+ with open(label_file, "w") as f:
74
+ f.write("\n".join(new_lines) + "\n")
75
+
76
  def create_filtered_dataset(original_dataset_path, output_filtered_dataset_path):
77
  """
78
  Create a filtered dataset with only images that have non-empty labels
 
121
  shutil.copy2(img_file, output_images_dir / img_file.name)
122
  # Copy label
123
  shutil.copy2(label_file, output_labels_dir / label_file.name)
124
+ convert_box_to_polygon(output_labels_dir / label_file.name)
125
  copied_count += 1
126
  else:
127
  print(f"Skipping {img_file.name} - empty label file")
comic_panel_extractor/yolo_manager.py CHANGED
@@ -68,8 +68,8 @@ class YOLOManager:
68
  print(f"πŸ“¦ Loading model from: {weights_path}")
69
  self.model = YOLO(weights_path)
70
  else:
71
- print("✨ Loading pretrained model 'yolo12s.pt'")
72
- self.model = YOLO(f"{Config.current_path}/yolo12s.pt")
73
  return self.model
74
 
75
  def train(self,
 
68
  print(f"πŸ“¦ Loading model from: {weights_path}")
69
  self.model = YOLO(weights_path)
70
  else:
71
+ print("✨ Loading pretrained model 'yolov12s-seg.pt'")
72
+ self.model = YOLO(f"{Config.current_path}/yolov12s-seg.pt")
73
  return self.model
74
 
75
  def train(self,