Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -218,7 +218,7 @@ def shrink_bbox(image: np.ndarray, shrink_factor: float):
|
|
218 |
x1 = max(center_x - new_width // 2, 0)
|
219 |
y1 = max(center_y - new_height // 2, 0)
|
220 |
x2 = min(center_x + new_width // 2, width)
|
221 |
-
y2 = min(center_y +
|
222 |
return image[y1:y2, x1:x2]
|
223 |
|
224 |
def exclude_scaling_box(image: np.ndarray, bbox: np.ndarray, orig_size: tuple, processed_size: tuple, expansion_factor: float = 1.2) -> np.ndarray:
|
@@ -347,9 +347,9 @@ def save_dxf_spline(inflated_contours, scaling_factor, height, finger_clearance=
|
|
347 |
print(f"Skipping contour: {e}")
|
348 |
return doc, final_polygons_inch
|
349 |
|
350 |
-
def add_rectangular_boundary(doc, polygons_inch, boundary_length, boundary_width, offset_unit, annotation_text=""):
|
351 |
msp = doc.modelspace()
|
352 |
-
#
|
353 |
if offset_unit.lower() == "mm":
|
354 |
if boundary_length < 50:
|
355 |
boundary_length = boundary_length * 25.4
|
@@ -361,7 +361,7 @@ def add_rectangular_boundary(doc, polygons_inch, boundary_length, boundary_width
|
|
361 |
boundary_length_in = boundary_length
|
362 |
boundary_width_in = boundary_width
|
363 |
|
364 |
-
# Compute bounding box
|
365 |
min_x = float("inf")
|
366 |
min_y = float("inf")
|
367 |
max_x = -float("inf")
|
@@ -376,28 +376,34 @@ def add_rectangular_boundary(doc, polygons_inch, boundary_length, boundary_width
|
|
376 |
print("No tool polygons found, skipping boundary.")
|
377 |
return None
|
378 |
|
379 |
-
#
|
380 |
inner_width = max_x - min_x
|
381 |
inner_length = max_y - min_y
|
382 |
|
383 |
# Set clearance margins.
|
384 |
-
clearance_side = 0.25
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
#
|
390 |
-
if boundary_width_in <= inner_width + 2 * clearance_side or
|
391 |
-
boundary_length_in <= inner_length + clearance_top + clearance_bottom:
|
392 |
raise BoundaryOverlapError("Error: The specified boundary dimensions are too small and overlap with the inner contours. Please provide larger values.")
|
393 |
|
394 |
-
#
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
401 |
|
402 |
rect_coords = [(left, bottom), (right, bottom), (right, top), (left, top), (left, bottom)]
|
403 |
from shapely.geometry import Polygon as ShapelyPolygon
|
@@ -449,11 +455,11 @@ def predict(
|
|
449 |
except Exception:
|
450 |
raise ValueError("Invalid base64 image data")
|
451 |
|
452 |
-
# Apply sharpness enhancement.
|
453 |
if isinstance(image, np.ndarray):
|
454 |
pil_image = Image.fromarray(image)
|
455 |
-
Bright = ImageEnhance.Brightness(pil_image).enhance(
|
456 |
-
enhanced_image = ImageEnhance.Sharpness(Bright).enhance(0.5)
|
457 |
image = np.array(enhanced_image)
|
458 |
|
459 |
# ---------------------
|
@@ -607,7 +613,14 @@ def predict(
|
|
607 |
boundary_polygon = None
|
608 |
if add_boundary.lower() == "yes":
|
609 |
boundary_polygon = add_rectangular_boundary(
|
610 |
-
doc,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
611 |
)
|
612 |
if boundary_polygon is not None:
|
613 |
final_polygons_inch.append(boundary_polygon)
|
@@ -619,11 +632,8 @@ def predict(
|
|
619 |
# ---------------------
|
620 |
msp = doc.modelspace()
|
621 |
if annotation_text.strip():
|
622 |
-
# Use the inner contours bounding box computed earlier.
|
623 |
text_x = (inner_min_x + inner_max_x) / 2.0
|
624 |
text_height_dxf = 0.5
|
625 |
-
# Place the text so that its top edge is 0.125 inches below the inner tool contour.
|
626 |
-
# Since text height is 0.5 inches, the baseline is at inner_min_y - 0.125 - text_height_dxf.
|
627 |
text_y_dxf = inner_min_y - 0.125 - text_height_dxf
|
628 |
text_entity = msp.add_text(
|
629 |
annotation_text.strip(),
|
@@ -647,16 +657,10 @@ def predict(
|
|
647 |
draw_polygons_inch(final_polygons_inch, new_outlines, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
648 |
|
649 |
if annotation_text.strip():
|
650 |
-
|
651 |
-
# Text is 0.5 inches high, and its baseline is at inner_min_y - 0.125 - 0.5.
|
652 |
-
text_height_cv = 0.5 # logical height in inches
|
653 |
-
# Calculate horizontal center (in inches) and convert to pixels
|
654 |
text_x_img = int(((inner_min_x + inner_max_x) / 2.0) / scaling_factor)
|
655 |
-
# Baseline position in inches:
|
656 |
text_y_in = inner_min_y - 0.125 - text_height_cv
|
657 |
-
# Convert the baseline from inches to pixel coordinate
|
658 |
text_y_img = int(processed_size[0] - (text_y_in / scaling_factor))
|
659 |
-
# Shift left to center the text approximately
|
660 |
org = (text_x_img - int(len(annotation_text.strip()) * 6), text_y_img)
|
661 |
|
662 |
cv2.putText(
|
@@ -664,7 +668,7 @@ def predict(
|
|
664 |
annotation_text.strip(),
|
665 |
org,
|
666 |
cv2.FONT_HERSHEY_SIMPLEX,
|
667 |
-
1.3,
|
668 |
(0, 0, 255),
|
669 |
3,
|
670 |
cv2.LINE_AA
|
|
|
218 |
x1 = max(center_x - new_width // 2, 0)
|
219 |
y1 = max(center_y - new_height // 2, 0)
|
220 |
x2 = min(center_x + new_width // 2, width)
|
221 |
+
y2 = min(center_y + new_height // 2, height)
|
222 |
return image[y1:y2, x1:x2]
|
223 |
|
224 |
def exclude_scaling_box(image: np.ndarray, bbox: np.ndarray, orig_size: tuple, processed_size: tuple, expansion_factor: float = 1.2) -> np.ndarray:
|
|
|
347 |
print(f"Skipping contour: {e}")
|
348 |
return doc, final_polygons_inch
|
349 |
|
350 |
+
def add_rectangular_boundary(doc, polygons_inch, boundary_length, boundary_width, offset_unit, annotation_text="", image_height_in=None, image_width_in=None):
|
351 |
msp = doc.modelspace()
|
352 |
+
# Convert from mm if necessary.
|
353 |
if offset_unit.lower() == "mm":
|
354 |
if boundary_length < 50:
|
355 |
boundary_length = boundary_length * 25.4
|
|
|
361 |
boundary_length_in = boundary_length
|
362 |
boundary_width_in = boundary_width
|
363 |
|
364 |
+
# Compute bounding box of inner contours.
|
365 |
min_x = float("inf")
|
366 |
min_y = float("inf")
|
367 |
max_x = -float("inf")
|
|
|
376 |
print("No tool polygons found, skipping boundary.")
|
377 |
return None
|
378 |
|
379 |
+
# Compute inner bounding box dimensions.
|
380 |
inner_width = max_x - min_x
|
381 |
inner_length = max_y - min_y
|
382 |
|
383 |
# Set clearance margins.
|
384 |
+
clearance_side = 0.25 # left/right clearance
|
385 |
+
clearance_tb = 0.25 # top/bottom clearance
|
386 |
+
if annotation_text.strip():
|
387 |
+
clearance_tb = 0.75
|
388 |
+
|
389 |
+
# Check if the boundary dimensions are at least larger than the inner box plus clearance.
|
390 |
+
if boundary_width_in <= inner_width + 2 * clearance_side or boundary_length_in <= inner_length + 2 * clearance_tb:
|
|
|
391 |
raise BoundaryOverlapError("Error: The specified boundary dimensions are too small and overlap with the inner contours. Please provide larger values.")
|
392 |
|
393 |
+
# Check if boundary exceeds image limits (for example, 1 inch less than the image dimensions).
|
394 |
+
if image_height_in is not None and image_width_in is not None:
|
395 |
+
if boundary_length_in > (image_height_in - 1) or boundary_width_in > (image_width_in - 1):
|
396 |
+
raise BoundaryExceedsError("Error: The specified boundary dimensions exceed the allowed image dimensions. Please enter smaller values.")
|
397 |
+
|
398 |
+
# Calculate the center of the inner contours.
|
399 |
+
center_x = (min_x + max_x) / 2
|
400 |
+
center_y = (min_y + max_y) / 2
|
401 |
+
|
402 |
+
# Draw rectangle centered at (center_x, center_y).
|
403 |
+
left = center_x - boundary_width_in / 2
|
404 |
+
right = center_x + boundary_width_in / 2
|
405 |
+
bottom = center_y - boundary_length_in / 2
|
406 |
+
top = center_y + boundary_length_in / 2
|
407 |
|
408 |
rect_coords = [(left, bottom), (right, bottom), (right, top), (left, top), (left, bottom)]
|
409 |
from shapely.geometry import Polygon as ShapelyPolygon
|
|
|
455 |
except Exception:
|
456 |
raise ValueError("Invalid base64 image data")
|
457 |
|
458 |
+
# Apply brightness and sharpness enhancement.
|
459 |
if isinstance(image, np.ndarray):
|
460 |
pil_image = Image.fromarray(image)
|
461 |
+
Bright = ImageEnhance.Brightness(pil_image).enhance(1)
|
462 |
+
enhanced_image = ImageEnhance.Sharpness(Bright).enhance(0.5)
|
463 |
image = np.array(enhanced_image)
|
464 |
|
465 |
# ---------------------
|
|
|
613 |
boundary_polygon = None
|
614 |
if add_boundary.lower() == "yes":
|
615 |
boundary_polygon = add_rectangular_boundary(
|
616 |
+
doc,
|
617 |
+
final_polygons_inch,
|
618 |
+
boundary_length,
|
619 |
+
boundary_width,
|
620 |
+
offset_unit,
|
621 |
+
annotation_text,
|
622 |
+
image_height_in=shrunked_img.shape[0] * scaling_factor,
|
623 |
+
image_width_in=shrunked_img.shape[1] * scaling_factor
|
624 |
)
|
625 |
if boundary_polygon is not None:
|
626 |
final_polygons_inch.append(boundary_polygon)
|
|
|
632 |
# ---------------------
|
633 |
msp = doc.modelspace()
|
634 |
if annotation_text.strip():
|
|
|
635 |
text_x = (inner_min_x + inner_max_x) / 2.0
|
636 |
text_height_dxf = 0.5
|
|
|
|
|
637 |
text_y_dxf = inner_min_y - 0.125 - text_height_dxf
|
638 |
text_entity = msp.add_text(
|
639 |
annotation_text.strip(),
|
|
|
657 |
draw_polygons_inch(final_polygons_inch, new_outlines, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
658 |
|
659 |
if annotation_text.strip():
|
660 |
+
text_height_cv = 0.5
|
|
|
|
|
|
|
661 |
text_x_img = int(((inner_min_x + inner_max_x) / 2.0) / scaling_factor)
|
|
|
662 |
text_y_in = inner_min_y - 0.125 - text_height_cv
|
|
|
663 |
text_y_img = int(processed_size[0] - (text_y_in / scaling_factor))
|
|
|
664 |
org = (text_x_img - int(len(annotation_text.strip()) * 6), text_y_img)
|
665 |
|
666 |
cv2.putText(
|
|
|
668 |
annotation_text.strip(),
|
669 |
org,
|
670 |
cv2.FONT_HERSHEY_SIMPLEX,
|
671 |
+
1.3,
|
672 |
(0, 0, 255),
|
673 |
3,
|
674 |
cv2.LINE_AA
|