Nighty3912 commited on
Commit
6fa8a4a
·
verified ·
1 Parent(s): b932751

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +230 -84
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,194 @@ 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
  # ---------------------
@@ -955,97 +1143,55 @@ 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))
@@ -1081,8 +1227,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
  # ---------------------
900
  # Main Predict Function with Finger Cut Clearance, Boundary Box, Annotation and Sharpness Enhancement
901
  # ---------------------
 
1143
  # ---------------------
1144
  # 9) For the preview images, draw the polygons and place text similarly
1145
  # ---------------------
1146
+ #draw_polygons_inch(final_polygons_inch, output_img, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
1147
+ for poly in final_polygons_inch:
1148
+ # Skip the boundary polygon
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, padding=50)
1153
+
1154
+ #draw_polygons_inch(final_polygons_inch, new_outlines, scaling_factor, processed_size[0], color=(0, 0, 255), thickness=2)
1155
+ import math
1156
  if annotation_text.strip():
1157
+ # Common variables
1158
+ font = cv2.FONT_HERSHEY_SIMPLEX
1159
+ text = annotation_text.strip().upper()
1160
+ canvas_height, canvas_width = new_outlines.shape[:2]
1161
+
1162
  if boundary_polygon is not None:
1163
+ # Keep original code for output_img
1164
  text_x_img = int(((inner_min_x + inner_max_x) / 2.0) / scaling_factor)
1165
  text_y_in = boundary_polygon.bounds[1] + 0.25
1166
  text_y_img = int(processed_size[0] - (text_y_in / scaling_factor))
1167
  org = (text_x_img - int(len(annotation_text.strip()) * 6), text_y_img)
1168
+
1169
+ # Process for output_img with mask (keeping your original code)
 
1170
  temp_img = np.zeros_like(output_img)
1171
+ cv2.putText(temp_img, text, org, font, 2, (0, 0, 255), 4, cv2.LINE_AA)
1172
+ cv2.putText(temp_img, text, org, font, 2, (255, 255, 255), 2, cv2.LINE_AA)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1173
  outline_mask = cv2.cvtColor(temp_img, cv2.COLOR_BGR2GRAY)
1174
  _, outline_mask = cv2.threshold(outline_mask, 1, 255, cv2.THRESH_BINARY)
 
1175
  output_img[outline_mask > 0] = temp_img[outline_mask > 0]
 
 
 
 
 
 
 
 
 
 
 
1176
 
1177
+ # For new_outlines - simple, centered text
1178
+ font_scale = 1
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, font, font_scale, thickness)[0]
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, text_y_outlines), font, font_scale, (0, 0, 255), thickness+(2), cv2.LINE_AA)
1193
+ cv2.putText(new_outlines, text, (text_x, text_y_outlines), font, font_scale, (255, 255, 255), thickness-(1), cv2.LINE_AA)
1194
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1195
 
1196
  outlines_color = cv2.cvtColor(new_outlines, cv2.COLOR_BGR2RGB)
1197
  print("Total prediction time: {:.2f} seconds".format(time.time() - overall_start))
 
1227
  gr.Textbox(label="Annotation (max 20 chars)", max_length=20, placeholder="Type up to 20 characters")
1228
  ],
1229
  outputs=[
1230
+ gr.Image(format="png",label="Output Image"),
1231
+ gr.Image(format="png",label="Outlines of Objects"),
1232
  gr.File(label="DXF file"),
1233
  gr.Image(label="Mask"),
1234
  gr.Textbox(label="Scaling Factor (inches/pixel)")