Nighty3912 commited on
Commit
35ee901
·
verified ·
1 Parent(s): b342278

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +304 -88
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 as ShapelyPolygon
680
- boundary_polygon = ShapelyPolygon(rect_coords)
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
- new_outlines = np.ones_like(output_img) * 255
960
- draw_polygons_inch(final_polygons_inch, new_outlines, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
961
-
 
 
 
 
 
 
962
  if annotation_text.strip():
 
 
 
 
 
963
  if boundary_polygon is not None:
964
- text_height_cv = 0.75
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
- # Method 2: Use two different thicknesses
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
- cv2.putText(
1013
- new_outlines,
1014
- annotation_text.strip().upper(),
1015
- org,
1016
- cv2.FONT_HERSHEY_SIMPLEX,
1017
- 2,
1018
- (255, 255, 255), # Inner text in white
1019
- 2, # Thinner inner part
1020
- cv2.LINE_AA
1021
- )
1022
- else:
1023
- text_height_cv = 0.75
1024
- text_x_img = int(((inner_min_x + inner_max_x) / 2.0) / scaling_factor)
1025
- text_y_in = inner_min_y - 0.125 - text_height_cv
1026
- text_y_img = int(processed_size[0] - (text_y_in / scaling_factor))
1027
- org = (text_x_img - int(len(annotation_text.strip()) * 6), text_y_img)
1028
-
1029
- cv2.putText(
1030
- output_img,
1031
- annotation_text.strip(),
1032
- org,
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)")