kreemyyyy commited on
Commit
a77b32c
·
verified ·
1 Parent(s): 68398ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -75
app.py CHANGED
@@ -8,8 +8,7 @@ import os
8
  from math import atan2, degrees
9
  import asyncio
10
  from pyppeteer import launch
11
- import nest_asyncio
12
- nest_asyncio.apply()
13
 
14
  # Configure logging
15
  logging.basicConfig(
@@ -25,67 +24,66 @@ logging.basicConfig(
25
  ROBOFLOW_API_KEY = "KUP9w62eUcD5PrrRMJsV" # Replace with your API key
26
  PROJECT_NAME = "model_verification_project"
27
  VERSION_NUMBER = 2
28
- # FONT_PATH is no longer used since we generate handwriting via Calligraphr
29
- # FONT_PATH = "./STEVEHANDWRITING-REGULAR.TTF"
30
 
31
  # ----------------------------
32
- # Pyppeteer: Generate handwriting image via Calligraphr
33
  # ----------------------------
34
- async def generate_handwriting_text_image(text_prompt, screenshot_path):
35
- browser = await launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox'])
36
- page = await browser.newPage()
37
-
38
- # Navigate to Calligraphr (adjust URL if needed)
39
- await page.goto('https://www.calligraphr.com/en/font/', {'waitUntil': 'networkidle2'})
40
-
41
- # Wait for the text input to be available and type the text
42
- await page.waitForSelector('#text-input')
43
- await page.type('#text-input', text_prompt)
44
-
45
- # Wait for the page to render the handwriting preview
46
- await asyncio.sleep(2)
47
-
48
- # Take a screenshot of the area containing the rendered handwriting text.
49
- # (Adjust the clip values if needed to capture the correct area.)
50
- await page.screenshot({
51
- 'path': screenshot_path,
52
- 'clip': {'x': 100, 'y': 200, 'width': 600, 'height': 150}
53
- })
54
-
55
- await browser.close()
56
- logging.debug(f"Calligraphr screenshot saved at {screenshot_path}")
57
- return screenshot_path
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  # ----------------------------
60
  # Helper: Detect paper angle within bounding box
61
  # ----------------------------
62
  def detect_paper_angle(image, bounding_box):
63
  x1, y1, x2, y2 = bounding_box
64
-
65
- # Crop the region of interest (ROI) based on the bounding box
66
  roi = np.array(image)[y1:y2, x1:x2]
67
-
68
- # Convert ROI to grayscale
69
  gray = cv2.cvtColor(roi, cv2.COLOR_RGBA2GRAY)
70
-
71
- # Apply edge detection
72
  edges = cv2.Canny(gray, 50, 150)
73
-
74
- # Detect lines using Hough Line Transformation
75
  lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=50, maxLineGap=10)
76
-
77
  if lines is not None:
78
- # Find the longest line (most prominent edge)
79
  longest_line = max(lines, key=lambda line: np.linalg.norm((line[0][2] - line[0][0], line[0][3] - line[0][1])))
80
  x1_line, y1_line, x2_line, y2_line = longest_line[0]
81
-
82
- # Calculate the angle of the line relative to the horizontal axis
83
  dx = x2_line - x1_line
84
  dy = y2_line - y1_line
85
  angle = degrees(atan2(dy, dx))
86
- return angle # Angle of the paper
87
  else:
88
- return 0 # Default to no rotation if no lines are found
89
 
90
  # ----------------------------
91
  # Main processing function
@@ -110,62 +108,44 @@ def process_image(image, text):
110
  prediction = model.predict(input_image_path, confidence=70, overlap=50).json()
111
  logging.debug(f"Inference result: {prediction}")
112
 
113
- # Open the image for processing
114
  pil_image = image.convert("RGBA")
115
  logging.debug("Converted image to RGBA mode.")
116
 
117
- # Iterate over detected objects (assumed white papers)
118
  for obj in prediction['predictions']:
119
- # Use white paper dimensions from the prediction
120
  white_paper_width = obj['width']
121
  white_paper_height = obj['height']
122
-
123
- # Set padding (adjust percentages as needed)
124
  padding_x = int(white_paper_width * 0.1)
125
  padding_y = int(white_paper_height * 0.1)
126
-
127
  box_width = white_paper_width - 2 * padding_x
128
  box_height = white_paper_height - 2 * padding_y
129
  logging.debug(f"Padded white paper dimensions: width={box_width}, height={box_height}.")
130
 
131
- # Calculate padded coordinates
132
  x1_padded = int(obj['x'] - white_paper_width / 2 + padding_x)
133
  y1_padded = int(obj['y'] - white_paper_height / 2 + padding_y)
134
  x2_padded = int(obj['x'] + white_paper_width / 2 - padding_x)
135
  y2_padded = int(obj['y'] + white_paper_height / 2 - padding_y)
136
 
137
- # Detect paper angle
138
  angle = detect_paper_angle(np.array(image), (x1_padded, y1_padded, x2_padded, y2_padded))
139
  logging.debug(f"Detected paper angle: {angle} degrees.")
140
 
141
- # For debugging: draw the bounding box (optional)
142
  debug_layer = pil_image.copy()
143
  debug_draw = ImageDraw.Draw(debug_layer)
144
  debug_draw.rectangle([(x1_padded, y1_padded), (x2_padded, y2_padded)], outline="red", width=3)
145
  debug_layer.save("/tmp/debug_bounding_box.png")
146
  logging.debug("Saved bounding box debug image to /tmp/debug_bounding_box.png.")
147
 
148
- # --------------------------------------------
149
- # New: Generate handwriting image via Calligraphr
150
- # --------------------------------------------
151
- handwriting_path = "/tmp/handwriting.png"
152
- try:
153
- # Run the async Pyppeteer function to generate handwriting
154
- handwriting_path = asyncio.run(generate_handwriting_text_image(text, handwriting_path))
155
- except Exception as e:
156
- logging.error(f"Error generating handwriting image: {e}")
157
- continue # Optionally, you could fall back to another method here
158
-
159
- # Open the generated handwriting image
160
  handwriting_img = Image.open(handwriting_path).convert("RGBA")
161
- # Resize handwriting image to fit the white paper box
162
  handwriting_img = handwriting_img.resize((box_width, box_height), Image.ANTIALIAS)
163
-
164
- # Rotate the handwriting image to align with the detected paper angle
165
  rotated_handwriting = handwriting_img.rotate(-angle, resample=Image.BICUBIC, expand=True)
166
 
167
- # Composite the rotated handwriting image onto a transparent layer,
168
- # then overlay it on the original image
169
  text_layer = Image.new("RGBA", pil_image.size, (255, 255, 255, 0))
170
  paste_x = int(obj['x'] - rotated_handwriting.size[0] / 2)
171
  paste_y = int(obj['y'] - rotated_handwriting.size[1] / 2)
@@ -173,7 +153,6 @@ def process_image(image, text):
173
  pil_image = Image.alpha_composite(pil_image, text_layer)
174
  logging.debug("Handwriting layer composited onto the original image.")
175
 
176
- # Save and return output image path
177
  output_image_path = "/tmp/output_image.png"
178
  pil_image.convert("RGB").save(output_image_path)
179
  logging.debug(f"Output image saved to {output_image_path}.")
@@ -205,16 +184,15 @@ interface = gr.Interface(
205
  gr.Textbox(label="Enter Text to Overlay")
206
  ],
207
  outputs=[
208
- gr.Image(label="Processed Image Preview"), # Preview processed image
209
- gr.File(label="Download Processed Image"), # Download the image
210
- gr.Textbox(label="Status") # Status message
211
  ],
212
  title="Roboflow Detection with Handwriting Overlay",
213
- description="Upload an image, enter text to overlay. The Roboflow model detects the white paper area, and a handwriting image is generated via Calligraphr using Pyppeteer. The output image is composited accordingly.",
214
  allow_flagging="never"
215
  )
