Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -823,78 +823,146 @@ def draw_single_polygon(poly, image_rgb, scaling_factor, image_height, color=(0,
|
|
| 823 |
import numpy as np
|
| 824 |
import cv2
|
| 825 |
|
| 826 |
-
def draw_and_pad(polygons_inch, scaling_factor, boundary_polygon, padding=50,
|
| 827 |
-
|
| 828 |
-
|
| 829 |
-
|
| 830 |
|
| 831 |
-
|
| 832 |
-
|
| 833 |
|
| 834 |
-
|
| 835 |
-
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
|
| 847 |
-
|
| 848 |
|
| 849 |
-
|
| 850 |
-
|
| 851 |
-
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
-
|
| 858 |
-
|
| 859 |
-
|
| 860 |
|
| 861 |
-
|
| 862 |
-
|
| 863 |
-
|
| 864 |
|
| 865 |
-
|
| 866 |
-
|
| 867 |
-
|
| 868 |
-
|
| 869 |
-
|
| 870 |
-
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
|
| 875 |
|
| 876 |
-
|
| 877 |
-
|
| 878 |
|
| 879 |
-
|
| 880 |
-
|
| 881 |
-
|
| 882 |
-
|
| 883 |
-
|
| 884 |
-
|
| 885 |
-
|
| 886 |
-
|
| 887 |
|
| 888 |
-
|
| 889 |
-
|
| 890 |
-
|
| 891 |
-
|
| 892 |
-
|
| 893 |
-
|
| 894 |
-
|
| 895 |
-
|
| 896 |
|
| 897 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 898 |
|
| 899 |
# ---------------------
|
| 900 |
# Main Predict Function with Finger Cut Clearance, Boundary Box, Annotation and Sharpness Enhancement
|
|
@@ -1149,7 +1217,7 @@ def predict(
|
|
| 1149 |
if boundary_polygon is not None and poly == boundary_polygon:
|
| 1150 |
continue
|
| 1151 |
draw_single_polygon(poly, output_img, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
| 1152 |
-
new_outlines= draw_and_pad(final_polygons_inch, scaling_factor,boundary_polygon
|
| 1153 |
|
| 1154 |
#draw_polygons_inch(final_polygons_inch, new_outlines, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
|
| 1155 |
import math
|
|
@@ -1175,27 +1243,29 @@ def predict(
|
|
| 1175 |
output_img[outline_mask > 0] = temp_img[outline_mask > 0]
|
| 1176 |
|
| 1177 |
# For new_outlines - simple, centered text
|
| 1178 |
-
font_scale =
|
| 1179 |
-
def optimal_font_dims(img, font_scale = 2e-3, thickness_scale = 5e-3):
|
| 1180 |
h, w, _ = img.shape
|
| 1181 |
font_scale = min(w, h) * font_scale
|
| 1182 |
thickness = math.ceil(min(w, h) * thickness_scale)
|
| 1183 |
return font_scale, thickness
|
| 1184 |
font_scale,thickness = optimal_font_dims(new_outlines)
|
| 1185 |
-
(text_width, text_height) = cv2.getTextSize(text,
|
| 1186 |
text_x = (canvas_width - text_width) // 2
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1187 |
# bottom_margin_px = int(0.25 / scaling_factor)
|
| 1188 |
# font_scale,_ = optimal_font_dims(new_outlines)
|
| 1189 |
-
text_y_outlines = int(canvas_height - (text_y_in + (0.75) / scaling_factor))
|
| 1190 |
|
| 1191 |
# First outline, then inner text
|
| 1192 |
-
cv2.putText(new_outlines, text, (text_x,
|
| 1193 |
-
cv2.putText(new_outlines, text, (text_x,
|
| 1194 |
|
| 1195 |
|
| 1196 |
outlines_color = cv2.cvtColor(new_outlines, cv2.COLOR_BGR2RGB)
|
| 1197 |
print("Total prediction time: {:.2f} seconds".format(time.time() - overall_start))
|
| 1198 |
-
|
| 1199 |
return (
|
| 1200 |
cv2.cvtColor(output_img, cv2.COLOR_BGR2RGB),
|
| 1201 |
outlines_color,
|
|
@@ -1227,8 +1297,8 @@ if __name__ == "__main__":
|
|
| 1227 |
gr.Textbox(label="Annotation (max 20 chars)", max_length=20, placeholder="Type up to 20 characters")
|
| 1228 |
],
|
| 1229 |
outputs=[
|
| 1230 |
-
gr.Image(label="Output Image"),
|
| 1231 |
-
gr.Image(label="Outlines of Objects"),
|
| 1232 |
gr.File(label="DXF file"),
|
| 1233 |
gr.Image(label="Mask"),
|
| 1234 |
gr.Textbox(label="Scaling Factor (inches/pixel)")
|
|
|
|
| 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=20,
|
| 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
|
|
|
|
| 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
|
|
|
|
| 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)")
|