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
|