216
 
217
- # Launch the Gradio app
218
  if __name__ == "__main__":
219
  logging.debug("Launching Gradio interface.")
220
  interface.launch(share=True)
 
8
  from math import atan2, degrees
9
  import asyncio
10
  from pyppeteer import launch
11
+ import multiprocessing
 
12
 
13
  # Configure logging
14
  logging.basicConfig(
 
24
  ROBOFLOW_API_KEY = "KUP9w62eUcD5PrrRMJsV" # Replace with your API key
25
  PROJECT_NAME = "model_verification_project"
26
  VERSION_NUMBER = 2
 
 
27
 
28
  # ----------------------------
29
+ # New: Run Pyppeteer code in a separate process
30
  # ----------------------------
31
+ def generate_handwriting_image_process(text_prompt, screenshot_path, return_dict):
32
+ """
33
+ This function runs in a separate process so that the Pyppeteer code
34
+ runs in the main thread of that process.
35
+ """
36
+ import asyncio
37
+ from pyppeteer import launch
38
+
39
+ async def _generate():
40
+ browser = await launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox'])
41
+ page = await browser.newPage()
42
+ await page.goto('https://www.calligraphr.com/en/font/', {'waitUntil': 'networkidle2'})
43
+ await page.waitForSelector('#text-input')
44
+ await page.type('#text-input', text_prompt)
45
+ await asyncio.sleep(2) # Wait for the handwriting preview to render
46
+
47
+ # Adjust these clip dimensions as needed for the correct area
48
+ await page.screenshot({
49
+ 'path': screenshot_path,
50
+ 'clip': {'x': 100, 'y': 200, 'width': 600, 'height': 150}
51
+ })
52
+ await browser.close()
53
+ return screenshot_path
54
+
55
+ # Create a new event loop for this process
56
+ loop = asyncio.new_event_loop()
57
+ asyncio.set_event_loop(loop)
58
+ result = loop.run_until_complete(_generate())
59
+ return_dict['result'] = result
60
+
61
+ def get_handwriting_image(text_prompt, screenshot_path="/tmp/handwriting.png"):
62
+ manager = multiprocessing.Manager()
63
+ return_dict = manager.dict()
64
+ process = multiprocessing.Process(target=generate_handwriting_image_process, args=(text_prompt, screenshot_path, return_dict))
65
+ process.start()
66
+ process.join()
67
+ return return_dict.get('result', None)
68
 
69
  # ----------------------------
70
  # Helper: Detect paper angle within bounding box
71
  # ----------------------------
72
  def detect_paper_angle(image, bounding_box):
73
  x1, y1, x2, y2 = bounding_box
 
 
74
  roi = np.array(image)[y1:y2, x1:x2]
 
 
75
  gray = cv2.cvtColor(roi, cv2.COLOR_RGBA2GRAY)
 
 
76
  edges = cv2.Canny(gray, 50, 150)
 
 
77
  lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=50, maxLineGap=10)
 
