Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -479,6 +479,7 @@ def convert_to_native_types(obj):
|
|
| 479 |
def clean_mask(mask: np.ndarray, min_area: int = 100) -> np.ndarray:
|
| 480 |
"""
|
| 481 |
Очищает маску от мелких артефактов и дыр.
|
|
|
|
| 482 |
|
| 483 |
mask: бинарная маска (H, W)
|
| 484 |
min_area: минимальная площадь компонента в пикселях
|
|
@@ -491,32 +492,15 @@ def clean_mask(mask: np.ndarray, min_area: int = 100) -> np.ndarray:
|
|
| 491 |
else:
|
| 492 |
mask_uint8 = (mask * 255).astype(np.uint8)
|
| 493 |
|
| 494 |
-
#
|
| 495 |
-
kernel
|
| 496 |
-
|
|
|
|
| 497 |
|
| 498 |
-
#
|
| 499 |
-
|
| 500 |
|
| 501 |
-
|
| 502 |
-
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(mask_uint8, connectivity=8)
|
| 503 |
-
|
| 504 |
-
# Создаем чистую маску
|
| 505 |
-
clean_mask = np.zeros_like(mask_uint8)
|
| 506 |
-
|
| 507 |
-
# Оставляем только большие компоненты
|
| 508 |
-
for i in range(1, num_labels): # Пропускаем фон (0)
|
| 509 |
-
area = stats[i, cv2.CC_STAT_AREA]
|
| 510 |
-
if area >= min_area:
|
| 511 |
-
clean_mask[labels == i] = 255
|
| 512 |
-
|
| 513 |
-
# Если ничего не осталось, возвращаем самый большой компонент
|
| 514 |
-
if clean_mask.sum() == 0 and num_labels > 1:
|
| 515 |
-
# Находим самый большой компонент
|
| 516 |
-
largest_component = 1 + np.argmax([stats[i, cv2.CC_STAT_AREA] for i in range(1, num_labels)])
|
| 517 |
-
clean_mask[labels == largest_component] = 255
|
| 518 |
-
|
| 519 |
-
return (clean_mask > 127).astype(bool)
|
| 520 |
|
| 521 |
def extract_object_image(image: np.ndarray, mask: np.ndarray, clean: bool = True) -> str:
|
| 522 |
"""
|
|
|
|
| 479 |
def clean_mask(mask: np.ndarray, min_area: int = 100) -> np.ndarray:
|
| 480 |
"""
|
| 481 |
Очищает маску от мелких артефактов и дыр.
|
| 482 |
+
Более мягкий вариант - не убивает тонкие детали типа лямок.
|
| 483 |
|
| 484 |
mask: бинарная маска (H, W)
|
| 485 |
min_area: минимальная площадь компонента в пикселях
|
|
|
|
| 492 |
else:
|
| 493 |
mask_uint8 = (mask * 255).astype(np.uint8)
|
| 494 |
|
| 495 |
+
# Только легкое закрытие для удаления мелких дыр внутри объекта
|
| 496 |
+
# Используем маленький kernel чтобы не убить тонкие детали (лямки, пальцы и т.д.)
|
| 497 |
+
kernel = np.ones((2, 2), np.uint8)
|
| 498 |
+
mask_uint8 = cv2.morphologyEx(mask_uint8, cv2.MORPH_CLOSE, kernel, iterations=1)
|
| 499 |
|
| 500 |
+
# УБРАЛ MORPH_OPEN - он убивал тонкие элементы типа лямок портфеля
|
| 501 |
+
# УБРАЛ фильтрацию по площади компонентов - она тоже могла вырезать лямки
|
| 502 |
|
| 503 |
+
return (mask_uint8 > 127).astype(bool)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 504 |
|
| 505 |
def extract_object_image(image: np.ndarray, mask: np.ndarray, clean: bool = True) -> str:
|
| 506 |
"""
|