Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -13,7 +13,6 @@ from transformers import AutoModelForImageSegmentation
|
|
13 |
import cv2
|
14 |
import ezdxf
|
15 |
import gradio as gr
|
16 |
-
from MODNet.src.models.modnet import MODNet
|
17 |
import gc
|
18 |
# from scalingtestupdated import calculate_scaling_factor
|
19 |
from scalingtestupdated import calculate_scaling_factor_with_units, calculate_paper_scaling_factor, convert_units
|
@@ -42,21 +41,6 @@ PAPER_SIZES = {
|
|
42 |
"A3": {"width": 297, "height": 420},
|
43 |
"US Letter": {"width": 215.9, "height": 279.4}
|
44 |
}
|
45 |
-
|
46 |
-
def get_modnet():
|
47 |
-
"""Lazy load MODNet model"""
|
48 |
-
global modnet_global
|
49 |
-
if modnet_global is None:
|
50 |
-
logger.info("Loading MODNet model...")
|
51 |
-
modnet_global = MODNet(backbone_pretrained=False)
|
52 |
-
modnet_global.load_state_dict(torch.load('modnet_photographic_portrait_matting.ckpt', map_location='cpu'))
|
53 |
-
modnet_global.to(device).eval()
|
54 |
-
return modnet_global
|
55 |
-
|
56 |
-
def get_yolo_world():
|
57 |
-
"""Lazy load YOLO-World model"""
|
58 |
-
yolo_world = YOLOWorld('yolov8s-world.pt') # Smaller model for efficiency
|
59 |
-
return yolo_world
|
60 |
|
61 |
# Custom Exception Classes
|
62 |
class TimeoutReachedError(Exception):
|
@@ -536,34 +520,6 @@ def remove_bg_u2netp(image: np.ndarray) -> np.ndarray:
|
|
536 |
logger.error(f"Error in U2NETP background removal: {e}")
|
537 |
raise
|
538 |
|
539 |
-
def remove_bg_modnet(image: np.ndarray) -> np.ndarray:
|
540 |
-
"""Remove background using MODNet"""
|
541 |
-
try:
|
542 |
-
model = get_modnet()
|
543 |
-
|
544 |
-
# Preprocess
|
545 |
-
transform = transforms.Compose([
|
546 |
-
transforms.ToTensor(),
|
547 |
-
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
|
548 |
-
])
|
549 |
-
|
550 |
-
image_pil = Image.fromarray(image)
|
551 |
-
image_tensor = transform(image_pil).unsqueeze(0).to(device)
|
552 |
-
|
553 |
-
# Predict
|
554 |
-
with torch.no_grad():
|
555 |
-
_, _, matte = model(image_tensor, True)
|
556 |
-
|
557 |
-
# Post-process
|
558 |
-
matte = matte.squeeze().cpu().numpy()
|
559 |
-
matte = (matte * 255).astype(np.uint8)
|
560 |
-
matte = cv2.resize(matte, (image.shape[1], image.shape[0]))
|
561 |
-
|
562 |
-
return matte
|
563 |
-
|
564 |
-
except Exception as e:
|
565 |
-
logger.error(f"MODNet failed: {e}")
|
566 |
-
return remove_bg_u2netp(image) # Fallback to U2Net
|
567 |
|
568 |
def remove_bg(image: np.ndarray) -> np.ndarray:
|
569 |
"""Remove background using BiRefNet model for main objects"""
|
@@ -1103,143 +1059,6 @@ def make_square(img: np.ndarray):
|
|
1103 |
|
1104 |
return padded
|
1105 |
|
1106 |
-
# def predict_with_paper(image, paper_size, offset,offset_unit, finger_clearance=False):
|
1107 |
-
# """Main prediction function using paper as reference"""
|
1108 |
-
|
1109 |
-
# logger.info(f"Starting prediction with image shape: {image.shape}")
|
1110 |
-
# logger.info(f"Paper size: {paper_size}")
|
1111 |
-
|
1112 |
-
# if offset_unit == "inches":
|
1113 |
-
# offset_mm = offset * 25.4 # Convert to mm for internal calculations
|
1114 |
-
# else:
|
1115 |
-
# offset_mm = offset
|
1116 |
-
|
1117 |
-
# edge_radius = None
|
1118 |
-
# if edge_radius is None or edge_radius == 0:
|
1119 |
-
# edge_radius = 0.0001
|
1120 |
-
|
1121 |
-
# if offset < 0:
|
1122 |
-
# raise gr.Error("Offset Value Can't be negative")
|
1123 |
-
|
1124 |
-
# try:
|
1125 |
-
# # Detect paper bounds and calculate scaling factor
|
1126 |
-
# logger.info("Starting paper detection...")
|
1127 |
-
# paper_contour, scaling_factor = detect_paper_bounds(image, paper_size)
|
1128 |
-
# logger.info(f"Paper detected successfully with scaling factor: {scaling_factor:.4f} mm/px")
|
1129 |
-
|
1130 |
-
# except ReferenceBoxNotDetectedError as e:
|
1131 |
-
# logger.error(f"Paper detection failed: {e}")
|
1132 |
-
# return (
|
1133 |
-
# None, None, None, None,
|
1134 |
-
# f"Error: {str(e)}"
|
1135 |
-
# )
|
1136 |
-
# except Exception as e:
|
1137 |
-
# logger.error(f"Unexpected error in paper detection: {e}")
|
1138 |
-
# raise gr.Error(f"Error processing image: {str(e)}")
|
1139 |
-
|
1140 |
-
# try:
|
1141 |
-
# # Remove background from main objects
|
1142 |
-
# # orig_size = image.shape[:2]
|
1143 |
-
# # objects_mask = remove_bg(image)
|
1144 |
-
|
1145 |
-
# # Mask paper area in input image first
|
1146 |
-
# masked_input_image = mask_paper_area_in_image(image, paper_contour)
|
1147 |
-
|
1148 |
-
# # Remove background from main objects
|
1149 |
-
# orig_size = image.shape[:2]
|
1150 |
-
# objects_mask = remove_bg(image)
|
1151 |
-
# processed_size = objects_mask.shape[:2]
|
1152 |
-
|
1153 |
-
# # Resize mask to match original image
|
1154 |
-
# objects_mask = cv2.resize(objects_mask, (image.shape[1], image.shape[0]))
|
1155 |
-
|
1156 |
-
# # Remove paper area from mask to focus only on objects
|
1157 |
-
# objects_mask = exclude_paper_area(objects_mask, paper_contour)
|
1158 |
-
|
1159 |
-
# # Check if we actually have object pixels after paper exclusion
|
1160 |
-
# object_pixels = np.count_nonzero(objects_mask)
|
1161 |
-
# if object_pixels < 1000: # Minimum threshold
|
1162 |
-
# raise NoObjectDetectedError("No significant object detected after excluding paper area")
|
1163 |
-
|
1164 |
-
# # Validate single object
|
1165 |
-
# validate_single_object(objects_mask, paper_contour)
|
1166 |
-
|
1167 |
-
# except (MultipleObjectsError, NoObjectDetectedError) as e:
|
1168 |
-
# return (
|
1169 |
-
# None, None, None, None,
|
1170 |
-
# f"Error: {str(e)}"
|
1171 |
-
# )
|
1172 |
-
# except Exception as e:
|
1173 |
-
# raise gr.Error(f"Error in object detection: {str(e)}")
|
1174 |
-
|
1175 |
-
# # Apply edge rounding if specified
|
1176 |
-
# rounded_mask = objects_mask.copy()
|
1177 |
-
|
1178 |
-
# # Apply dilation for offset - more precise calculation
|
1179 |
-
# if offset_mm > 0:
|
1180 |
-
# offset_pixels = int(round(float(offset_mm) / scaling_factor))
|
1181 |
-
# if offset_pixels > 0:
|
1182 |
-
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (offset_pixels*2+1, offset_pixels*2+1))
|
1183 |
-
# dilated_mask = cv2.dilate(rounded_mask, kernel, iterations=1)
|
1184 |
-
# else:
|
1185 |
-
# dilated_mask = rounded_mask.copy()
|
1186 |
-
|
1187 |
-
# # Save original dilated mask for output
|
1188 |
-
# Image.fromarray(dilated_mask).save("./outputs/scaled_mask_original.jpg")
|
1189 |
-
# dilated_mask_orig = dilated_mask.copy()
|
1190 |
-
|
1191 |
-
# # Extract contours
|
1192 |
-
# outlines, contours = extract_outlines(dilated_mask)
|
1193 |
-
|
1194 |
-
# try:
|
1195 |
-
# # Generate DXF
|
1196 |
-
# dxf, finger_polygons, original_polygons = save_dxf_spline(
|
1197 |
-
# contours,
|
1198 |
-
# scaling_factor,
|
1199 |
-
# processed_size[0],
|
1200 |
-
# finger_clearance=(finger_clearance == "On")
|
1201 |
-
# )
|
1202 |
-
# except FingerCutOverlapError as e:
|
1203 |
-
# raise gr.Error(str(e))
|
1204 |
-
|
1205 |
-
# # Create annotated image
|
1206 |
-
# shrunked_img_contours = image.copy()
|
1207 |
-
|
1208 |
-
# if finger_clearance == "On":
|
1209 |
-
# outlines = np.full_like(dilated_mask, 255)
|
1210 |
-
# for poly in finger_polygons:
|
1211 |
-
# try:
|
1212 |
-
# coords = np.array([
|
1213 |
-
# (int(x / scaling_factor), int(processed_size[0] - y / scaling_factor))
|
1214 |
-
# for x, y in poly.exterior.coords
|
1215 |
-
# ], np.int32).reshape((-1, 1, 2))
|
1216 |
-
|
1217 |
-
# cv2.drawContours(shrunked_img_contours, [coords], -1, (0, 255, 0), thickness=2)
|
1218 |
-
# cv2.drawContours(outlines, [coords], -1, 0, thickness=2)
|
1219 |
-
# except Exception as e:
|
1220 |
-
# logger.warning(f"Failed to draw finger cut: {e}")
|
1221 |
-
# continue
|
1222 |
-
# else:
|
1223 |
-
# outlines = np.full_like(dilated_mask, 255)
|
1224 |
-
# cv2.drawContours(shrunked_img_contours, contours, -1, (0, 255, 0), thickness=2)
|
1225 |
-
# cv2.drawContours(outlines, contours, -1, 0, thickness=2)
|
1226 |
-
|
1227 |
-
# # # Draw paper bounds on annotated image
|
1228 |
-
# # cv2.drawContours(shrunked_img_contours, [paper_contour], -1, (255, 0, 0), thickness=3)
|
1229 |
-
|
1230 |
-
# # # Add paper size text
|
1231 |
-
# # paper_text = f"Paper: {paper_size}"
|
1232 |
-
# # cv2.putText(shrunked_img_contours, paper_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
|
1233 |
-
|
1234 |
-
# cleanup_models()
|
1235 |
-
|
1236 |
-
# return (
|
1237 |
-
# shrunked_img_contours,
|
1238 |
-
# outlines,
|
1239 |
-
# dxf,
|
1240 |
-
# dilated_mask_orig,
|
1241 |
-
# f"Scale: {scaling_factor:.4f} mm/px | Paper: {paper_size}"
|
1242 |
-
# )
|
1243 |
def predict_with_paper(image, paper_size, offset, offset_unit, finger_clearance=False):
|
1244 |
"""Main prediction function using paper as reference"""
|
1245 |
|
@@ -1286,7 +1105,7 @@ def predict_with_paper(image, paper_size, offset, offset_unit, finger_clearance=
|
|
1286 |
orig_size = image.shape[:2]
|
1287 |
# objects_mask = remove_bg(image)
|
1288 |
# objects_mask = remove_bg(image)
|
1289 |
-
objects_mask =
|
1290 |
processed_size = objects_mask.shape[:2]
|
1291 |
|
1292 |
# Resize mask to match original image
|
|
|
13 |
import cv2
|
14 |
import ezdxf
|
15 |
import gradio as gr
|
|
|
16 |
import gc
|
17 |
# from scalingtestupdated import calculate_scaling_factor
|
18 |
from scalingtestupdated import calculate_scaling_factor_with_units, calculate_paper_scaling_factor, convert_units
|
|
|
41 |
"A3": {"width": 297, "height": 420},
|
42 |
"US Letter": {"width": 215.9, "height": 279.4}
|
43 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
# Custom Exception Classes
|
46 |
class TimeoutReachedError(Exception):
|
|
|
520 |
logger.error(f"Error in U2NETP background removal: {e}")
|
521 |
raise
|
522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
523 |
|
524 |
def remove_bg(image: np.ndarray) -> np.ndarray:
|
525 |
"""Remove background using BiRefNet model for main objects"""
|
|
|
1059 |
|
1060 |
return padded
|
1061 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1062 |
def predict_with_paper(image, paper_size, offset, offset_unit, finger_clearance=False):
|
1063 |
"""Main prediction function using paper as reference"""
|
1064 |
|
|
|
1105 |
orig_size = image.shape[:2]
|
1106 |
# objects_mask = remove_bg(image)
|
1107 |
# objects_mask = remove_bg(image)
|
1108 |
+
objects_mask = remove_bg_u2netp(image)
|
1109 |
processed_size = objects_mask.shape[:2]
|
1110 |
|
1111 |
# Resize mask to match original image
|