mlbench123 commited on
Commit
6344420
·
verified ·
1 Parent(s): f1fd8d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -54
app.py CHANGED
@@ -368,6 +368,20 @@ def detect_paper_bounds(image: np.ndarray, paper_size: str, output_unit: str = "
368
  # Use fallback contour detection
369
  logger.info("Using fallback contour detection for paper")
370
  paper_contour, _ = detect_paper_contour(image, output_unit)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
372
  # Calculate scaling factor based on paper size with proper units
373
  scaling_factor = calculate_paper_scaling_factor(paper_contour, paper_size, output_unit)
@@ -529,24 +543,20 @@ def mask_paper_area_in_image(image: np.ndarray, paper_contour: np.ndarray) -> np
529
  return masked_image
530
 
531
  def exclude_paper_area(mask: np.ndarray, paper_contour: np.ndarray, expansion_factor: float = 1.2) -> np.ndarray:
532
- """
533
- Remove paper area from the mask to focus only on objects using soft boundaries
534
- """
535
  # Create paper mask
536
  paper_mask = np.zeros(mask.shape[:2], dtype=np.uint8)
537
  cv2.fillPoly(paper_mask, [paper_contour], 255)
538
 
539
- # Create eroded version of paper mask (soft inward boundary)
540
- erosion_size = int(min(mask.shape[0], mask.shape[1]) * 0.03) # 3% of image size
541
- kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (erosion_size, erosion_size))
542
- eroded_paper_mask = cv2.erode(paper_mask, kernel, iterations=2)
543
 
544
- # Apply soft mask: keep pixels in original mask AND in eroded paper area
545
- result_mask = cv2.bitwise_and(mask, eroded_paper_mask)
546
 
547
- # Gentle cleanup without hard cuts
548
- small_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
549
- result_mask = cv2.morphologyEx(result_mask, cv2.MORPH_CLOSE, small_kernel, iterations=1)
550
 
551
  return result_mask
552
 