78
  if lines is not None:
 
79
  longest_line = max(lines, key=lambda line: np.linalg.norm((line[0][2] - line[0][0], line[0][3] - line[0][1])))
80
  x1_line, y1_line, x2_line, y2_line = longest_line[0]
 
 
81
  dx = x2_line - x1_line
82
  dy = y2_line - y1_line
83
  angle = degrees(atan2(dy, dx))
84
+ return angle
85
  else:
86
+ return 0
87
 
88
  # ----------------------------
89
  # Main processing function
 
108
  prediction = model.predict(input_image_path, confidence=70, overlap=50).json()
109
  logging.debug(f"Inference result: {prediction}")
110
 
 
111
  pil_image = image.convert("RGBA")
112
  logging.debug("Converted image to RGBA mode.")
113
 
114
+ # Process each detected object (assumed to be white paper)
115
  for obj in prediction['predictions']:
 
116
  white_paper_width = obj['width']
117
  white_paper_height = obj['height']
 
 
118
  padding_x = int(white_paper_width * 0.1)
119
  padding_y = int(white_paper_height * 0.1)
 
120
  box_width = white_paper_width - 2 * padding_x
121
  box_height = white_paper_height - 2 * padding_y
122
  logging.debug(f"Padded white paper dimensions: width={box_width}, height={box_height}.")
123
 
 
124
  x1_padded = int(obj['x'] - white_paper_width / 2 + padding_x)
125
  y1_padded = int(obj['y'] - white_paper_height / 2 + padding_y)
126
  x2_padded = int(obj['x'] + white_paper_width / 2 - padding_x)
127
  y2_padded = int(obj['y'] + white_paper_height / 2 - padding_y)
128
 
 
129
  angle = detect_paper_angle(np.array(image), (x1_padded, y1_padded, x2_padded, y2_padded))
130
  logging.debug(f"Detected paper angle: {angle} degrees.")
131
 
132
+ # For debugging: draw bounding box (optional)
133
  debug_layer = pil_image.copy()
134
  debug_draw = ImageDraw.Draw(debug_layer)
135
  debug_draw.rectangle([(x1_padded, y1_padded), (x2_padded, y2_padded)], outline="red", width=3)
136
  debug_layer.save("/tmp/debug_bounding_box.png")
137
  logging.debug("Saved bounding box debug image to /tmp/debug_bounding_box.png.")
138
 
139
+ # Generate handwriting image using the separate process
140
+ handwriting_path = get_handwriting_image(text, "/tmp/handwriting.png")
141
+ if not handwriting_path:
142
+ logging.error("Handwriting image generation failed.")
143
+ continue
144
+
 
 
 
 
 
 
145
  handwriting_img = Image.open(handwriting_path).convert("RGBA")
 
146
  handwriting_img = handwriting_img.resize((box_width, box_height), Image.ANTIALIAS)
 
 
147
  rotated_handwriting = handwriting_img.rotate(-angle, resample=Image.BICUBIC, expand=True)
148
 
 
 
149
  text_layer = Image.new("RGBA", pil_image.size, (255, 255, 255, 0))
150
  paste_x = int(obj['x'] - rotated_handwriting.size[0] / 2)
151
  paste_y = int(obj['y'] - rotated_handwriting.size[1] / 2)
 
153
  pil_image = Image.alpha_composite(pil_image, text_layer)
154
  logging.debug("Handwriting layer composited onto the original image.")
155
 
 
156
  output_image_path = "/tmp/output_image.png"
157
  pil_image.convert("RGB").save(output_image_path)
158
  logging.debug(f"Output image saved to {output_image_path}.")
 
184
  gr.Textbox(label="Enter Text to Overlay")
185
  ],
186
  outputs=[
187
+ gr.Image(label="Processed Image Preview"),
188
+ gr.File(label="Download Processed Image"),
189
+ gr.Textbox(label="Status")
190
  ],
191
  title="Roboflow Detection with Handwriting Overlay",
192
+ description="Upload an image and enter text to overlay. The Roboflow model detects the white paper area, and a handwriting image is generated via Calligraphr using Pyppeteer. The output image is composited accordingly.",
193
  allow_flagging="never"
194
  )
195
 
 
196
  if __name__ == "__main__":
197
  logging.debug("Launching Gradio interface.")
198
  interface.launch(share=True)