Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -676,8 +676,8 @@ def add_rectangular_boundary(doc, polygons_inch, boundary_length, boundary_width
|
|
676 |
top = center_y + boundary_length_in / 2
|
677 |
|
678 |
rect_coords = [(left, bottom), (right, bottom), (right, top), (left, top), (left, bottom)]
|
679 |
-
from shapely.geometry import Polygon
|
680 |
-
boundary_polygon =
|
681 |
msp.add_lwpolyline(rect_coords, close=True, dxfattribs={"layer": "BOUNDARY"})
|
682 |
|
683 |
text_top = boundary_polygon.bounds[1] + 1
|
@@ -708,6 +708,262 @@ def draw_single_polygon(poly, image_rgb, scaling_factor, image_height, color=(0,
|
|
708 |
pts_px = np.array(pts_px, dtype=np.int32)
|
709 |
cv2.polylines(image_rgb, [pts_px], isClosed=True, color=color, thickness=thickness, lineType=cv2.LINE_AA)
|
710 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
711 |
# ---------------------
|
712 |
# Main Predict Function with Finger Cut Clearance, Boundary Box, Annotation and Sharpness Enhancement
|
713 |
# ---------------------
|
@@ -928,11 +1184,11 @@ def predict(
|
|
928 |
|
929 |
# Calculate actual text width from the path's bounds
|
930 |
text_bbox = path.bbox(paths)
|
931 |
-
text_width = text_bbox[2] - text_bbox[0] # xmax - xmin
|
932 |
-
|
933 |
# Calculate center point of inner tool contours
|
934 |
center_x = (inner_min_x + inner_max_x) / 2.0
|
935 |
-
|
936 |
# Calculate starting x position for truly centered text
|
937 |
text_x = center_x - (text_width / 2.0)
|
938 |
|
@@ -955,101 +1211,61 @@ def predict(
|
|
955 |
# ---------------------
|
956 |
# 9) For the preview images, draw the polygons and place text similarly
|
957 |
# ---------------------
|
958 |
-
draw_polygons_inch(final_polygons_inch, output_img, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
959 |
-
|
960 |
-
|
961 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
962 |
if annotation_text.strip():
|
|
|
|
|
|
|
|
|
|
|
963 |
if boundary_polygon is not None:
|
964 |
-
|
965 |
text_x_img = int(((inner_min_x + inner_max_x) / 2.0) / scaling_factor)
|
966 |
text_y_in = boundary_polygon.bounds[1] + 0.25
|
967 |
text_y_img = int(processed_size[0] - (text_y_in / scaling_factor))
|
968 |
org = (text_x_img - int(len(annotation_text.strip()) * 6), text_y_img)
|
969 |
-
|
970 |
-
#
|
971 |
-
# Draw thicker outline
|
972 |
temp_img = np.zeros_like(output_img)
|
973 |
-
|
974 |
-
cv2.putText(
|
975 |
-
temp_img,
|
976 |
-
annotation_text.strip().upper(),
|
977 |
-
org,
|
978 |
-
cv2.FONT_HERSHEY_SIMPLEX,
|
979 |
-
2,
|
980 |
-
(0, 0, 255), # Red color
|
981 |
-
4, # Thicker outline
|
982 |
-
cv2.LINE_AA
|
983 |
-
)
|
984 |
-
|
985 |
-
cv2.putText(
|
986 |
-
temp_img,
|
987 |
-
annotation_text.strip().upper(),
|
988 |
-
org,
|
989 |
-
cv2.FONT_HERSHEY_SIMPLEX,
|
990 |
-
2,
|
991 |
-
(0, 0, 0), # Black to create hole
|
992 |
-
2, # Thinner inner part
|
993 |
-
cv2.LINE_AA
|
994 |
-
)
|
995 |
-
|
996 |
outline_mask = cv2.cvtColor(temp_img, cv2.COLOR_BGR2GRAY)
|
997 |
_, outline_mask = cv2.threshold(outline_mask, 1, 255, cv2.THRESH_BINARY)
|
998 |
-
|
999 |
output_img[outline_mask > 0] = temp_img[outline_mask > 0]
|
1000 |
-
|
1001 |
-
cv2.putText(
|
1002 |
-
new_outlines,
|
1003 |
-
annotation_text.strip().upper(),
|
1004 |
-
org,
|
1005 |
-
cv2.FONT_HERSHEY_SIMPLEX,
|
1006 |
-
2,
|
1007 |
-
(0, 0, 255), # Red color
|
1008 |
-
4, # Thicker outline
|
1009 |
-
cv2.LINE_AA
|
1010 |
-
)
|
1011 |
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
)
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
cv2.FONT_HERSHEY_SIMPLEX,
|
1034 |
-
1.2,
|
1035 |
-
(0, 0, 255),
|
1036 |
-
2,
|
1037 |
-
cv2.LINE_AA
|
1038 |
-
)
|
1039 |
-
cv2.putText(
|
1040 |
-
new_outlines,
|
1041 |
-
annotation_text.strip(),
|
1042 |
-
org,
|
1043 |
-
cv2.FONT_HERSHEY_SIMPLEX,
|
1044 |
-
1.2,
|
1045 |
-
(0, 0, 255),
|
1046 |
-
2,
|
1047 |
-
cv2.LINE_AA
|
1048 |
-
)
|
1049 |
|
1050 |
outlines_color = cv2.cvtColor(new_outlines, cv2.COLOR_BGR2RGB)
|
1051 |
print("Total prediction time: {:.2f} seconds".format(time.time() - overall_start))
|
1052 |
-
|
1053 |
return (
|
1054 |
cv2.cvtColor(output_img, cv2.COLOR_BGR2RGB),
|
1055 |
outlines_color,
|
@@ -1081,8 +1297,8 @@ if __name__ == "__main__":
|
|
1081 |
gr.Textbox(label="Annotation (max 20 chars)", max_length=20, placeholder="Type up to 20 characters")
|
1082 |
],
|
1083 |
outputs=[
|
1084 |
-
gr.Image(label="Output Image"),
|
1085 |
-
gr.Image(label="Outlines of Objects"),
|
1086 |
gr.File(label="DXF file"),
|
1087 |
gr.Image(label="Mask"),
|
1088 |
gr.Textbox(label="Scaling Factor (inches/pixel)")
|
|
|
676 |
top = center_y + boundary_length_in / 2
|
677 |
|
678 |
rect_coords = [(left, bottom), (right, bottom), (right, top), (left, top), (left, bottom)]
|
679 |
+
from shapely.geometry import Polygon
|
680 |
+
boundary_polygon = Polygon(rect_coords)
|
681 |
msp.add_lwpolyline(rect_coords, close=True, dxfattribs={"layer": "BOUNDARY"})
|
682 |
|
683 |
text_top = boundary_polygon.bounds[1] + 1
|
|
|
708 |
pts_px = np.array(pts_px, dtype=np.int32)
|
709 |
cv2.polylines(image_rgb, [pts_px], isClosed=True, color=color, thickness=thickness, lineType=cv2.LINE_AA)
|
710 |
|
711 |
+
# def draw_and_pad(polygons_inch, scaling_factor,boundary_polygon, padding=50,
|
712 |
+
# color=(0,0,255), thickness=2):
|
713 |
+
# """
|
714 |
+
# - polygons_inch: list of Shapely Polygons in inch units (already including boundary).
|
715 |
+
# - scaling_factor: inches per pixel.
|
716 |
+
# - padding: padding in pixels.
|
717 |
+
# """
|
718 |
+
# all_x = []
|
719 |
+
# all_y = []
|
720 |
+
# pixel_polys = []
|
721 |
+
|
722 |
+
# # 1) Convert to pixel coords and collect bounds
|
723 |
+
# for poly in polygons_inch:
|
724 |
+
# coords = list(poly.exterior.coords)
|
725 |
+
# pts = []
|
726 |
+
# for x_in, y_in in coords:
|
727 |
+
# px = int(round(x_in / scaling_factor))
|
728 |
+
# py = int(round(y_in / scaling_factor))
|
729 |
+
# pts.append([px, py])
|
730 |
+
# all_x.append(px)
|
731 |
+
# all_y.append(py)
|
732 |
+
# pixel_polys.append(np.array(pts, dtype=np.int32))
|
733 |
+
|
734 |
+
# # 2) Compute canvas size
|
735 |
+
|
736 |
+
# min_x, max_x = min(all_x), max(all_x)
|
737 |
+
# min_y, max_y = min(all_y), max(all_y)
|
738 |
+
# width = max_x - min_x + 1
|
739 |
+
# height = max_y - min_y + 1
|
740 |
+
|
741 |
+
# # 3) Create blank white canvas
|
742 |
+
# canvas = 255 * np.ones((height, width, 3), dtype=np.uint8)
|
743 |
+
|
744 |
+
# # 4) Draw each polygon, flipping y within the local box
|
745 |
+
# for pts in pixel_polys:
|
746 |
+
# # Offset so min corner is (0,0)
|
747 |
+
# pts_off = pts - np.array([[min_x, min_y]])
|
748 |
+
# # Flip y: new_y = height-1 - old_y
|
749 |
+
# pts_off[:,1] = (height - 1) - pts_off[:,1]
|
750 |
+
# cv2.polylines(canvas, [pts_off], isClosed=True,
|
751 |
+
# color=color, thickness=thickness, lineType=cv2.LINE_AA)
|
752 |
+
|
753 |
+
# # 5) Pad the canvas
|
754 |
+
|
755 |
+
# padded = cv2.copyMakeBorder(
|
756 |
+
# canvas,
|
757 |
+
# top=padding, bottom=padding,
|
758 |
+
# left=padding, right=padding,
|
759 |
+
# borderType=cv2.BORDER_CONSTANT,
|
760 |
+
# value=[255,255,255]
|
761 |
+
# )
|
762 |
+
# return padded
|
763 |
+
|
764 |
+
# import numpy as np
|
765 |
+
# import cv2
|
766 |
+
|
767 |
+
# def draw_and_pad(polygons_inch, scaling_factor, boundary_polygon, padding=50,
|
768 |
+
# color=(0,0,255), thickness=2):
|
769 |
+
# """
|
770 |
+
# - polygons_inch: list of Shapely Polygons in inch units.
|
771 |
+
# - scaling_factor: inches per pixel.
|
772 |
+
# - boundary_polygon: the Shapely boundary polygon, or None.
|
773 |
+
# - padding: base padding in pixels.
|
774 |
+
# """
|
775 |
+
# all_x, all_y = [], []
|
776 |
+
# pixel_polys = []
|
777 |
+
|
778 |
+
# # 1) Convert to pixel coords and collect bounds
|
779 |
+
# for poly in polygons_inch:
|
780 |
+
# coords = list(poly.exterior.coords)
|
781 |
+
# pts = []
|
782 |
+
# for x_in, y_in in coords:
|
783 |
+
# px = int(round(x_in / scaling_factor))
|
784 |
+
# py = int(round(y_in / scaling_factor))
|
785 |
+
# pts.append([px, py])
|
786 |
+
# all_x.append(px)
|
787 |
+
# all_y.append(py)
|
788 |
+
# pixel_polys.append(np.array(pts, dtype=np.int32))
|
789 |
+
|
790 |
+
# # 2) Compute canvas size
|
791 |
+
# min_x, max_x = min(all_x), max(all_x)
|
792 |
+
# min_y, max_y = min(all_y), max(all_y)
|
793 |
+
# width = max_x - min_x + 1
|
794 |
+
# height = max_y - min_y + 1
|
795 |
+
|
796 |
+
# # 3) Create blank white canvas
|
797 |
+
# canvas = 255 * np.ones((height, width, 3), dtype=np.uint8)
|
798 |
+
|
799 |
+
# # 4) Draw each polygon, flipping y within the local box
|
800 |
+
# for pts in pixel_polys:
|
801 |
+
# pts_off = pts - np.array([[min_x, min_y]])
|
802 |
+
# pts_off[:,1] = (height - 1) - pts_off[:,1]
|
803 |
+
# cv2.polylines(canvas, [pts_off], isClosed=True,
|
804 |
+
# color=color, thickness=thickness, lineType=cv2.LINE_AA)
|
805 |
+
|
806 |
+
# # 5) Decide padding amounts
|
807 |
+
# if boundary_polygon is not None:
|
808 |
+
# top = bottom = left = right = padding
|
809 |
+
# else:
|
810 |
+
# # Double the padding if there's no boundary, to avoid clipping
|
811 |
+
# top = bottom = left = right = padding * 2
|
812 |
+
|
813 |
+
# # 6) Pad the canvas
|
814 |
+
# padded = cv2.copyMakeBorder(
|
815 |
+
# canvas,
|
816 |
+
# top=top, bottom=bottom,
|
817 |
+
# left=left, right=right,
|
818 |
+
# borderType=cv2.BORDER_CONSTANT,
|
819 |
+
# value=[255,255,255]
|
820 |
+
# )
|
821 |
+
# return padded
|
822 |
+
|
823 |
+
import numpy as np
|
824 |
+
import cv2
|
825 |
+
|
826 |
+
# def draw_and_pad(polygons_inch, scaling_factor, boundary_polygon, padding=50,
|
827 |
+
# color=(0, 0, 255), thickness=2):
|
828 |
+
# """
|
829 |
+
# Draws Shapely Polygons (in inch units) on a white canvas.
|
830 |
+
|
831 |
+
# When boundary_polygon is None, the computed bounds are expanded by the padding value
|
832 |
+
# so that the drawn contours are not clipped at the edges after adding the final padding.
|
833 |
+
|
834 |
+
# Arguments:
|
835 |
+
# polygons_inch: list of Shapely Polygons in inch units (already including boundary).
|
836 |
+
# scaling_factor: inches per pixel.
|
837 |
+
# boundary_polygon: the Shapely boundary polygon, or None.
|
838 |
+
# padding: padding in pixels.
|
839 |
+
# color: color of the drawn polylines (in BGR format).
|
840 |
+
# thickness: line thickness.
|
841 |
+
|
842 |
+
# Returns:
|
843 |
+
# padded: an image (numpy array) of the drawn polygons with an external white border.
|
844 |
+
# """
|
845 |
+
# all_x = []
|
846 |
+
# all_y = []
|
847 |
+
# pixel_polys = []
|
848 |
+
|
849 |
+
# # 1) Convert each polygon to pixel coordinates and compute overall bounds.
|
850 |
+
# for poly in polygons_inch:
|
851 |
+
# coords = list(poly.exterior.coords)
|
852 |
+
# pts = []
|
853 |
+
# for x_in, y_in in coords:
|
854 |
+
# px = int(round(x_in / scaling_factor))
|
855 |
+
# py = int(round(y_in / scaling_factor))
|
856 |
+
# pts.append([px, py])
|
857 |
+
# all_x.append(px)
|
858 |
+
# all_y.append(py)
|
859 |
+
# pixel_polys.append(np.array(pts, dtype=np.int32))
|
860 |
+
|
861 |
+
# # 2) Compute the basic canvas size from the polygon bounds.
|
862 |
+
# min_x, max_x = min(all_x), max(all_x)
|
863 |
+
# min_y, max_y = min(all_y), max(all_y)
|
864 |
+
|
865 |
+
# # If no boundary polygon is provided, expand the bounds to add margin
|
866 |
+
# # so that later when we pad externally, the contours do not get clipped.
|
867 |
+
# if boundary_polygon is None:
|
868 |
+
# min_x -= padding
|
869 |
+
# max_x += padding
|
870 |
+
# min_y -= padding
|
871 |
+
# max_y += padding
|
872 |
+
|
873 |
+
# width = max_x - min_x + 1
|
874 |
+
# height = max_y - min_y + 1
|
875 |
+
|
876 |
+
# # 3) Create a blank white canvas.
|
877 |
+
# canvas = 255 * np.ones((height, width, 3), dtype=np.uint8)
|
878 |
+
|
879 |
+
# # 4) Draw each polygon, flipping the y-coordinates to match image coordinates.
|
880 |
+
# for pts in pixel_polys:
|
881 |
+
# # Offset so the minimum corner becomes (0,0) on canvas.
|
882 |
+
# pts_off = pts - np.array([[min_x, min_y]])
|
883 |
+
# # Flip y: image coordinates have (0,0) at the top-left.
|
884 |
+
# pts_off[:, 1] = (height - 1) - pts_off[:, 1]
|
885 |
+
# cv2.polylines(canvas, [pts_off], isClosed=True,
|
886 |
+
# color=color, thickness=thickness, lineType=cv2.LINE_AA)
|
887 |
+
|
888 |
+
# # 5) Finally, add external padding on all sides.
|
889 |
+
# padded = cv2.copyMakeBorder(
|
890 |
+
# canvas,
|
891 |
+
# top=padding, bottom=padding,
|
892 |
+
# left=padding, right=padding,
|
893 |
+
# borderType=cv2.BORDER_CONSTANT,
|
894 |
+
# value=[255, 255, 255]
|
895 |
+
# )
|
896 |
+
|
897 |
+
# return padded
|
898 |
+
|
899 |
+
import numpy as np
|
900 |
+
import cv2
|
901 |
+
from shapely.geometry import Polygon
|
902 |
+
|
903 |
+
import numpy as np
|
904 |
+
import cv2
|
905 |
+
from shapely.geometry import Polygon
|
906 |
+
|
907 |
+
def draw_and_pad(polygons_inch,
|
908 |
+
scaling_factor, # inches per pixel
|
909 |
+
boundary_polygon=None,
|
910 |
+
max_res=1024,
|
911 |
+
simplify_tol_px=1.0,
|
912 |
+
padding_px=50,
|
913 |
+
color=(0,0,255),
|
914 |
+
thickness=2):
|
915 |
+
# 1) Simplify & collect raw coords in inches
|
916 |
+
all_x, all_y = [], []
|
917 |
+
simple_polys = []
|
918 |
+
for poly in polygons_inch:
|
919 |
+
tol_in = simplify_tol_px * scaling_factor / max_res
|
920 |
+
simp = poly.simplify(tolerance=tol_in, preserve_topology=True)
|
921 |
+
coords = np.array(simp.exterior.coords) # (N,2) in inches
|
922 |
+
all_x.extend(coords[:,0])
|
923 |
+
all_y.extend(coords[:,1])
|
924 |
+
simple_polys.append(coords)
|
925 |
+
|
926 |
+
# 2) Compute full‑res pixel extents
|
927 |
+
min_x_in, max_x_in = min(all_x), max(all_x)
|
928 |
+
min_y_in, max_y_in = min(all_y), max(all_y)
|
929 |
+
w_in = (max_x_in - min_x_in) if boundary_polygon is None else (max_x_in - min_x_in)
|
930 |
+
h_in = (max_y_in - min_y_in) if boundary_polygon is None else (max_y_in - min_y_in)
|
931 |
+
full_w_px = np.ceil(w_in / scaling_factor)
|
932 |
+
full_h_px = np.ceil(h_in / scaling_factor)
|
933 |
+
|
934 |
+
# 3) Compute preview scale ≤1 so dims ≤ max_res
|
935 |
+
scale = min(max_res / full_w_px, max_res / full_h_px, 1.0)
|
936 |
+
|
937 |
+
# 4) Compute preview dims & allocate _fully‐padded_ canvas
|
938 |
+
W = int(np.ceil(full_w_px * scale))
|
939 |
+
H = int(np.ceil(full_h_px * scale))
|
940 |
+
PW, PH = W + 2*padding_px, H + 2*padding_px
|
941 |
+
canvas = 255 * np.ones((PH, PW, 3), dtype=np.uint8)
|
942 |
+
|
943 |
+
# Precompute offsets (in preview px) of the “world origin”
|
944 |
+
off_x = int(np.floor(min_x_in / scaling_factor * scale))
|
945 |
+
off_y = int(np.floor(min_y_in / scaling_factor * scale))
|
946 |
+
|
947 |
+
# 5) Draw each polygon, now fully inside the padded canvas
|
948 |
+
for coords in simple_polys:
|
949 |
+
# inch→preview‐px transform
|
950 |
+
pts = ((coords / scaling_factor) * scale).round().astype(int)
|
951 |
+
# shift by both the minimum and the padding:
|
952 |
+
pts[:,0] = pts[:,0] - off_x + padding_px
|
953 |
+
pts[:,1] = pts[:,1] - off_y + padding_px
|
954 |
+
# flip Y into image coords
|
955 |
+
pts[:,1] = PH - 1 - pts[:,1]
|
956 |
+
cv2.polylines(canvas,
|
957 |
+
[pts],
|
958 |
+
isClosed=True,
|
959 |
+
color=color,
|
960 |
+
thickness=thickness,
|
961 |
+
lineType=cv2.LINE_AA)
|
962 |
+
|
963 |
+
return canvas, scale, off_y, padding_px, PH
|
964 |
+
|
965 |
+
|
966 |
+
|
967 |
# ---------------------
|
968 |
# Main Predict Function with Finger Cut Clearance, Boundary Box, Annotation and Sharpness Enhancement
|
969 |
# ---------------------
|
|
|
1184 |
|
1185 |
# Calculate actual text width from the path's bounds
|
1186 |
text_bbox = path.bbox(paths)
|
1187 |
+
#text_width = text_bbox[2] - text_bbox[0] # xmax - xmin
|
1188 |
+
#text_width = text_bbox.width
|
1189 |
# Calculate center point of inner tool contours
|
1190 |
center_x = (inner_min_x + inner_max_x) / 2.0
|
1191 |
+
text_width = text_bbox.extmax.x - text_bbox.extmin.x
|
1192 |
# Calculate starting x position for truly centered text
|
1193 |
text_x = center_x - (text_width / 2.0)
|
1194 |
|
|
|
1211 |
# ---------------------
|
1212 |
# 9) For the preview images, draw the polygons and place text similarly
|
1213 |
# ---------------------
|
1214 |
+
#draw_polygons_inch(final_polygons_inch, output_img, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
1215 |
+
for poly in final_polygons_inch:
|
1216 |
+
# Skip the boundary polygon
|
1217 |
+
if boundary_polygon is not None and poly == boundary_polygon:
|
1218 |
+
continue
|
1219 |
+
draw_single_polygon(poly, output_img, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
1220 |
+
new_outlines,preview_scale, off_y, padding_px, PH= draw_and_pad(final_polygons_inch, scaling_factor,boundary_polygon)
|
1221 |
+
|
1222 |
+
#draw_polygons_inch(final_polygons_inch, new_outlines, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
1223 |
+
import math
|
1224 |
if annotation_text.strip():
|
1225 |
+
# Common variables
|
1226 |
+
font = cv2.FONT_HERSHEY_SIMPLEX
|
1227 |
+
text = annotation_text.strip().upper()
|
1228 |
+
canvas_height, canvas_width = new_outlines.shape[:2]
|
1229 |
+
|
1230 |
if boundary_polygon is not None:
|
1231 |
+
# Keep original code for output_img
|
1232 |
text_x_img = int(((inner_min_x + inner_max_x) / 2.0) / scaling_factor)
|
1233 |
text_y_in = boundary_polygon.bounds[1] + 0.25
|
1234 |
text_y_img = int(processed_size[0] - (text_y_in / scaling_factor))
|
1235 |
org = (text_x_img - int(len(annotation_text.strip()) * 6), text_y_img)
|
1236 |
+
|
1237 |
+
# Process for output_img with mask (keeping your original code)
|
|
|
1238 |
temp_img = np.zeros_like(output_img)
|
1239 |
+
cv2.putText(temp_img, text, org, font, 2, (0, 0, 255), 4, cv2.LINE_AA)
|
1240 |
+
cv2.putText(temp_img, text, org, font, 2, (255, 255, 255), 2, cv2.LINE_AA)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1241 |
outline_mask = cv2.cvtColor(temp_img, cv2.COLOR_BGR2GRAY)
|
1242 |
_, outline_mask = cv2.threshold(outline_mask, 1, 255, cv2.THRESH_BINARY)
|
|
|
1243 |
output_img[outline_mask > 0] = temp_img[outline_mask > 0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1244 |
|
1245 |
+
# For new_outlines - simple, centered text
|
1246 |
+
def optimal_font_dims(img, font_scale = 1e-3, thickness_scale = 2e-3):
|
1247 |
+
h, w, _ = img.shape
|
1248 |
+
font_scale = min(w, h) * font_scale
|
1249 |
+
thickness = math.ceil(min(w, h) * thickness_scale)
|
1250 |
+
return font_scale, thickness
|
1251 |
+
font_scale,thickness = optimal_font_dims(new_outlines)
|
1252 |
+
(text_width, text_height), baseline = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, font_scale, thickness)
|
1253 |
+
text_x = (canvas_width - text_width) // 2
|
1254 |
+
raw_y = (text_y_in / scaling_factor) * preview_scale
|
1255 |
+
y1 = raw_y - off_y + padding_px
|
1256 |
+
text_y_px = int(round(PH - 1 - y1))
|
1257 |
+
text_y_px_adjusted = text_y_px - baseline
|
1258 |
+
# bottom_margin_px = int(0.25 / scaling_factor)
|
1259 |
+
# font_scale,_ = optimal_font_dims(new_outlines)
|
1260 |
+
#text_y_outlines = int(canvas_height - (text_y_in + (0.75) / scaling_factor))
|
1261 |
+
|
1262 |
+
# First outline, then inner text
|
1263 |
+
cv2.putText(new_outlines, text, (text_x, text_y_px_adjusted), font, font_scale, (0, 0, 255), thickness+2, cv2.LINE_AA)
|
1264 |
+
cv2.putText(new_outlines, text, (text_x, text_y_px_adjusted), font, font_scale, (255, 255, 255), thickness-1, cv2.LINE_AA)
|
1265 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1266 |
|
1267 |
outlines_color = cv2.cvtColor(new_outlines, cv2.COLOR_BGR2RGB)
|
1268 |
print("Total prediction time: {:.2f} seconds".format(time.time() - overall_start))
|
|
|
1269 |
return (
|
1270 |
cv2.cvtColor(output_img, cv2.COLOR_BGR2RGB),
|
1271 |
outlines_color,
|
|
|
1297 |
gr.Textbox(label="Annotation (max 20 chars)", max_length=20, placeholder="Type up to 20 characters")
|
1298 |
],
|
1299 |
outputs=[
|
1300 |
+
gr.Image(format="png",label="Output Image"),
|
1301 |
+
gr.Image(format="png",label="Outlines of Objects"),
|
1302 |
gr.File(label="DXF file"),
|
1303 |
gr.Image(label="Mask"),
|
1304 |
gr.Textbox(label="Scaling Factor (inches/pixel)")
|