@@ -964,51 +974,31 @@ def predict_with_paper(image, paper_size, offset, offset_unit, finger_clearance=
964
  raise gr.Error(f"Error processing image: {str(e)}")
965
 
966
  try:
967
- # Mask paper area in input image first
968
- # masked_input_image = mask_paper_area_in_image(image, paper_contour)
 
969
 
970
- # Use YOLOv8 to detect objects
971
- yolo_v8 = get_yolo_v8()
972
- if yolo_v8 is None:
973
- logger.warning("YOLOv8 model not available, proceeding with full image")
974
- cropped_image = image
975
- crop_offset = (0, 0)
976
- else:
977
- # YOLOv8 detects all COCO classes by default
978
- results = yolo_v8.predict(image, conf=0.1, verbose=False)
979
-
980
- if not results or len(results) == 0 or not hasattr(results[0], 'boxes') or len(results[0].boxes) == 0:
981
- logger.warning("No objects detected by YOLOv8, proceeding with full image")
982
- cropped_image = image
983
- crop_offset = (0, 0)
984
- else:
985
- boxes = results[0].boxes.xyxy.cpu().numpy()
986
- confidences = results[0].boxes.conf.cpu().numpy()
987
-
988
- # Filter out very large boxes (likely paper/background)
989
- image_area = image.shape[0] * image.shape[1]
990
- valid_boxes = []
991
-
992
- for i, box in enumerate(boxes):
993
- x_min, y_min, x_max, y_max = box
994
- box_area = (x_max - x_min) * (y_max - y_min)
995
- # Keep boxes that are 5% to 40% of image area
996
- if 0.001 * image_area < box_area < 0.6 * image_area:
997
- valid_boxes.append((i, confidences[i]))
998
-
999
- if not valid_boxes:
1000
- logger.warning("No valid objects detected, proceeding with full image")
1001
- cropped_image = image
1002
- crop_offset = (0, 0)
1003
- else:
1004
- # Get highest confidence valid box
1005
- best_idx = max(valid_boxes, key=lambda x: x[1])[0]
1006
- x_min, y_min, x_max, y_max = map(int, boxes[best_idx])
1007
 
1008
- # Remove background from cropped image
1009
- orig_size = image.shape[:2]
1010
  objects_mask = remove_bg(cropped_image)
1011
- processed_size = objects_mask.shape[:2]
 
 
 
 
 
 
 
 
1012
 
1013
  # Resize mask to match cropped region and place back in original image space
1014
  full_mask = np.zeros((orig_size[0], orig_size[1]), dtype=np.uint8)
 
368
  # Use fallback contour detection
369
  logger.info("Using fallback contour detection for paper")
370
  paper_contour, _ = detect_paper_contour(image, output_unit)
371
+
372
+ # After getting paper_contour, expand it
373
+ rect = cv2.boundingRect(paper_contour)
374
+ expansion = int(min(rect[2], rect[3]) * 0.1) # Expand by 10%
375
+
376
+ x, y, w, h = rect
377
+ expanded_contour = np.array([
378
+ [[max(0, x - expansion), max(0, y - expansion)]],
379
+ [[min(image.shape[1], x + w + expansion), max(0, y - expansion)]],
380
+ [[min(image.shape[1], x + w + expansion), min(image.shape[0], y + h + expansion)]],
381
+ [[max(0, x - expansion), min(image.shape[0], y + h + expansion)]]
382
+ ])
383
+
384
+ paper_contour = expanded_contour
385
 
386
  # Calculate scaling factor based on paper size with proper units
387
  scaling_factor = calculate_paper_scaling_factor(paper_contour, paper_size, output_unit)
 
543
  return masked_image
544
 
545
  def exclude_paper_area(mask: np.ndarray, paper_contour: np.ndarray, expansion_factor: float = 1.2) -> np.ndarray:
546
+ """Less aggressive paper area exclusion"""
 
 
547
  # Create paper mask
548
  paper_mask = np.zeros(mask.shape[:2], dtype=np.uint8)
549
  cv2.fillPoly(paper_mask, [paper_contour], 255)
550
 
551
+ # Instead of eroding, slightly expand the paper mask
552
+ rect = cv2.boundingRect(paper_contour)
553
+ expansion = max(10, int(min(rect[2], rect[3]) * 0.02)) # 2% expansion
 
554
 
555
+ kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (expansion, expansion))
556
+ expanded_paper_mask = cv2.dilate(paper_mask, kernel, iterations=1)
557
 
558
+ # Keep objects within expanded paper area
559
+ result_mask = cv2.bitwise_and(mask, expanded_paper_mask)
 
560
 
561
  return result_mask
562
 
 
974
  raise gr.Error(f"Error processing image: {str(e)}")
975
 
976
  try:
977
+ # Get paper bounds with expansion
978
+ rect = cv2.boundingRect(paper_contour)
979
+ expansion = max(20, int(min(rect[2], rect[3]) * 0.05)) # 5% expansion
980
 
981
+ x, y, w, h = rect
982
+ x_min = max(0, x - expansion)
983
+ y_min = max(0, y - expansion)
984
+ x_max = min(image.shape[1], x + w + expansion)
985
+ y_max = min(image.shape[0], y + h + expansion)
986
+
987
+ # Process the expanded paper area
988
+ cropped_image = image[y_min:y_max, x_min:x_max]
989
+ crop_offset = (x_min, y_min)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
990
 
991
+ # Remove background
 
992
  objects_mask = remove_bg(cropped_image)
993
+
994
+ # Place back in full image space
995
+ full_mask = np.zeros((image.shape[0], image.shape[1]), dtype=np.uint8)
996
+ full_mask[y_min:y_max, x_min:x_max] = objects_mask
997
+
998
+ # Light filtering only - don't exclude paper area aggressively
999
+ # Just remove small noise
1000
+ kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
1001
+ objects_mask = cv2.morphologyEx(full_mask, cv2.MORPH_OPEN, kernel)
1002
 
1003
  # Resize mask to match cropped region and place back in original image space
1004
  full_mask = np.zeros((orig_size[0], orig_size[1]), dtype=np.uint8)