Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -465,33 +465,23 @@ def mask_paper_area_in_image(image: np.ndarray, paper_contour: np.ndarray) -> np
|
|
| 465 |
|
| 466 |
def exclude_paper_area(mask: np.ndarray, paper_contour: np.ndarray, expansion_factor: float = 1.2) -> np.ndarray:
|
| 467 |
"""
|
| 468 |
-
Remove paper area from the mask to focus only on objects
|
| 469 |
"""
|
| 470 |
-
#
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
# Create much more aggressive inward shrinking
|
| 475 |
-
shrink_x = int(w * 0.15) # Shrink 15% from each side
|
| 476 |
-
shrink_y = int(h * 0.15) # Shrink 15% from top/bottom
|
| 477 |
-
|
| 478 |
-
# Create inner object area (much smaller than paper)
|
| 479 |
-
inner_x = x + shrink_x
|
| 480 |
-
inner_y = y + shrink_y
|
| 481 |
-
inner_w = w - (2 * shrink_x)
|
| 482 |
-
inner_h = h - (2 * shrink_y)
|
| 483 |
|
| 484 |
-
# Create mask
|
| 485 |
-
|
| 486 |
-
cv2.
|
|
|
|
| 487 |
|
| 488 |
-
# Apply mask: keep
|
| 489 |
-
result_mask = cv2.bitwise_and(mask,
|
| 490 |
|
| 491 |
-
#
|
| 492 |
-
|
| 493 |
-
result_mask = cv2.morphologyEx(result_mask, cv2.
|
| 494 |
-
result_mask = cv2.morphologyEx(result_mask, cv2.MORPH_CLOSE, kernel, iterations=2)
|
| 495 |
|
| 496 |
return result_mask
|
| 497 |
|
|
@@ -765,13 +755,34 @@ def place_finger_cut_adjusted(
|
|
| 765 |
logger.error(f"Error in place_finger_cut_adjusted: {e}")
|
| 766 |
return fallback_solution()
|
| 767 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 768 |
def extract_outlines(binary_image: np.ndarray) -> Tuple[np.ndarray, list]:
|
| 769 |
"""Extract outlines from binary image"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 770 |
contours, _ = cv2.findContours(
|
| 771 |
-
|
| 772 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 773 |
outline_image = np.full_like(binary_image, 255)
|
| 774 |
-
return outline_image,
|
| 775 |
|
| 776 |
def round_edges(mask: np.ndarray, radius_mm: float, scaling_factor: float) -> np.ndarray:
|
| 777 |
"""Round mask edges using contour smoothing"""
|
|
|
|
| 465 |
|
| 466 |
def exclude_paper_area(mask: np.ndarray, paper_contour: np.ndarray, expansion_factor: float = 1.2) -> np.ndarray:
|
| 467 |
"""
|
| 468 |
+
Remove paper area from the mask to focus only on objects using soft boundaries
|
| 469 |
"""
|
| 470 |
+
# Create paper mask
|
| 471 |
+
paper_mask = np.zeros(mask.shape[:2], dtype=np.uint8)
|
| 472 |
+
cv2.fillPoly(paper_mask, [paper_contour], 255)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 473 |
|
| 474 |
+
# Create eroded version of paper mask (soft inward boundary)
|
| 475 |
+
erosion_size = int(min(mask.shape[0], mask.shape[1]) * 0.03) # 3% of image size
|
| 476 |
+
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (erosion_size, erosion_size))
|
| 477 |
+
eroded_paper_mask = cv2.erode(paper_mask, kernel, iterations=2)
|
| 478 |
|
| 479 |
+
# Apply soft mask: keep pixels in original mask AND in eroded paper area
|
| 480 |
+
result_mask = cv2.bitwise_and(mask, eroded_paper_mask)
|
| 481 |
|
| 482 |
+
# Gentle cleanup without hard cuts
|
| 483 |
+
small_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
|
| 484 |
+
result_mask = cv2.morphologyEx(result_mask, cv2.MORPH_CLOSE, small_kernel, iterations=1)
|
|
|
|
| 485 |
|
| 486 |
return result_mask
|
| 487 |
|
|
|
|
| 755 |
logger.error(f"Error in place_finger_cut_adjusted: {e}")
|
| 756 |
return fallback_solution()
|
| 757 |
|
| 758 |
+
# def extract_outlines(binary_image: np.ndarray) -> Tuple[np.ndarray, list]:
|
| 759 |
+
# """Extract outlines from binary image"""
|
| 760 |
+
# contours, _ = cv2.findContours(
|
| 761 |
+
# binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE
|
| 762 |
+
# )
|
| 763 |
+
# outline_image = np.full_like(binary_image, 255)
|
| 764 |
+
# return outline_image, contours
|
| 765 |
+
|
| 766 |
def extract_outlines(binary_image: np.ndarray) -> Tuple[np.ndarray, list]:
|
| 767 |
"""Extract outlines from binary image"""
|
| 768 |
+
# Check if contours are being cut at image boundaries
|
| 769 |
+
h, w = binary_image.shape
|
| 770 |
+
|
| 771 |
+
# Add small border to prevent boundary cutting
|
| 772 |
+
bordered_image = cv2.copyMakeBorder(binary_image, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=0)
|
| 773 |
+
|
| 774 |
contours, _ = cv2.findContours(
|
| 775 |
+
bordered_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE
|
| 776 |
)
|
| 777 |
+
|
| 778 |
+
# Adjust contour coordinates back to original image space
|
| 779 |
+
adjusted_contours = []
|
| 780 |
+
for contour in contours:
|
| 781 |
+
adjusted_contour = contour - [5, 5] # Subtract border offset
|
| 782 |
+
adjusted_contours.append(adjusted_contour)
|
| 783 |
+
|
| 784 |
outline_image = np.full_like(binary_image, 255)
|
| 785 |
+
return outline_image, adjusted_contours
|
| 786 |
|
| 787 |
def round_edges(mask: np.ndarray, radius_mm: float, scaling_factor: float) -> np.ndarray:
|
| 788 |
"""Round mask edges using contour smoothing"""
|