jebin2 commited on
Commit
c38c187
Β·
1 Parent(s): a1f4a1e

added polygon support

Browse files
Files changed (1) hide show
  1. comic_panel_extractor/yolo_manager.py +52 -18
comic_panel_extractor/yolo_manager.py CHANGED
@@ -150,6 +150,8 @@ class YOLOManager:
150
  image_paths: List of image file paths
151
  output_dir: Directory to save annotated images and labels
152
  image_size: Size for inference
 
 
153
  """
154
  if not self.model:
155
  raise ValueError("❌ No model loaded. Please load a model first.")
@@ -159,8 +161,8 @@ class YOLOManager:
159
 
160
  image_size = image_size or Config.DEFAULT_IMAGE_SIZE
161
  # clean_directory(output_dir)
162
- totla_images = len(image_paths)
163
- print(f"🎨 Annotating {totla_images} images and saving labels...")
164
 
165
  for idx, image_path in enumerate(image_paths):
166
  if not os.path.isfile(image_path):
@@ -176,7 +178,8 @@ class YOLOManager:
176
 
177
  # Run inference
178
  results = self.model(image_path, imgsz=image_size)
179
- annotated_frame = results[0].plot()
 
180
 
181
  # Prepare save paths
182
  original_name = os.path.basename(image_path)
@@ -191,33 +194,64 @@ class YOLOManager:
191
 
192
  # Write YOLO label file
193
  with open(save_txt_path, 'w') as f:
194
- for box in results[0].boxes:
195
- # box.xyxy format: (xmin, ymin, xmax, ymax)
196
- xyxy = box.xyxy[0].tolist()
197
- cls_id = int(box.cls[0].item()) # class id
198
 
199
- xmin, ymin, xmax, ymax = xyxy
200
- # Convert to YOLO format (normalized)
201
- x_center = ((xmin + xmax) / 2) / w
202
- y_center = ((ymin + ymax) / 2) / h
203
- width = (xmax - xmin) / w
204
- height = (ymax - ymin) / h
205
 
206
- # Write one line per object
207
- f.write(f"{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
209
  if label_path:
210
  shutil.copyfile(save_txt_path, label_path)
211
- print(f'βœ… Saved annotated image: {save_img_path}')
 
 
212
  print(f'βœ… Saved label file: {save_txt_path}')
213
  print(f"πŸŽ‰ Annotation and label saving complete! Results saved to: {output_dir}")
214
 
215
- if totla_images == 1:
216
  return save_img_path, save_txt_path
217
 
218
  except Exception as e:
219
  print(f"❌ Error processing {image_path}: {str(e)}")
220
- return None, None
 
221
 
222
  def __enter__(self):
223
  # When entering context, just return self
 
150
  image_paths: List of image file paths
151
  output_dir: Directory to save annotated images and labels
152
  image_size: Size for inference
153
+ save_image: Whether to save annotated images
154
+ label_path: Optional specific path for label file
155
  """
156
  if not self.model:
157
  raise ValueError("❌ No model loaded. Please load a model first.")
 
161
 
162
  image_size = image_size or Config.DEFAULT_IMAGE_SIZE
163
  # clean_directory(output_dir)
164
+ total_images = len(image_paths)
165
+ print(f"🎨 Annotating {total_images} images and saving labels...")
166
 
167
  for idx, image_path in enumerate(image_paths):
168
  if not os.path.isfile(image_path):
 
178
 
179
  # Run inference
180
  results = self.model(image_path, imgsz=image_size)
181
+ result = results[0]
182
+ annotated_frame = result.plot()
183
 
184
  # Prepare save paths
185
  original_name = os.path.basename(image_path)
 
194
 
195
  # Write YOLO label file
196
  with open(save_txt_path, 'w') as f:
197
+ # Check if we have segmentation masks (YOLO-seg model)
198
+ if hasattr(result, 'masks') and result.masks is not None:
199
+ print(f"πŸ“ Processing segmentation masks...")
 
200
 
201
+ # Process segmentation masks
202
+ masks = result.masks
203
+ for i, mask in enumerate(masks.xy): # masks.xy gives polygon coordinates
204
+ cls_id = int(result.boxes.cls[i].item())
 
 
205
 
206
+ # mask is already in pixel coordinates
207
+ # Normalize coordinates to [0,1] range
208
+ normalized_coords = []
209
+ for point in mask:
210
+ x_norm = point[0] / w
211
+ y_norm = point[1] / h
212
+ normalized_coords.extend([x_norm, y_norm])
213
+
214
+ # Write segmentation format: class_id x1 y1 x2 y2 x3 y3 ...
215
+ coords_str = ' '.join(f'{coord:.6f}' for coord in normalized_coords)
216
+ f.write(f"{cls_id} {coords_str}\n")
217
+
218
+ # Fallback to bounding boxes if no masks (YOLO detection model)
219
+ elif hasattr(result, 'boxes') and result.boxes is not None:
220
+ print(f"πŸ“¦ Processing bounding boxes...")
221
+
222
+ for box in result.boxes:
223
+ # box.xyxy format: (xmin, ymin, xmax, ymax)
224
+ xyxy = box.xyxy[0].tolist()
225
+ cls_id = int(box.cls[0].item())
226
+
227
+ xmin, ymin, xmax, ymax = xyxy
228
+ # Convert to YOLO format (normalized)
229
+ x_center = ((xmin + xmax) / 2) / w
230
+ y_center = ((ymin + ymax) / 2) / h
231
+ width = (xmax - xmin) / w
232
+ height = (ymax - ymin) / h
233
+
234
+ # Write bounding box format: class_id x_center y_center width height
235
+ f.write(f"{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}\n")
236
+
237
+ else:
238
+ print("⚠️ No detections found in this image")
239
 
240
  if label_path:
241
  shutil.copyfile(save_txt_path, label_path)
242
+
243
+ if save_img_path:
244
+ print(f'βœ… Saved annotated image: {save_img_path}')
245
  print(f'βœ… Saved label file: {save_txt_path}')
246
  print(f"πŸŽ‰ Annotation and label saving complete! Results saved to: {output_dir}")
247
 
248
+ if total_images == 1:
249
  return save_img_path, save_txt_path
250
 
251
  except Exception as e:
252
  print(f"❌ Error processing {image_path}: {str(e)}")
253
+ if total_images == 1:
254
+ return None, None
255
 
256
  def __enter__(self):
257
  # When entering context, just return self